From 70288f1b8a2f27fba440ae02bef583972045bb65 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 26 Mar 2021 18:43:18 -0700 Subject: [PATCH 001/798] Write generated files during tests to CMake's build directory using the name of the test. Co-authored-by: Vladislav Shchapov --- CMakeLists.txt | 19 ++++++++---- cmake/detect-arch.cmake | 2 +- cmake/test-compress.cmake | 63 ++++++++++++++++++++------------------- 3 files changed, 47 insertions(+), 37 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2376cfc87e..686c0f15bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1081,7 +1081,7 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME makefixed COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKEFIXED_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/inffixed_tbl._h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/inffixed_tbl._h -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/inffixed_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -1093,7 +1093,7 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME maketrees COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKETREES_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/trees_tbl._h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/trees_tbl._h -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/trees_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -1105,7 +1105,7 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME makecrct-crc32 COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/crc32_tbl._h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/crc32_tbl._h -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -1114,7 +1114,7 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME makecrct-crc32-combine COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/crc32_comb_tbl._h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/crc32_comb_tbl._h -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_comb_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -1152,7 +1152,7 @@ if(ZLIB_ENABLE_TESTS) "-DCOMPRESS_ARGS=${compress_args}" "-DDECOMPRESS_ARGS=-d;-c" -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${path} - -DOUTPUT=${CMAKE_CURRENT_SOURCE_DIR}/${path}-${test_id}.gz + -DTEST_NAME=${test_id} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) endif() endmacro() @@ -1181,7 +1181,7 @@ if(ZLIB_ENABLE_TESTS) continue() endif() foreach(TEST_CONFIG ${TEST_CONFIGS}) - get_filename_component(TEST_NAME ${TEST_FILE_PATH} NAME_WE) + get_filename_component(TEST_NAME ${TEST_FILE_PATH} NAME) if (TEST_NAME STREQUAL "") continue() endif() @@ -1214,6 +1214,7 @@ if(ZLIB_ENABLE_TESTS) COMMAND ${CMAKE_COMMAND} "-DTARGET=${MINIGZIP_COMMAND}" "-DCOMPRESS_ARGS=-c;-k;-4" + -DTEST_NAME=GH-361-test-txt -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-361/test.txt -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) @@ -1222,6 +1223,7 @@ if(ZLIB_ENABLE_TESTS) "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" "-DCOMPRESS_ARGS=1;5;9;3" "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" + -DTEST_NAME=GH-364-test-bin -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-364/test.bin -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) @@ -1231,6 +1233,7 @@ if(ZLIB_ENABLE_TESTS) "-DCOMPRESS_ARGS=-c;-m;1;-w;-15;-1;-s;4" "-DDECOMPRESS_ARGS=-c;-d;-m;1;-w;-15" -DGZIP_VERIFY=OFF + -DTEST_NAME=GH-382-defneg3-dat -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-382/defneg3.dat -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) @@ -1241,6 +1244,7 @@ if(ZLIB_ENABLE_TESTS) "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" -DCOMPARE=OFF -DGZIP_VERIFY=OFF + -DTEST_NAME=GH-536-segfault-lcet10-txt -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) @@ -1251,6 +1255,7 @@ if(ZLIB_ENABLE_TESTS) "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" -DCOMPARE=OFF -DGZIP_VERIFY=OFF + -DTEST_NAME=GH-536-incomplete-read-lcet10-txt -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) @@ -1261,12 +1266,14 @@ if(ZLIB_ENABLE_TESTS) "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" -DCOMPARE=OFF -DGZIP_VERIFY=OFF + -DTEST_NAME=GH-536-zero-stored-block-lcet10-txt -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) add_test(NAME GH-751 COMMAND ${CMAKE_COMMAND} "-DTARGET=${MINIGZIP_COMMAND}" + -DTEST_NAME=GH-751-test-txt -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-751/test.txt -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) diff --git a/cmake/detect-arch.cmake b/cmake/detect-arch.cmake index b80d6666f2..69475da38d 100644 --- a/cmake/detect-arch.cmake +++ b/cmake/detect-arch.cmake @@ -24,7 +24,7 @@ else() try_run( run_result_unused compile_result_unused - ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/detect-arch.c COMPILE_OUTPUT_VARIABLE RAWOUTPUT CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} diff --git a/cmake/test-compress.cmake b/cmake/test-compress.cmake index 833aa3fc0e..e5b1f3b471 100644 --- a/cmake/test-compress.cmake +++ b/cmake/test-compress.cmake @@ -15,6 +15,7 @@ # DECOMPRESS_TARGET - Command to run to decompress output file # Optional Variables +# TEST_NAME - Name of test to use when constructing output file paths # COMPRESS_ARGS - Arguments to pass for compress command (default: -c -k) # DECOMPRESS_ARGS - Arguments to pass to decompress command (default: -d -c) @@ -49,23 +50,25 @@ if(NOT DEFINED SUCCESS_EXIT) set(SUCCESS_EXIT 0) endif() -# Generate unique output path so multiple tests can be executed at the same time -if(NOT OUTPUT) - # Output name based on input and unique id - string(RANDOM UNIQUE_ID) - set(OUTPUT ${INPUT}-${UNIQUE_ID}) -else() - # Output name appends unique id in case multiple tests with same output name - string(RANDOM LENGTH 6 UNIQUE_ID) - set(OUTPUT ${OUTPUT}-${UNIQUE_ID}) +# Use test name from input file name +if(NOT DEFINED TEST_NAME) + get_filename_component(TEST_NAME "${INPUT}" NAME) endif() -string(REPLACE ".gz" "" OUTPUT "${OUTPUT}") + +# Generate unique output path so multiple tests can be executed at the same time +string(RANDOM LENGTH 6 UNIQUE_ID) +string(REPLACE "." "-" TEST_NAME "${TEST_NAME}") +set(OUTPUT_BASE "${CMAKE_CURRENT_BINARY_DIR}/test/${TEST_NAME}-${UNIQUE_ID}") + +# Ensure directory exists for output files +get_filename_component(OUTPUT_DIR "${OUTPUT_BASE}" DIRECTORY) +file(MAKE_DIRECTORY "${OUTPUT_DIR}") macro(cleanup) # Cleanup temporary mingizip files - file(REMOVE ${OUTPUT}.gz ${OUTPUT}.out) + file(REMOVE ${OUTPUT_BASE}.gz ${OUTPUT_BASE}.out) # Cleanup temporary gzip files - file(REMOVE ${OUTPUT}.gzip.gz ${OUTPUT}.gzip.out) + file(REMOVE ${OUTPUT_BASE}.gzip.gz ${OUTPUT_BASE}.gzip.out) endmacro() # Compress input file @@ -78,7 +81,7 @@ set(COMPRESS_COMMAND ${COMPRESS_TARGET} ${COMPRESS_ARGS}) execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${COMPRESS_COMMAND}" -DINPUT=${INPUT} - -DOUTPUT=${OUTPUT}.gz + -DOUTPUT=${OUTPUT_BASE}.gz "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -89,17 +92,17 @@ if(CMD_RESULT) endif() # Decompress output -if(NOT EXISTS ${OUTPUT}.gz) +if(NOT EXISTS ${OUTPUT_BASE}.gz) cleanup() - message(FATAL_ERROR "Cannot find decompress input: ${OUTPUT}.gz") + message(FATAL_ERROR "Cannot find decompress input: ${OUTPUT_BASE}.gz") endif() set(DECOMPRESS_COMMAND ${DECOMPRESS_TARGET} ${DECOMPRESS_ARGS}) execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT}.gz - -DOUTPUT=${OUTPUT}.out + -DINPUT=${OUTPUT_BASE}.gz + -DOUTPUT=${OUTPUT_BASE}.out "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -112,7 +115,7 @@ endif() if(COMPARE) # Compare decompressed output with original input file execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT}.out + -E compare_files ${INPUT} ${OUTPUT_BASE}.out RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) @@ -125,9 +128,9 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") # Transparent writing does not use gzip format find_program(GZIP gzip) if(GZIP) - if(NOT EXISTS ${OUTPUT}.gz) + if(NOT EXISTS ${OUTPUT_BASE}.gz) cleanup() - message(FATAL_ERROR "Cannot find gzip decompress input: ${OUTPUT}.gz") + message(FATAL_ERROR "Cannot find gzip decompress input: ${OUTPUT_BASE}.gz") endif() # Check gzip can decompress our compressed output @@ -135,8 +138,8 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${GZ_DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT}.gz - -DOUTPUT=${OUTPUT}.gzip.out + -DINPUT=${OUTPUT_BASE}.gz + -DOUTPUT=${OUTPUT_BASE}.gzip.out "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -148,7 +151,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") # Compare gzip output with original input file execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT}.gzip.out + -E compare_files ${INPUT} ${OUTPUT_BASE}.gzip.out RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) @@ -156,7 +159,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") message(FATAL_ERROR "Compare gzip decompress failed: ${CMD_RESULT}") endif() - if(NOT EXISTS ${OUTPUT}.gz) + if(NOT EXISTS ${OUTPUT_BASE}.gz) cleanup() message(FATAL_ERROR "Cannot find gzip compress input: ${INPUT}") endif() @@ -167,7 +170,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${GZ_COMPRESS_COMMAND}" -DINPUT=${INPUT} - -DOUTPUT=${OUTPUT}.gzip.gz + -DOUTPUT=${OUTPUT_BASE}.gzip.gz "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -177,16 +180,16 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") message(FATAL_ERROR "Gzip compress failed: ${CMD_RESULT}") endif() - if(NOT EXISTS ${OUTPUT}.gz) + if(NOT EXISTS ${OUTPUT_BASE}.gz) cleanup() - message(FATAL_ERROR "Cannot find minigzip decompress input: ${OUTPUT}.gzip.gz") + message(FATAL_ERROR "Cannot find minigzip decompress input: ${OUTPUT_BASE}.gzip.gz") endif() # Check decompress target can handle gzip compressed output execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT}.gzip.gz - -DOUTPUT=${OUTPUT}.gzip.out + -DINPUT=${OUTPUT_BASE}.gzip.gz + -DOUTPUT=${OUTPUT_BASE}.gzip.out "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -199,7 +202,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") if(COMPARE) # Compare original input file with gzip decompressed output execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT}.gzip.out + -E compare_files ${INPUT} ${OUTPUT_BASE}.gzip.out RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) From deda158428676929b7b3f9233eed2cbe1498769b Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sat, 10 Apr 2021 03:13:33 +0300 Subject: [PATCH 002/798] [ARM] Use temporary variable when loading more than 8 bits in chunkmemset_neon(). * using memcpy() forbids optimizer to optimize away the temporary variable due to aliasing rules. --- arch/arm/chunkset_neon.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index e9cbcb1bab..b153298275 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -23,11 +23,15 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { } static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { - *chunk = vreinterpretq_u8_s16(vdupq_n_s16(*(int16_t *)from)); + int16_t tmp; + memcpy(&tmp, from, 2); + *chunk = vreinterpretq_u8_s16(vdupq_n_s16(tmp)); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { - *chunk = vreinterpretq_u8_s32(vdupq_n_s32(*(int32_t *)from)); + int32_t tmp; + memcpy(&tmp, from, 4); + *chunk = vreinterpretq_u8_s32(vdupq_n_s32(tmp)); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { From f03918fa94a0f046e15632c861ad0c9867ce3943 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 26 Mar 2021 17:50:28 -0700 Subject: [PATCH 003/798] Remove unnecessary malloc.h header include from minigzip and minigzip_fuzzer. --- test/fuzz/minigzip_fuzzer.c | 4 ---- test/minigzip.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/test/fuzz/minigzip_fuzzer.c b/test/fuzz/minigzip_fuzzer.c index 1f19126f44..57e8588882 100644 --- a/test/fuzz/minigzip_fuzzer.c +++ b/test/fuzz/minigzip_fuzzer.c @@ -32,10 +32,6 @@ # include #endif -#ifndef UNALIGNED_OK -# include -#endif - #if defined(_WIN32) || defined(__CYGWIN__) # include # include diff --git a/test/minigzip.c b/test/minigzip.c index 2e4ef8e2a5..29729f3894 100644 --- a/test/minigzip.c +++ b/test/minigzip.c @@ -32,10 +32,6 @@ # include #endif -#ifndef UNALIGNED_OK -# include -#endif - #if defined(_WIN32) || defined(__CYGWIN__) # include # include From 461c2796c262885593a40ae1acd2c195b300adc7 Mon Sep 17 00:00:00 2001 From: Victor Westerhuis Date: Sun, 25 Apr 2021 00:55:10 +0200 Subject: [PATCH 004/798] Fix build with LTO on GCC --- CMakeLists.txt | 27 ++++++++++++++++++--------- arch/arm/Makefile.in | 24 +++++++++++++----------- arch/power/Makefile.in | 13 +++++++------ arch/x86/Makefile.in | 41 +++++++++++++++++++++-------------------- configure | 20 ++++++++++++++++++-- 5 files changed, 77 insertions(+), 48 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 686c0f15bb..56b4a839c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -253,6 +253,15 @@ else() set(SSE4FLAG "-msse4") set(PCLMULFLAG "-mpclmul") endif() + # Check whether -fno-lto is available + set(CMAKE_REQUIRED_FLAGS "-fno-lto") + check_c_source_compiles( + "int main() { return 0; }" + FNO_LTO_AVAILABLE FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) + if(FNO_LTO_AVAILABLE) + set(NOLTOFLAG "-fno-lto") + endif() endif() endif() endif() @@ -645,7 +654,7 @@ if(WITH_OPTIM) if(WITH_ACLE AND NOT MSVC) add_definitions(-DARM_ACLE_CRC_HASH) set(ACLE_SRCS ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c) - set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG}") + set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG} ${NOLTOFLAG}") list(APPEND ZLIB_ARCH_SRCS ${ACLE_SRCS}) add_feature_info(ACLE_CRC 1 "Support ACLE optimized CRC hash generation, using \"${ACLEFLAG}\"") endif() @@ -653,7 +662,7 @@ if(WITH_OPTIM) add_definitions(-DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_neon.c) list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) - set_property(SOURCE ${NEON_SRCS} PROPERTY COMPILE_FLAGS "${NEONFLAG}") + set_property(SOURCE ${NEON_SRCS} PROPERTY COMPILE_FLAGS "${NEONFLAG} ${NOLTOFLAG}") if(MSVC) add_definitions(-D__ARM_NEON__) endif() @@ -670,7 +679,7 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/slide_hash_power8.c) list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) - set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG}") + set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") endif() elseif(BASEARCH_S360_FOUND) if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) @@ -703,14 +712,14 @@ if(WITH_OPTIM) list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx.c) add_feature_info(AVX2_ADLER32 1 "Support AVX2-accelerated adler32, using \"${AVX2FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) - set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG}") + set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG} ${NOLTOFLAG}") endif() if(WITH_SSE4 AND (HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN)) add_definitions(-DX86_SSE42_CRC_HASH) set(SSE42_SRCS ${ARCHDIR}/insert_string_sse.c) add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE4FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG}") + set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") if(HAVE_SSE42CRC_INTRIN) add_definitions(-DX86_SSE42_CRC_INTRIN) endif() @@ -720,14 +729,14 @@ if(WITH_OPTIM) set(SSE42_SRCS ${ARCHDIR}/compare258_sse.c) add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE4FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG}") + set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") endif() if(WITH_SSE2 AND HAVE_SSE2_INTRIN) add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) set(SSE2_SRCS ${ARCHDIR}/chunkset_sse.c ${ARCHDIR}/slide_sse.c) list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) if(NOT ${ARCH} MATCHES "x86_64") - set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG}") + set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG} ${NOLTOFLAG}") add_feature_info(FORCE_SSE2 FORCE_SSE2 "Assume CPU is SSE2 capable") if(FORCE_SSE2) add_definitions(-DX86_NOCHECK_SSE2) @@ -739,14 +748,14 @@ if(WITH_OPTIM) set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c) add_feature_info(SSSE3_ADLER32 1 "Support SSSE3-accelerated adler32, using \"${SSSE3FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) - set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG}") + set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${NOLTOFLAG}") endif() if(WITH_PCLMULQDQ AND HAVE_PCLMULQDQ_INTRIN AND WITH_SSSE3 AND WITH_SSE4) add_definitions(-DX86_PCLMULQDQ_CRC) set(PCLMULQDQ_SRCS ${ARCHDIR}/crc_folding.c) add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) - set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}") + set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") endif() endif() endif() diff --git a/arch/arm/Makefile.in b/arch/arm/Makefile.in index a728d5ab24..d383ba0853 100644 --- a/arch/arm/Makefile.in +++ b/arch/arm/Makefile.in @@ -6,9 +6,11 @@ CC= CFLAGS= SFLAGS= INCLUDES= +SUFFIX= + ACLEFLAG= NEONFLAG= -SUFFIX= +NOLTOFLAG= SRCDIR=. SRCTOP=../.. @@ -23,10 +25,10 @@ all: \ insert_string_acle.o insert_string_acle.lo adler32_neon.o: - $(CC) $(CFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c adler32_neon.lo: - $(CC) $(SFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c armfeature.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c @@ -35,28 +37,28 @@ armfeature.lo: $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c chunkset_neon.o: - $(CC) $(CFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c chunkset_neon.lo: - $(CC) $(SFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c crc32_acle.o: - $(CC) $(CFLAGS) $(ACLEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c + $(CC) $(CFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c crc32_acle.lo: - $(CC) $(SFLAGS) $(ACLEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c + $(CC) $(SFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c slide_neon.o: - $(CC) $(CFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_neon.c + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_neon.c slide_neon.lo: - $(CC) $(SFLAGS) $(NEONFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_neon.c + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_neon.c insert_string_acle.o: - $(CC) $(CFLAGS) $(ACLEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c + $(CC) $(CFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c insert_string_acle.lo: - $(CC) $(SFLAGS) $(ACLEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c + $(CC) $(SFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c mostlyclean: clean clean: diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index 25ebc9d1d5..cf5839b934 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -8,12 +8,13 @@ SFLAGS= INCLUDES= SUFFIX= +P8FLAGS=-mcpu=power8 +NOLTOFLAG= + SRCDIR=. SRCTOP=../.. TOPDIR=$(SRCTOP) -P8FLAGS=-mcpu=power8 - all: power.o \ power.lo \ adler32_power8.o \ @@ -28,16 +29,16 @@ power.lo: $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power.c adler32_power8.o: - $(CC) $(CFLAGS) $(P8FLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c adler32_power8.lo: - $(CC) $(SFLAGS) $(P8FLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c slide_hash_power8.o: - $(CC) $(CFLAGS) $(P8FLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c slide_hash_power8.lo: - $(CC) $(SFLAGS) $(P8FLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c mostlyclean: clean clean: diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 4f6594e6df..13c736c632 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -13,6 +13,7 @@ SSE2FLAG=-msse2 SSSE3FLAG=-mssse3 SSE4FLAG=-msse4 PCLMULFLAG=-mpclmul +NOLTOFLAG= SRCDIR=. SRCTOP=../.. @@ -38,64 +39,64 @@ x86.lo: $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c chunkset_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c chunkset_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c chunkset_sse.o: - $(CC) $(CFLAGS) $(SSE2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse.c + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse.c chunkset_sse.lo: - $(CC) $(SFLAGS) $(SSE2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse.c + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse.c compare258_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c compare258_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c compare258_sse.o: - $(CC) $(CFLAGS) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c + $(CC) $(CFLAGS) $(SSE4FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c compare258_sse.lo: - $(CC) $(SFLAGS) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c + $(CC) $(SFLAGS) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c insert_string_sse.o: - $(CC) $(CFLAGS) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c + $(CC) $(CFLAGS) $(SSE4FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c insert_string_sse.lo: - $(CC) $(SFLAGS) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c + $(CC) $(SFLAGS) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c crc_folding.o: - $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c + $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c crc_folding.lo: - $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE4FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c + $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c slide_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_avx.c + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_avx.c slide_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_avx.c + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_avx.c slide_sse.o: - $(CC) $(CFLAGS) $(SSE2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_sse.c + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_sse.c slide_sse.lo: - $(CC) $(SFLAGS) $(SSE2FLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_sse.c + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_sse.c adler32_avx.o: $(SRCDIR)/adler32_avx.c - $(CC) $(CFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c adler32_avx.lo: $(SRCDIR)/adler32_avx.c - $(CC) $(SFLAGS) $(AVX2FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c adler32_ssse3.o: $(SRCDIR)/adler32_ssse3.c - $(CC) $(CFLAGS) $(SSSE3FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c + $(CC) $(CFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c adler32_ssse3.lo: $(SRCDIR)/adler32_ssse3.c - $(CC) $(SFLAGS) $(SSSE3FLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c + $(CC) $(SFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c mostlyclean: clean clean: diff --git a/configure b/configure index d1a44db50b..aafaa06ac5 100755 --- a/configure +++ b/configure @@ -109,6 +109,7 @@ sse42flag="-msse4.2" pclmulflag="-mpclmul" acleflag= neonflag= +noltoflag="-fno-lto" without_optimizations=0 without_new_strategies=0 gcc=0 @@ -239,6 +240,7 @@ if test $native -eq 1; then sse4flag="" sse42flag="" pclmulflag="" + noltoflag="" fi if test $build32 -eq 1; then @@ -871,10 +873,23 @@ echo "" > test.c int main() { return 0; } EOF if test "$gcc" -eq 1 && ($cc $CFLAGS -fno-semantic-interposition -c $test.c) >> configure.log 2>&1; then - echo "Checking for -no-semantic-interposition... Yes." | tee -a configure.log + echo "Checking for -fno-semantic-interposition... Yes." | tee -a configure.log SFLAGS="$SFLAGS -fno-semantic-interposition" else - echo "Checking for -no-semantic-interposition... No." | tee -a configure.log + echo "Checking for -fno-semantic-interposition... No." | tee -a configure.log +fi + +# Check for -fno-lto compiler support +if test $gcc -eq 1 -a $without_optimizations -eq 0 -a $native -eq 0; then + cat > $test.c <> configure.log 2>&1; then + echo "Checking for -fno-lto... Yes." | tee -a configure.log + else + echo "Checking for -fno-lto... No." | tee -a configure.log + noltoflag="" + fi fi # see if we can hide zlib internal symbols that are linked between separate source files using hidden @@ -1659,6 +1674,7 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^PCLMULFLAG *=/s#=.*#=$pclmulflag# /^ACLEFLAG *=/s#=.*#=$acleflag# /^NEONFLAG *=/s#=.*#=$neonflag# +/^NOLTOFLAG *=/s#=.*#=$noltoflag# " > $ARCHDIR/Makefile # Append header files dependences. From 29fd4672a2279a0368be936d7cd44d013d009fae Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 24 Apr 2021 23:58:35 +0200 Subject: [PATCH 005/798] Fix cmake coverage detection requiring cmake 3.14 or newer. --- cmake/detect-coverage.cmake | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cmake/detect-coverage.cmake b/cmake/detect-coverage.cmake index dc51404475..96478f6771 100644 --- a/cmake/detect-coverage.cmake +++ b/cmake/detect-coverage.cmake @@ -3,8 +3,13 @@ macro(add_code_coverage) # Check for -coverage flag support for Clang/GCC - set(CMAKE_REQUIRED_LINK_OPTIONS -coverage) + if(CMAKE_VERSION VERSION_LESS 3.14) + set(CMAKE_REQUIRED_LIBRARIES -lgcov) + else() + set(CMAKE_REQUIRED_LINK_OPTIONS -coverage) + endif() check_c_compiler_flag(-coverage HAVE_COVERAGE) + set(CMAKE_REQUIRED_LIBRARIES) set(CMAKE_REQUIRED_LINK_OPTIONS) if(HAVE_COVERAGE) @@ -13,8 +18,13 @@ macro(add_code_coverage) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -coverage") else() # Some versions of GCC don't support -coverage shorthand - set(CMAKE_REQUIRED_LINK_OPTIONS -lgcov -fprofile-arcs) + if(CMAKE_VERSION VERSION_LESS 3.14) + set(CMAKE_REQUIRED_LIBRARIES -lgcov) + else() + set(CMAKE_REQUIRED_LINK_OPTIONS -lgcov -fprofile-arcs) + endif() check_c_compiler_flag("-ftest-coverage -fprofile-arcs -fprofile-values" HAVE_TEST_COVERAGE) + set(CMAKE_REQUIRED_LIBRARIES) set(CMAKE_REQUIRED_LINK_OPTIONS) if(HAVE_TEST_COVERAGE) From 3938397fd1627922dc090c57faac1de094420721 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 15 Apr 2021 08:44:03 -0700 Subject: [PATCH 006/798] Changed minigzip fuzzer outmode[3] to be determined based on a different value then outmode[2] for better coverage. --- test/fuzz/minigzip_fuzzer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fuzz/minigzip_fuzzer.c b/test/fuzz/minigzip_fuzzer.c index 57e8588882..5a15c662b4 100644 --- a/test/fuzz/minigzip_fuzzer.c +++ b/test/fuzz/minigzip_fuzzer.c @@ -267,7 +267,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { /* Compression level: [0..9]. */ outmode[2] = data[0] % 10; - switch (data[0] % 4) { + switch (data[dataLen-1] % 4) { default: case 0: outmode[3] = 0; From dce3a097dd25fd9aeb02c24ce31cae3606b0e3f1 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 15 Apr 2021 08:44:52 -0700 Subject: [PATCH 007/798] Added Z_FIXED and direct gzip out modes to minigzip fuzzer. --- test/fuzz/minigzip_fuzzer.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/fuzz/minigzip_fuzzer.c b/test/fuzz/minigzip_fuzzer.c index 5a15c662b4..7c5d3ef635 100644 --- a/test/fuzz/minigzip_fuzzer.c +++ b/test/fuzz/minigzip_fuzzer.c @@ -267,7 +267,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { /* Compression level: [0..9]. */ outmode[2] = data[0] % 10; - switch (data[dataLen-1] % 4) { + switch (data[dataLen-1] % 6) { default: case 0: outmode[3] = 0; @@ -284,6 +284,14 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { /* compress with Z_RLE */ outmode[3] = 'R'; break; + case 4: + /* compress with Z_FIXED */ + outmode[3] = 'F'; + break; + case 5: + /* direct */ + outmode[3] = 'T'; + break; } file_compress(inFileName, outmode); From cbae1c88df2818e36beb105c6d422b17b4d20a80 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 24 Apr 2021 13:27:58 -0700 Subject: [PATCH 008/798] Don't directly include asm/hwcap.h; fix compilation on musl aarch64 sys/auxv.h includes the appropriate headers to provide the HWCAP constants, on both glibc and musl, which makes it unnecessary to include asm/hwcap.h directly. And on musl, asm/hwcap.h doesn't exist. --- arch/arm/armfeature.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/armfeature.c b/arch/arm/armfeature.c index cf31a48f0c..cea19e614e 100644 --- a/arch/arm/armfeature.c +++ b/arch/arm/armfeature.c @@ -2,7 +2,6 @@ #if defined(__linux__) # include -# include #elif defined(__FreeBSD__) && defined(__aarch64__) # include # ifndef ID_AA64ISAR0_CRC32_VAL From a7f2956c68a97e99af5b74775b0f9a17844b8829 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 25 Apr 2021 15:21:54 -0700 Subject: [PATCH 009/798] Detect hwcap flags needed for runtime detection on ARM Linux This allows us to provide useful warning messages from cmake or configure if the system headers don't provide the necessary flags to do runtime detection. --- CMakeLists.txt | 28 ++++++++++++++++++++++++ arch/arm/armfeature.c | 4 ++-- configure | 51 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56b4a839c5..dd174a3dff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -649,6 +649,34 @@ endif() if(WITH_OPTIM) if(BASEARCH_ARM_FOUND) add_definitions(-DARM_FEATURES) + if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); + }" + ARM_AUXV_HAS_CRC32 + ) + if(ARM_AUXV_HAS_CRC32) + add_definitions(-DARM_AUXV_HAS_CRC32) + else() + message(STATUS "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") + endif() + if(NOT "${ARCH}" MATCHES "aarch64") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & HWCAP_NEON); + }" + ARM_AUXV_HAS_NEON + ) + if(ARM_AUXV_HAS_NEON) + add_definitions(-DARM_AUXV_HAS_NEON) + else() + message(STATUS "HWCAP_NEON not present in sys/auxv.h; cannot detect support at runtime.") + endif() + endif() + endif() list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/armfeature.c) if(WITH_ACLE AND NOT MSVC) diff --git a/arch/arm/armfeature.c b/arch/arm/armfeature.c index cea19e614e..e8fcc1e5ea 100644 --- a/arch/arm/armfeature.c +++ b/arch/arm/armfeature.c @@ -14,7 +14,7 @@ #endif static int arm_has_crc32() { -#if defined(__linux__) && defined(HWCAP2_CRC32) +#if defined(__linux__) && defined(ARM_AUXV_HAS_CRC32) return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0 ? 1 : 0; #elif defined(__FreeBSD__) && defined(__aarch64__) return getenv("QEMU_EMULATING") == NULL @@ -34,7 +34,7 @@ static int arm_has_crc32() { /* AArch64 has neon. */ #if !defined(__aarch64__) && !defined(_M_ARM64) static inline int arm_has_neon() { -#if defined(__linux__) && defined(HWCAP_NEON) +#if defined(__linux__) && defined(ARM_AUXV_HAS_NEON) return (getauxval(AT_HWCAP) & HWCAP_NEON) != 0 ? 1 : 0; #elif defined(__APPLE__) int hasneon; diff --git a/configure b/configure index aafaa06ac5..89388be0cd 100755 --- a/configure +++ b/configure @@ -524,6 +524,14 @@ else esac fi +# Simplify some later conditionals +case "$uname" in +Linux* | linux*) + LINUX=1 ;; +*) + LINUX=0 ;; +esac + # destination names for shared library if not defined above SHAREDLIB=${SHAREDLIB-"${LIBNAME}$shared_ext"} SHAREDLIBV=${SHAREDLIBV-"${LIBNAME}$shared_ext.$VER"} @@ -1265,6 +1273,34 @@ case "${ARCH}" in SFLAGS="${SFLAGS} -DARM_FEATURES" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} armfeature.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} armfeature.lo" + + if test $LINUX -eq 1; then + cat > $test.c < +int main() { + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); +} +EOF + if try $CC -c $CFLAGS $test.c; then + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" + else + echo "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + fi + + cat > $test.c < +int main() { + return (getauxval(AT_HWCAP) & HWCAP_NEON); +} +EOF + if try $CC -c $CFLAGS $test.c; then + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_NEON" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_NEON" + else + echo "HWCAP_NEON not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + fi + fi fi cat > $test.c << EOF @@ -1405,6 +1441,21 @@ EOF ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} armfeature.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} armfeature.lo" + if test $LINUX -eq 1; then + cat > $test.c < +int main() { + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); +} +EOF + if try $CC -c $CFLAGS $test.c; then + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" + else + echo "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + fi + fi + if test $buildacle -eq 1; then if test $native -eq 0; then ARCH="${ARCH}+crc" From fc7719dbe979237b6348f7e3fdd9edd9921fae3e Mon Sep 17 00:00:00 2001 From: Aaron Boxer Date: Tue, 20 Apr 2021 18:03:32 -0400 Subject: [PATCH 010/798] crc: fix three conversion warnings --- arch/x86/crc_folding.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/crc_folding.c b/arch/x86/crc_folding.c index 918bd94681..49cdc99300 100644 --- a/arch/x86/crc_folding.c +++ b/arch/x86/crc_folding.c @@ -186,7 +186,7 @@ static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); - const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080); + const __m128i xmm_mask3 = _mm_set1_epi32((int32_t)0x80808080); __m128i xmm_shl, xmm_shr, xmm_tmp1, xmm_tmp2, xmm_tmp3; __m128i xmm_a0_0, xmm_a0_1; @@ -358,7 +358,7 @@ Z_INTERNAL void crc_fold_copy(deflate_state *const s, unsigned char *dst, const memcpy(dst, partial_buf, len); partial: - partial_fold(len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); done: /* CRC_SAVE */ _mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0); @@ -450,7 +450,7 @@ uint32_t Z_INTERNAL crc_fold_512to32(deflate_state *const s) { xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1); - crc = _mm_extract_epi32(xmm_crc3, 2); + crc = (uint32_t)_mm_extract_epi32(xmm_crc3, 2); return ~crc; } From 78f07cc2c4281276655956999cc6eee982f621e5 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 2 May 2021 06:05:35 -0700 Subject: [PATCH 011/798] Decompress gzip compressed archive to a separate file to prevent corruption issues on macOS. (#939) * Decompress gzip compressed archive to a separate file to prevent corruption issues on macOS. * Clean up fatal error messages in test-compress cmake script. --- cmake/test-compress.cmake | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/cmake/test-compress.cmake b/cmake/test-compress.cmake index e5b1f3b471..4e90821147 100644 --- a/cmake/test-compress.cmake +++ b/cmake/test-compress.cmake @@ -65,10 +65,13 @@ get_filename_component(OUTPUT_DIR "${OUTPUT_BASE}" DIRECTORY) file(MAKE_DIRECTORY "${OUTPUT_DIR}") macro(cleanup) - # Cleanup temporary mingizip files - file(REMOVE ${OUTPUT_BASE}.gz ${OUTPUT_BASE}.out) - # Cleanup temporary gzip files - file(REMOVE ${OUTPUT_BASE}.gzip.gz ${OUTPUT_BASE}.gzip.out) + # Cleanup temporary files + file(REMOVE + ${OUTPUT_BASE}.gz + ${OUTPUT_BASE}.out + ${OUTPUT_BASE}.gzip + ${OUTPUT_BASE}.gzip.gz + ${OUTPUT_BASE}.gzip.out) endmacro() # Compress input file @@ -180,34 +183,34 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") message(FATAL_ERROR "Gzip compress failed: ${CMD_RESULT}") endif() - if(NOT EXISTS ${OUTPUT_BASE}.gz) + if(NOT EXISTS ${OUTPUT_BASE}.gzip.gz) cleanup() - message(FATAL_ERROR "Cannot find minigzip decompress input: ${OUTPUT_BASE}.gzip.gz") + message(FATAL_ERROR "Cannot find decompress gzip input: ${OUTPUT_BASE}.gzip.gz") endif() # Check decompress target can handle gzip compressed output execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${DECOMPRESS_COMMAND}" -DINPUT=${OUTPUT_BASE}.gzip.gz - -DOUTPUT=${OUTPUT_BASE}.gzip.out + -DOUTPUT=${OUTPUT_BASE}.gzip "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) cleanup() - message(FATAL_ERROR "Minigzip decompress gzip failed: ${CMD_RESULT}") + message(FATAL_ERROR "Decompress gzip failed: ${CMD_RESULT}") endif() if(COMPARE) # Compare original input file with gzip decompressed output execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT_BASE}.gzip.out + -E compare_files ${INPUT} ${OUTPUT_BASE}.gzip RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) cleanup() - message(FATAL_ERROR "Compare minigzip decompress gzip failed: ${CMD_RESULT}") + message(FATAL_ERROR "Compare decompress gzip failed: ${CMD_RESULT}") endif() endif() endif() From 0733cb47997b94506ccfe429d7f81abc99b9ad2f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 29 Apr 2021 18:45:41 -0700 Subject: [PATCH 012/798] Print differences between expected output in test-compress cmake script and upload as artifacts. --- .github/workflows/cmake.yml | 5 +++++ cmake/test-compress.cmake | 44 +++++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 95d3b5aa64..8178e2a189 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -441,4 +441,9 @@ jobs: path: | ${{ matrix.build-dir || '.' }}/CMakeFiles/CMakeOutput.log ${{ matrix.build-dir || '.' }}/CMakeFiles/CMakeError.log + ${{ matrix.build-dir || '.' }}/Testing/Temporary/*.log + ${{ matrix.build-dir || '.' }}/test/**/*.diff + ${{ matrix.build-dir || '.' }}/test/**/*.hex + ${{ matrix.build-dir || '.' }}/test/**/*.gz* + ${{ matrix.build-dir || '.' }}/test/**/*.out retention-days: 30 diff --git a/cmake/test-compress.cmake b/cmake/test-compress.cmake index 4e90821147..97c387da2d 100644 --- a/cmake/test-compress.cmake +++ b/cmake/test-compress.cmake @@ -64,14 +64,41 @@ set(OUTPUT_BASE "${CMAKE_CURRENT_BINARY_DIR}/test/${TEST_NAME}-${UNIQUE_ID}") get_filename_component(OUTPUT_DIR "${OUTPUT_BASE}" DIRECTORY) file(MAKE_DIRECTORY "${OUTPUT_DIR}") +# Cleanup temporary files macro(cleanup) - # Cleanup temporary files - file(REMOVE - ${OUTPUT_BASE}.gz - ${OUTPUT_BASE}.out - ${OUTPUT_BASE}.gzip - ${OUTPUT_BASE}.gzip.gz - ${OUTPUT_BASE}.gzip.out) + if(NOT DEFINED ENV{CI}) + file(REMOVE + ${OUTPUT_BASE}.gz + ${OUTPUT_BASE}.out + ${OUTPUT_BASE}.gzip + ${OUTPUT_BASE}.gzip.gz + ${OUTPUT_BASE}.gzip.out) + endif() +endmacro() + +# Show differences between two files +macro(diff src1 src2) + find_program(XXD xxd) + if(XXD) + find_program(DIFF diff) + if(DIFF) + set(XXD_COMMAND ${XXD} ${src1} ${src1}.hex) + execute_process(COMMAND ${XXD_COMMAND}) + set(XXD_COMMAND ${XXD} ${src2} ${src2}.hex) + execute_process(COMMAND ${XXD_COMMAND}) + + set(DIFF_COMMAND ${DIFF} -u ${src1}.hex ${src2}.hex) + execute_process(COMMAND ${DIFF_COMMAND} + OUTPUT_FILE ${src2}.diff) + + file(READ ${src2}.diff DIFF_OUTPUT) + message(STATUS ${DIFF_OUTPUT}) + + if(NOT DEFINED ENV{CI}) + file(REMOVE ${src1}.hex ${src2}.hex ${src2}.diff) + endif() + endif() + endif() endmacro() # Compress input file @@ -122,6 +149,7 @@ if(COMPARE) RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) + diff(${INPUT} ${OUTPUT_BASE}.out) cleanup() message(FATAL_ERROR "Compare minigzip decompress failed: ${CMD_RESULT}") endif() @@ -158,6 +186,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) + diff(${INPUT} ${OUTPUT_BASE}.gzip.out) cleanup() message(FATAL_ERROR "Compare gzip decompress failed: ${CMD_RESULT}") endif() @@ -209,6 +238,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) + diff(${INPUT} ${OUTPUT_BASE}.gzip) cleanup() message(FATAL_ERROR "Compare decompress gzip failed: ${CMD_RESULT}") endif() From c549c4c55b3287f91d1b21d6002f853340bbd220 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 29 Apr 2021 18:02:34 -0700 Subject: [PATCH 013/798] Create temporary files in CTest's Testing/Temporary directory and upload all files as artifacts. --- .github/workflows/cmake.yml | 6 +----- cmake/test-compress.cmake | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8178e2a189..6ab72297ca 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -441,9 +441,5 @@ jobs: path: | ${{ matrix.build-dir || '.' }}/CMakeFiles/CMakeOutput.log ${{ matrix.build-dir || '.' }}/CMakeFiles/CMakeError.log - ${{ matrix.build-dir || '.' }}/Testing/Temporary/*.log - ${{ matrix.build-dir || '.' }}/test/**/*.diff - ${{ matrix.build-dir || '.' }}/test/**/*.hex - ${{ matrix.build-dir || '.' }}/test/**/*.gz* - ${{ matrix.build-dir || '.' }}/test/**/*.out + ${{ matrix.build-dir || '.' }}/Testing/Temporary/* retention-days: 30 diff --git a/cmake/test-compress.cmake b/cmake/test-compress.cmake index 97c387da2d..1ec1b27ed3 100644 --- a/cmake/test-compress.cmake +++ b/cmake/test-compress.cmake @@ -58,7 +58,7 @@ endif() # Generate unique output path so multiple tests can be executed at the same time string(RANDOM LENGTH 6 UNIQUE_ID) string(REPLACE "." "-" TEST_NAME "${TEST_NAME}") -set(OUTPUT_BASE "${CMAKE_CURRENT_BINARY_DIR}/test/${TEST_NAME}-${UNIQUE_ID}") +set(OUTPUT_BASE "${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/${TEST_NAME}-${UNIQUE_ID}") # Ensure directory exists for output files get_filename_component(OUTPUT_DIR "${OUTPUT_BASE}" DIRECTORY) From 8e7087d32a70df4d85e8305811263ad0a4e21a22 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 29 Apr 2021 18:16:56 -0700 Subject: [PATCH 014/798] Simplify cleaning up files in test-compress cmake script and always clean up files on successful run. --- cmake/test-compress.cmake | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/cmake/test-compress.cmake b/cmake/test-compress.cmake index 1ec1b27ed3..89f0a7b256 100644 --- a/cmake/test-compress.cmake +++ b/cmake/test-compress.cmake @@ -65,14 +65,14 @@ get_filename_component(OUTPUT_DIR "${OUTPUT_BASE}" DIRECTORY) file(MAKE_DIRECTORY "${OUTPUT_DIR}") # Cleanup temporary files +macro(cleanup_always) + file(GLOB TEMP_FILES ${OUTPUT_BASE}*) + file(REMOVE ${TEMP_FILES}) +endmacro() +# Clean up temporary files if not on CI macro(cleanup) if(NOT DEFINED ENV{CI}) - file(REMOVE - ${OUTPUT_BASE}.gz - ${OUTPUT_BASE}.out - ${OUTPUT_BASE}.gzip - ${OUTPUT_BASE}.gzip.gz - ${OUTPUT_BASE}.gzip.out) + cleanup_always() endif() endmacro() @@ -246,4 +246,5 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") endif() endif() -cleanup() \ No newline at end of file + +cleanup_always() \ No newline at end of file From 1cdd7dfad8cdaf36cb7a471346dcbeb2b419b212 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 29 Apr 2021 18:18:36 -0700 Subject: [PATCH 015/798] Add status messages in test-compress cmake script. Change filenames used during test to make it more clear what stage they are apart of. --- cmake/test-compress.cmake | 56 ++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/cmake/test-compress.cmake b/cmake/test-compress.cmake index 89f0a7b256..321fa54301 100644 --- a/cmake/test-compress.cmake +++ b/cmake/test-compress.cmake @@ -92,7 +92,7 @@ macro(diff src1 src2) OUTPUT_FILE ${src2}.diff) file(READ ${src2}.diff DIFF_OUTPUT) - message(STATUS ${DIFF_OUTPUT}) + message(STATUS "Diff:\n${DIFF_OUTPUT}") if(NOT DEFINED ENV{CI}) file(REMOVE ${src1}.hex ${src2}.hex ${src2}.diff) @@ -108,6 +108,10 @@ endif() set(COMPRESS_COMMAND ${COMPRESS_TARGET} ${COMPRESS_ARGS}) +message(STATUS "Compress ${COMPRESS_COMMAND}") +message(STATUS " Input: ${INPUT}") +message(STATUS " Output: ${OUTPUT_BASE}.gz") + execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${COMPRESS_COMMAND}" -DINPUT=${INPUT} @@ -129,10 +133,14 @@ endif() set(DECOMPRESS_COMMAND ${DECOMPRESS_TARGET} ${DECOMPRESS_ARGS}) +message(STATUS "Decompress ${DECOMPRESS_COMMAND}") +message(STATUS " Input: ${OUTPUT_BASE}.gz") +message(STATUS " Output: ${OUTPUT_BASE}") + execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${DECOMPRESS_COMMAND}" -DINPUT=${OUTPUT_BASE}.gz - -DOUTPUT=${OUTPUT_BASE}.out + -DOUTPUT=${OUTPUT_BASE} "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -145,13 +153,13 @@ endif() if(COMPARE) # Compare decompressed output with original input file execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT_BASE}.out + -E compare_files ${INPUT} ${OUTPUT_BASE} RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) - diff(${INPUT} ${OUTPUT_BASE}.out) + diff(${INPUT} ${OUTPUT_BASE}) cleanup() - message(FATAL_ERROR "Compare minigzip decompress failed: ${CMD_RESULT}") + message(FATAL_ERROR "Compare decompress failed: ${CMD_RESULT}") endif() endif() @@ -167,10 +175,14 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") # Check gzip can decompress our compressed output set(GZ_DECOMPRESS_COMMAND ${GZIP} --decompress) + message(STATUS "Gzip decompress ${GZ_DECOMPRESS_COMMAND}") + message(STATUS " Input: ${OUTPUT_BASE}.gz") + message(STATUS " Output: ${OUTPUT_BASE}-ungzip") + execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${GZ_DECOMPRESS_COMMAND}" -DINPUT=${OUTPUT_BASE}.gz - -DOUTPUT=${OUTPUT_BASE}.gzip.out + -DOUTPUT=${OUTPUT_BASE}-ungzip "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -182,27 +194,26 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") # Compare gzip output with original input file execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT_BASE}.gzip.out + -E compare_files ${INPUT} ${OUTPUT_BASE}-ungzip RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) - diff(${INPUT} ${OUTPUT_BASE}.gzip.out) + diff(${INPUT} ${OUTPUT_BASE}-ungzip) cleanup() message(FATAL_ERROR "Compare gzip decompress failed: ${CMD_RESULT}") endif() - if(NOT EXISTS ${OUTPUT_BASE}.gz) - cleanup() - message(FATAL_ERROR "Cannot find gzip compress input: ${INPUT}") - endif() - # Compress input file with gzip set(GZ_COMPRESS_COMMAND ${GZIP} --stdout) + message(STATUS "Gzip compress ${GZ_COMPRESS_COMMAND}") + message(STATUS " Input: ${INPUT}") + message(STATUS " Output: ${OUTPUT_BASE}-gzip.gz") + execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${GZ_COMPRESS_COMMAND}" -DINPUT=${INPUT} - -DOUTPUT=${OUTPUT_BASE}.gzip.gz + -DOUTPUT=${OUTPUT_BASE}-gzip.gz "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -212,16 +223,20 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") message(FATAL_ERROR "Gzip compress failed: ${CMD_RESULT}") endif() - if(NOT EXISTS ${OUTPUT_BASE}.gzip.gz) + if(NOT EXISTS ${OUTPUT_BASE}-gzip.gz) cleanup() - message(FATAL_ERROR "Cannot find decompress gzip input: ${OUTPUT_BASE}.gzip.gz") + message(FATAL_ERROR "Cannot find decompress gzip input: ${OUTPUT_BASE}-gzip.gz") endif() + message(STATUS "Decompress gzip ${DECOMPRESS_COMMAND}") + message(STATUS " Input: ${OUTPUT_BASE}-gzip.gz") + message(STATUS " Output: ${OUTPUT_BASE}-gzip") + # Check decompress target can handle gzip compressed output execute_process(COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT_BASE}.gzip.gz - -DOUTPUT=${OUTPUT_BASE}.gzip + -DINPUT=${OUTPUT_BASE}-gzip.gz + -DOUTPUT=${OUTPUT_BASE}-gzip "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake RESULT_VARIABLE CMD_RESULT) @@ -234,11 +249,11 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") if(COMPARE) # Compare original input file with gzip decompressed output execute_process(COMMAND ${CMAKE_COMMAND} - -E compare_files ${INPUT} ${OUTPUT_BASE}.gzip + -E compare_files ${INPUT} ${OUTPUT_BASE}-gzip RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) - diff(${INPUT} ${OUTPUT_BASE}.gzip) + diff(${INPUT} ${OUTPUT_BASE}-gzip) cleanup() message(FATAL_ERROR "Compare decompress gzip failed: ${CMD_RESULT}") endif() @@ -246,5 +261,4 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") endif() endif() - cleanup_always() \ No newline at end of file From 9d74e168501c37c5f49d6f995581eaefc8f164dc Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Mon, 3 May 2021 17:06:05 +0300 Subject: [PATCH 016/798] Reintroduce Z_SOLO support for compatibility mode. --- zlib.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zlib.h b/zlib.h index edf92242df..99be5f6629 100644 --- a/zlib.h +++ b/zlib.h @@ -1192,6 +1192,8 @@ Z_EXTERN unsigned long Z_EXPORT zlibCompileFlags(void); */ +#ifndef Z_SOLO + /* utility functions */ /* @@ -1646,6 +1648,7 @@ Z_EXTERN void Z_EXPORT gzclearerr(gzFile file); file that is being written concurrently. */ +#endif /* checksum functions */ From 81f1c8a41bd1427707f402450de8820816760fca Mon Sep 17 00:00:00 2001 From: Vladimir Smirnov Date: Sun, 2 May 2021 14:56:16 +0200 Subject: [PATCH 017/798] Fix cmake detection of risc-v (32 and 64 bit) Add a case to detect risc-v architectures. Fixes #941 --- cmake/detect-arch.c | 7 +++++++ cmake/detect-arch.cmake | 3 +++ 2 files changed, 10 insertions(+) diff --git a/cmake/detect-arch.c b/cmake/detect-arch.c index 571553582a..c8bad4beda 100644 --- a/cmake/detect-arch.c +++ b/cmake/detect-arch.c @@ -93,6 +93,13 @@ #elif defined(__THW_RS6000) #error archfound rs6000 +// RISC-V +#elif defined(__riscv) + #if __riscv_xlen == 64 + #error archfound riscv64 + #elif __riscv_xlen == 32 + #error archfound riscv32 + // return 'unrecognized' if we do not know what architecture this is #else #error archfound unrecognized diff --git a/cmake/detect-arch.cmake b/cmake/detect-arch.cmake index 69475da38d..76b52b9f36 100644 --- a/cmake/detect-arch.cmake +++ b/cmake/detect-arch.cmake @@ -85,6 +85,9 @@ elseif("${ARCH}" MATCHES "parisc") elseif("${ARCH}" MATCHES "rs6000") set(BASEARCH "rs6000") set(BASEARCH_RS6000_FOUND TRUE) +elseif("${ARCH}" MATCHES "riscv(32|64)") + set(BASEARCH "riscv") + set(BASEARCH_RISCV_FOUND TRUE) else() set(BASEARCH "x86") set(BASEARCH_X86_FOUND TRUE) From 811ddc9ce722d6c2ca613dbb9ae4da8194d15256 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 8 May 2021 14:46:15 +0200 Subject: [PATCH 018/798] Don't check for SSSE3 on non-x86 architectures. --- configure | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/configure b/configure index 89388be0cd..9812d057f6 100755 --- a/configure +++ b/configure @@ -994,8 +994,9 @@ EOF esac # Check for SSSE3 intrinsics - -cat > $test.c << EOF +case "${ARCH}" in + i386 | i486 | i586 | i686 | x86_64) + cat > $test.c << EOF #include int main(void) { @@ -1007,13 +1008,15 @@ int main(void) return 0; } EOF -if try ${CC} ${CFLAGS} ${ssse3flag} $test.c; then - echo "Checking for SSSE3 intrinsics ... Yes." | tee -a configure.log - HAVE_SSSE3_INTRIN=1 -else - echo "Checking for SSSE3 intrinsics ... No." | tee -a configure.log - HAVE_SSSE3_INTRIN=0 -fi + if try ${CC} ${CFLAGS} ${ssse3flag} $test.c; then + echo "Checking for SSSE3 intrinsics ... Yes." | tee -a configure.log + HAVE_SSSE3_INTRIN=1 + else + echo "Checking for SSSE3 intrinsics ... No." | tee -a configure.log + HAVE_SSSE3_INTRIN=0 + fi + ;; +esac # Check for SSE4.2 CRC inline assembly case "${ARCH}" in From 62b269b4a5f4502d6dc03d73bb5b552e80066885 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Thu, 6 May 2021 19:49:21 +0200 Subject: [PATCH 019/798] upgrade links to HTTPS http://infozip.sourceforge.net/ is sadly not having HTTPS access enabled. Shoutout to somebody with admin access for this project: It would be nice to enable it and thus allowing secure access to these pages via https://infozip.sourceforge.io/ . The option has been there for a while now: https://sourceforge.net/blog/introducing-https-for-project-websites/ also: - follow permanent redirects - add ending slashes --- FAQ.zlib | 26 +++++++++++++------------- arch/s390/README.md | 2 +- arch/x86/crc_folding.c | 2 +- deflate.c | 2 +- doc/algorithm.txt | 2 +- doc/rfc1952.txt | 2 +- test/CVE-2003-0107.c | 2 +- test/README.md | 4 ++-- win32/DLL_FAQ.txt | 4 ++-- win32/README-WIN32.txt | 8 ++++---- win32/zlib-ng1.rc | 2 +- win32/zlib1.rc | 2 +- zlib-ng.h | 2 +- zlib.h | 2 +- 14 files changed, 31 insertions(+), 31 deletions(-) diff --git a/FAQ.zlib b/FAQ.zlib index f234f3e592..a681656f7d 100644 --- a/FAQ.zlib +++ b/FAQ.zlib @@ -9,8 +9,8 @@ If your question is not there, please check the zlib home page -http://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at http://zlib.net/zlib_faq.html +https://zlib.net/ which may have more recent information. +The lastest zlib FAQ is at https://zlib.net/zlib_faq.html 1. Is zlib Y2K-compliant? @@ -21,12 +21,12 @@ The lastest zlib FAQ is at http://zlib.net/zlib_faq.html The zlib sources can be compiled without change to produce a DLL. See the file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the - precompiled DLL are found in the zlib web site at http://zlib.net/ . + precompiled DLL are found in the zlib web site at https://zlib.net/ . 3. Where can I get a Visual Basic interface to zlib? See - * http://marknelson.us/1997/01/01/zlib-engine/ + * https://marknelson.us/1997/01/01/zlib-engine/ * win32/DLL_FAQ.txt in the zlib distribution 4. compress() returns Z_BUF_ERROR. @@ -45,7 +45,7 @@ The lastest zlib FAQ is at http://zlib.net/zlib_faq.html made with more input or output space. A Z_BUF_ERROR may in fact be unavoidable depending on how the functions are used, since it is not possible to tell whether or not there is more output pending when - strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a + strm.avail_out returns with zero. See https://zlib.net/zlib_how.html for a heavily annotated example. 6. Where's the zlib documentation (man pages, etc.)? @@ -116,8 +116,8 @@ The lastest zlib FAQ is at http://zlib.net/zlib_faq.html 16. Can zlib decode Flate data in an Adobe PDF file? - Yes. See http://www.pdflib.com/ . To modify PDF forms, see - http://sourceforge.net/projects/acroformtool/ . + Yes. See https://www.pdflib.com/ . To modify PDF forms, see + https://sourceforge.net/projects/acroformtool/ . 17. Why am I getting this "register_frame_info not found" error on Solaris? @@ -130,7 +130,7 @@ The lastest zlib FAQ is at http://zlib.net/zlib_faq.html The symbol __register_frame_info is not part of zlib, it is generated by the C compiler (cc or gcc). You must recompile applications using zlib which have this problem. This problem is specific to Solaris. See - http://www.sunfreeware.com for Solaris versions of zlib and applications + http://www.sunfreeware.com/ for Solaris versions of zlib and applications using zlib. 18. Why does gzip give an error on a file I make with compress/deflate? @@ -242,7 +242,7 @@ The lastest zlib FAQ is at http://zlib.net/zlib_faq.html As far as we know, no. In fact, that was originally the whole point behind zlib. Look here for some more information: - http://www.gzip.org/#faq11 + https://www.gzip.org/#faq11 32. Can zlib work with greater than 4 GB of data? @@ -278,7 +278,7 @@ The lastest zlib FAQ is at http://zlib.net/zlib_faq.html If you don't have snprintf() or vsnprintf() and would like one, you can find a portable implementation here: - http://www.ijs.si/software/snprintf/ + https://www.ijs.si/software/snprintf/ Note that you should be using the most recent version of zlib. Versions 1.1.3 and before were subject to a double-free vulnerability, and versions @@ -290,7 +290,7 @@ The lastest zlib FAQ is at http://zlib.net/zlib_faq.html Probably what you want is to use zlib in Java. zlib is already included as part of the Java SDK in the java.util.zip package. If you really want a version of zlib written in the Java language, look on the zlib home - page for links: http://zlib.net/ . + page for links: https://zlib.net/ . 35. I get this or that compiler or source-code scanner warning when I crank it up to maximally-pedantic. Can't you guys write proper code? @@ -321,9 +321,9 @@ The lastest zlib FAQ is at http://zlib.net/zlib_faq.html zlib doesn't support encryption. The original PKZIP encryption is very weak and can be broken with freely available programs. To get strong - encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib + encryption, use GnuPG, https://www.gnupg.org/ , which already includes zlib compression. For PKZIP compatible "encryption", look at - http://www.info-zip.org/ + http://infozip.sourceforge.net/ 39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? diff --git a/arch/s390/README.md b/arch/s390/README.md index 641c63a832..9425de3901 100644 --- a/arch/s390/README.md +++ b/arch/s390/README.md @@ -23,7 +23,7 @@ https://www.ibm.com/products/z15) and newer machines under the name [ https://www.ibm.com/support/z-content-solutions/compression/). The programming interface to it is a machine instruction called DEFLATE CONVERSION CALL (DFLTCC). It is documented in Chapter 26 of [Principles -of Operation](http://publibfp.dhe.ibm.com/epubs/pdf/a227832c.pdf). Both +of Operation](https://publibfp.dhe.ibm.com/epubs/pdf/a227832c.pdf). Both the code and the rest of this document refer to this feature simply as "DFLTCC". diff --git a/arch/x86/crc_folding.c b/arch/x86/crc_folding.c index 49cdc99300..4030db5988 100644 --- a/arch/x86/crc_folding.c +++ b/arch/x86/crc_folding.c @@ -3,7 +3,7 @@ * instruction. * * A white paper describing this algorithm can be found at: - * http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf + * https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf * * Copyright (C) 2013 Intel Corporation. All rights reserved. * Authors: diff --git a/deflate.c b/deflate.c index 1707f75c20..7e270899d6 100644 --- a/deflate.c +++ b/deflate.c @@ -37,7 +37,7 @@ * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://tools.ietf.org/html/rfc1951 + * Available in https://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. diff --git a/doc/algorithm.txt b/doc/algorithm.txt index c97f495020..acd099c9ae 100644 --- a/doc/algorithm.txt +++ b/doc/algorithm.txt @@ -206,4 +206,4 @@ Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, pp. 337-343. ``DEFLATE Compressed Data Format Specification'' available in -http://tools.ietf.org/html/rfc1951 +https://tools.ietf.org/html/rfc1951 diff --git a/doc/rfc1952.txt b/doc/rfc1952.txt index a8e51b4567..14c0c72eb2 100644 --- a/doc/rfc1952.txt +++ b/doc/rfc1952.txt @@ -420,7 +420,7 @@ RFC 1952 GZIP File Format Specification May 1996 This contains a Cyclic Redundancy Check value of the uncompressed data computed according to CRC-32 algorithm used in the ISO 3309 standard and in section 8.1.1.6.2 of - ITU-T recommendation V.42. (See http://www.iso.ch for + ITU-T recommendation V.42. (See https://www.iso.org/ for ordering ISO documents. See gopher://info.itu.ch for an online version of ITU-T V.42.) diff --git a/test/CVE-2003-0107.c b/test/CVE-2003-0107.c index 51c79b2cda..427767d072 100644 --- a/test/CVE-2003-0107.c +++ b/test/CVE-2003-0107.c @@ -1,4 +1,4 @@ -// http://www.securityfocus.com/archive/1/312869 --- originally by Richard Kettlewell +// https://www.securityfocus.com/archive/1/312869 --- originally by Richard Kettlewell #include #include #include diff --git a/test/README.md b/test/README.md index 247d5bac74..b15b01df67 100644 --- a/test/README.md +++ b/test/README.md @@ -26,11 +26,11 @@ Some of the files in _test_ are licensed differently: “Combinatorial Modeling of Chromatin Features Quantitatively Predicts DNA Replication Timing in _Drosophila_” by Federico Comoglio and Renato Paro, which is licensed under the CC-BY license. See - http://www.ploscompbiol.org/static/license for more information. + https://www.ploscompbiol.org/static/license for more information. - test/data/lcet10.txt is from Project Gutenberg. It does not have expired copyright, but is still in the public domain according to the license information. - (http://www.gutenberg.org/ebooks/53). + (https://www.gutenberg.org/ebooks/53). - test/GH-382/defneg3.dat was the smallest file generated by Nathan Moinvaziri that reproduced GH-382. It is licensed under the terms of the zlib license. diff --git a/win32/DLL_FAQ.txt b/win32/DLL_FAQ.txt index c212985967..7a57079673 100644 --- a/win32/DLL_FAQ.txt +++ b/win32/DLL_FAQ.txt @@ -6,7 +6,7 @@ This document describes the design, the rationale, and the usage of the official DLL build of zlib, named ZLIB1.DLL. If you have general questions about zlib, you should see the file "FAQ" found in the zlib distribution, or at the following location: - http://www.gzip.org/zlib/zlib_faq.html + https://www.zlib.net/zlib_faq.html 1. What is ZLIB1.DLL, and how can I get it? @@ -16,7 +16,7 @@ in the zlib distribution, or at the following location: Pointers to a precompiled ZLIB1.DLL can be found in the zlib web site at: - http://www.zlib.net/ + https://www.zlib.net/ Applications that link to ZLIB1.DLL can rely on the following specification: diff --git a/win32/README-WIN32.txt b/win32/README-WIN32.txt index 7a859bb234..905ace6b89 100644 --- a/win32/README-WIN32.txt +++ b/win32/README-WIN32.txt @@ -3,7 +3,7 @@ ZLIB DATA COMPRESSION LIBRARY zlib 1.2.11 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files -http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +https://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). All functions of the compression library are documented in the file zlib.h @@ -12,11 +12,11 @@ examples are distributed in this package, example and minigzip. The example_d and minigzip_d flavors validate that the zlib1.dll file is working correctly. Questions about zlib should be sent to . The zlib home page -is http://zlib.net/ . Before reporting a problem, please check this site to +is https://zlib.net/ . Before reporting a problem, please check this site to verify that you have the latest version of zlib; otherwise get the latest version and check whether the problem still exists or not. -PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html +PLEASE read DLL_FAQ.txt, and the the zlib FAQ https://zlib.net/zlib_faq.html before asking for help. @@ -59,7 +59,7 @@ The package zlib-1.2.11-win32-x86.zip will contain the following files: All .pdb files above are entirely optional, but are very useful to a developer attempting to diagnose program misbehavior or a crash. Many additional important files for developers can be found in the zlib127.zip source package -available from http://zlib.net/ - review that package's README file for details. +available from https://zlib.net/ - review that package's README file for details. Acknowledgments: diff --git a/win32/zlib-ng1.rc b/win32/zlib-ng1.rc index fdac56ff68..b53906904b 100644 --- a/win32/zlib-ng1.rc +++ b/win32/zlib-ng1.rc @@ -30,7 +30,7 @@ BEGIN VALUE "OriginalFilename", "zlib-ng1.dll\0" VALUE "ProductName", "zlib\0" VALUE "ProductVersion", ZLIBNG_VERSION "\0" - VALUE "Comments", "For more information visit http://www.zlib.net/\0" + VALUE "Comments", "For more information visit https://www.zlib.net/\0" END END BLOCK "VarFileInfo" diff --git a/win32/zlib1.rc b/win32/zlib1.rc index 5c0feed1b4..11be5f49f9 100644 --- a/win32/zlib1.rc +++ b/win32/zlib1.rc @@ -30,7 +30,7 @@ BEGIN VALUE "OriginalFilename", "zlib1.dll\0" VALUE "ProductName", "zlib\0" VALUE "ProductVersion", ZLIB_VERSION "\0" - VALUE "Comments", "For more information visit http://www.zlib.net/\0" + VALUE "Comments", "For more information visit https://www.zlib.net/\0" END END BLOCK "VarFileInfo" diff --git a/zlib-ng.h b/zlib-ng.h index 6d98f6c454..3cacc64af8 100644 --- a/zlib-ng.h +++ b/zlib-ng.h @@ -25,7 +25,7 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + Comments) 1950 to 1952 in the files https://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ diff --git a/zlib.h b/zlib.h index 99be5f6629..d6aa53830a 100644 --- a/zlib.h +++ b/zlib.h @@ -26,7 +26,7 @@ The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + Comments) 1950 to 1952 in the files https://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ From f2077005e80b08bc03a67f7b1aca9be809e93e95 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 9 May 2021 08:17:03 +0300 Subject: [PATCH 020/798] [ARM/AArch64] More thorough testing of getauxval() macros and includes * 32-bit ARM and AArch64 use slightly different macros for CRC32 and NEON feature bits * 32-bit ARM sometimes requires asm/hwcap.h for AT_HWCAP2 --- CMakeLists.txt | 62 ++++++++++++++++++++++++++++++++++--------- arch/arm/armfeature.c | 11 ++++++++ configure | 33 +++++++++++++++++++---- 3 files changed, 89 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dd174a3dff..42316c9bb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -650,30 +650,68 @@ if(WITH_OPTIM) if(BASEARCH_ARM_FOUND) add_definitions(-DARM_FEATURES) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - check_c_source_compiles( - "#include - int main() { - return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); - }" - ARM_AUXV_HAS_CRC32 - ) - if(ARM_AUXV_HAS_CRC32) - add_definitions(-DARM_AUXV_HAS_CRC32) + if(NOT "${ARCH}" MATCHES "aarch64") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); + }" + ARM_AUXV_HAS_CRC32 + ) + if(ARM_AUXV_HAS_CRC32) + add_definitions(-DARM_AUXV_HAS_CRC32) + else() + check_c_source_compiles( + "#include + #include + int main() { + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); + }" + ARM_HWCAP_HAS_CRC32 + ) + if (ARM_HWCAP_HAS_CRC32) + add_definitions(-DARM_AUXV_HAS_CRC32 -DARM_ASM_HWCAP) + else() + message(STATUS "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") + endif() + endif() else() - message(STATUS "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & HWCAP_CRC32); + }" + ARM_AUXV_HAS_CRC32 + ) + if(ARM_AUXV_HAS_CRC32) + add_definitions(-DARM_AUXV_HAS_CRC32) + else() + message(STATUS "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") + endif() endif() if(NOT "${ARCH}" MATCHES "aarch64") check_c_source_compiles( "#include int main() { - return (getauxval(AT_HWCAP) & HWCAP_NEON); + return (getauxval(AT_HWCAP) & HWCAP_ARM_NEON); }" ARM_AUXV_HAS_NEON ) if(ARM_AUXV_HAS_NEON) add_definitions(-DARM_AUXV_HAS_NEON) else() - message(STATUS "HWCAP_NEON not present in sys/auxv.h; cannot detect support at runtime.") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & HWCAP_NEON); + }" + ARM_AUXV_HAS_NEON + ) + if (ARM_AUXV_HAS_NEON) + add_definitions(-DARM_AUXV_HAS_NEON) + else() + message(STATUS "Neither HWCAP_ARM_NEON or HWCAP_NEON present in sys/auxv.h; cannot detect support at runtime.") + endif() endif() endif() endif() diff --git a/arch/arm/armfeature.c b/arch/arm/armfeature.c index e8fcc1e5ea..bef9b290ad 100644 --- a/arch/arm/armfeature.c +++ b/arch/arm/armfeature.c @@ -2,6 +2,9 @@ #if defined(__linux__) # include +# ifdef ARM_ASM_HWCAP +# include +# endif #elif defined(__FreeBSD__) && defined(__aarch64__) # include # ifndef ID_AA64ISAR0_CRC32_VAL @@ -15,7 +18,11 @@ static int arm_has_crc32() { #if defined(__linux__) && defined(ARM_AUXV_HAS_CRC32) +# ifdef HWCAP_CRC32 + return (getauxval(AT_HWCAP) & HWCAP_CRC32) != 0 ? 1 : 0; +# else return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0 ? 1 : 0; +# endif #elif defined(__FreeBSD__) && defined(__aarch64__) return getenv("QEMU_EMULATING") == NULL && ID_AA64ISAR0_CRC32_VAL(READ_SPECIALREG(id_aa64isar0_el1)) >= ID_AA64ISAR0_CRC32_BASE; @@ -35,7 +42,11 @@ static int arm_has_crc32() { #if !defined(__aarch64__) && !defined(_M_ARM64) static inline int arm_has_neon() { #if defined(__linux__) && defined(ARM_AUXV_HAS_NEON) +# ifdef HWCAP_ARM_NEON + return (getauxval(AT_HWCAP) & HWCAP_ARM_NEON) != 0 ? 1 : 0; +# else return (getauxval(AT_HWCAP) & HWCAP_NEON) != 0 ? 1 : 0; +# endif #elif defined(__APPLE__) int hasneon; size_t size = sizeof(hasneon); diff --git a/configure b/configure index 9812d057f6..fd02a6fea0 100755 --- a/configure +++ b/configure @@ -1288,20 +1288,43 @@ EOF CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" else - echo "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + cat > $test.c < +#include +int main() { + return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); +} +EOF + if try $CC -c $CFLAGS $test.c; then + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32 -DARM_ASM_HWCAP" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32 -DARM_ASM_HWCAP" + else + echo "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + fi fi cat > $test.c < int main() { - return (getauxval(AT_HWCAP) & HWCAP_NEON); + return (getauxval(AT_HWCAP) & HWCAP_ARM_NEON); } EOF if try $CC -c $CFLAGS $test.c; then CFLAGS="${CFLAGS} -DARM_AUXV_HAS_NEON" SFLAGS="${SFLAGS} -DARM_AUXV_HAS_NEON" else - echo "HWCAP_NEON not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + cat > $test.c < +int main() { + return (getauxval(AT_HWCAP) & HWCAP_NEON); +} +EOF + if try $CC -c $CFLAGS $test.c; then + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_NEON" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_NEON" + else + echo "Neither HWCAP_ARM_NEON or HWCAP_NEON present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + fi fi fi fi @@ -1448,14 +1471,14 @@ EOF cat > $test.c < int main() { - return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); + return (getauxval(AT_HWCAP) & HWCAP_CRC32); } EOF if try $CC -c $CFLAGS $test.c; then CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" else - echo "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + echo "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log fi fi From 54b1c13c37b53f2481f02576657cedfef29fce2f Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 8 May 2021 18:45:00 +0200 Subject: [PATCH 021/798] Version 2.0.3 - Include porting guide in release packages #917 - Documentation improvements #913 #949 - Added Windows ARM binaries in release packages #916 - Fix crash on ARMv7 #927 - Fix building on FreeBSD #921 - Fix building with musl on aarch64 #936 #952 - Fix ARM float-abi detection #918 - Fix cmake detection of risc-v architectures #942 - Minor buildsystem fixes #922 #924 #933 #938 #950 - Improve zlib-compat build #915 #944 - CI/Test improvements #926 #929 #927 #937 #939 #940 --- Makefile.in | 2 +- zlib-ng.h | 6 +++--- zlib.h | 6 +++--- zutil.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.in b/Makefile.in index 0859a759bf..68e921774c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.0.2 +VER=2.0.3 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h b/zlib-ng.h index 3cacc64af8..84228cb974 100644 --- a/zlib-ng.h +++ b/zlib-ng.h @@ -44,11 +44,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.0.2" -#define ZLIBNG_VERNUM 0x2020 +#define ZLIBNG_VERSION "2.0.3" +#define ZLIBNG_VERNUM 0x2030 #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 0 -#define ZLIBNG_VER_REVISION 2 +#define ZLIBNG_VER_REVISION 3 #define ZLIBNG_VER_SUBREVISION 0 /* diff --git a/zlib.h b/zlib.h index d6aa53830a..5f06753631 100644 --- a/zlib.h +++ b/zlib.h @@ -46,11 +46,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.0.2" -#define ZLIBNG_VERNUM 0x2020 +#define ZLIBNG_VERSION "2.0.3" +#define ZLIBNG_VERNUM 0x2030 #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 0 -#define ZLIBNG_VER_REVISION 2 +#define ZLIBNG_VER_REVISION 3 #define ZLIBNG_VER_SUBREVISION 0 #define ZLIB_VERSION "1.2.11.zlib-ng" diff --git a/zutil.c b/zutil.c index 902af570de..a01150ad0a 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char zlibng_string[] = - " zlib-ng 2.0.2 forked from zlib"; + " zlib-ng 2.0.3 forked from zlib"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From 5339a31cf9349a7b7e7ab8a5a507fda917f53f87 Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Thu, 13 May 2021 17:10:12 -0600 Subject: [PATCH 022/798] Spelling fixes --- .github/workflows/cmake.yml | 2 +- CMakeLists.txt | 2 +- FAQ.zlib | 2 +- PORTING.md | 2 +- cmake/run-and-compare.cmake | 2 +- cmake/run-and-redirect.cmake | 2 +- deflate.c | 2 +- inftrees.h | 2 +- test/abicheck.md | 2 +- test/data/lcet10.txt | 8 ++++---- zlib-ng.h | 8 ++++---- zlib.h | 8 ++++---- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 6ab72297ca..1446ea7003 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -390,7 +390,7 @@ jobs: wineboot --init - name: Generate project files - # Shared libaries turned off for qemu ppc* and sparc & reduce code coverage sources + # Shared libraries turned off for qemu ppc* and sparc & reduce code coverage sources run: | mkdir ${{ matrix.build-dir || '.not-used' }} cd ${{ matrix.build-dir || '.' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 42316c9bb6..7bfeba7e55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ message(STATUS "Using CMake version ${CMAKE_VERSION}") set(CMAKE_MACOSX_RPATH 1) # If not specified on the command line, enable C99 as the default -# Configuration items that affect the global compiler envirionment standards +# Configuration items that affect the global compiler environment standards # should be issued before the "project" command. if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) # The C standard whose features are requested to build this target diff --git a/FAQ.zlib b/FAQ.zlib index a681656f7d..163160c103 100644 --- a/FAQ.zlib +++ b/FAQ.zlib @@ -10,7 +10,7 @@ If your question is not there, please check the zlib home page https://zlib.net/ which may have more recent information. -The lastest zlib FAQ is at https://zlib.net/zlib_faq.html +The latest zlib FAQ is at https://zlib.net/zlib_faq.html 1. Is zlib Y2K-compliant? diff --git a/PORTING.md b/PORTING.md index 837d6bf252..eda2608da4 100644 --- a/PORTING.md +++ b/PORTING.md @@ -12,7 +12,7 @@ in a single application or system-wide. Please note that zlib-ng in zlib-compat mode is API-compatible but not ABI-compatible, meaning that you cannot simply replace the zlib library/dll files and expect the application to work. The application will need to be -recompiled against the zlib-ng headers and libs to ensure full compatability. +recompiled against the zlib-ng headers and libs to ensure full compatibility. **Advantages:** - Easy to port to, since it only requires a recompile of the application and diff --git a/cmake/run-and-compare.cmake b/cmake/run-and-compare.cmake index d64005204a..af54abc264 100644 --- a/cmake/run-and-compare.cmake +++ b/cmake/run-and-compare.cmake @@ -9,7 +9,7 @@ # COMPARE - String to compare output against # Optional Variables -# INPUT - Standard intput +# INPUT - Standard input # IGNORE_LINE_ENDINGS - Ignore line endings when comparing output if(NOT DEFINED OUTPUT OR NOT DEFINED COMPARE OR NOT DEFINED COMMAND) diff --git a/cmake/run-and-redirect.cmake b/cmake/run-and-redirect.cmake index 29f8a33e61..6651d1a302 100644 --- a/cmake/run-and-redirect.cmake +++ b/cmake/run-and-redirect.cmake @@ -10,7 +10,7 @@ # COMMAND - Command to run # Optional Variables -# INPUT - Standard intput +# INPUT - Standard input # OUTPUT - Standard output (default: /dev/null) # SUCCESS_EXIT - List of successful exit codes (default: 0, ie: 0;1) diff --git a/deflate.c b/deflate.c index 7e270899d6..ca9dafa8db 100644 --- a/deflate.c +++ b/deflate.c @@ -208,7 +208,7 @@ Z_INTERNAL void slide_hash_c(deflate_state *s) { * 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 unncessary zero-extension. + * variable to avoid unnecessary zero-extension. */ { unsigned int i; diff --git a/inftrees.h b/inftrees.h index 7758737c2e..031c2a1b94 100644 --- a/inftrees.h +++ b/inftrees.h @@ -41,7 +41,7 @@ typedef struct { /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program - examples/enough.c found in the zlib distribtution. The arguments to that + examples/enough.c found in the zlib distributions. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. diff --git a/test/abicheck.md b/test/abicheck.md index 6e9e58aade..3e291264ad 100644 --- a/test/abicheck.md +++ b/test/abicheck.md @@ -46,7 +46,7 @@ constantly downloading and building the old version, you can check the .abi file into git. To make this easier, a helper script could be written to automatically build -all the configurations tested by .github/worflows/abicheck.yml +all the configurations tested by .github/workflows/abicheck.yml Then they could be checked into git en masse by a maintainer when a new platform is added or a new major version (which intentionally breaks backwards compatibility) is being prepared. diff --git a/test/data/lcet10.txt b/test/data/lcet10.txt index 26b187d048..1dbdfc56e4 100644 --- a/test/data/lcet10.txt +++ b/test/data/lcet10.txt @@ -897,7 +897,7 @@ current difficulty in exchanging electronically computer-based instructional software, which in turn makes it difficult for one scholar to build upon the work of others, will be resolved before too long. Stand-alone curricular applications that involve electronic text will be -sharable through networks, reinforcing their significance as intellectual +shareable through networks, reinforcing their significance as intellectual products as well as instructional tools. The second aspect of electronic learning involves the use of research and @@ -1587,7 +1587,7 @@ Bowdoin. CALALUCA * PLD's principal focus and contribution to scholarship * Various questions preparatory to beginning the project * Basis for project * Basic rule in converting PLD * Concerning the images in PLD * -Running PLD under a variety of retrieval softwares * Encoding the +Running PLD under a variety of retrieval software * Encoding the database a hard-fought issue * Various features demonstrated * Importance of user documentation * Limitations of the CD-ROM version * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -1654,7 +1654,7 @@ anything demonstrated at the Workshop. What cannot practically be done is go back and reconvert and re-encode data, a time-consuming and extremely costly enterprise. CALALUCA sees PLD as a database that can, and should, be run under a variety of -retrieval softwares. This will permit the widest possible searches. +retrieval software. This will permit the widest possible searches. Consequently, the need to produce a CD-ROM of PLD, as well as to develop software that could handle some 1.3 gigabyte of heavily encoded text, developed out of conversations with collection development and reference @@ -5034,7 +5034,7 @@ schemes every single discrete area of a text that might someday be searched. That was another decision. Searching by a column number, an author, a word, a volume, permitting combination searches, and tagging notations seemed logical choices as core elements. 3) How does one make -the data available? Tieing it to a CD-ROM edition creates limitations, +the data available? Tying it to a CD-ROM edition creates limitations, but a magnetic tape file that is very large, is accompanied by the encoding specifications, and that allows one to make local modifications also allows one to incorporate any changes one may desire within the diff --git a/zlib-ng.h b/zlib-ng.h index 84228cb974..b506faddc6 100644 --- a/zlib-ng.h +++ b/zlib-ng.h @@ -273,7 +273,7 @@ int32_t zng_deflate(zng_stream *strm, int32_t flush); == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), - which can be used if desired to determine whether or not there is more ouput + which can be used if desired to determine whether or not there is more output in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to @@ -655,7 +655,7 @@ int32_t zng_deflateGetDictionary(zng_stream *strm, uint8_t *dictionary, uint32_t to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. + Similarly, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up @@ -903,7 +903,7 @@ int32_t zng_inflateGetDictionary(zng_stream *strm, uint8_t *dictionary, uint32_t to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is NULL, then it is not set. + Similarly, if dictLength is NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. @@ -1438,7 +1438,7 @@ size_t zng_gzfread(void *buf, size_t size, size_t nitems, gzFile file); provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written - file, reseting and retrying on end-of-file, when size is not 1. + file, resetting and retrying on end-of-file, when size is not 1. */ Z_EXTERN Z_EXPORT diff --git a/zlib.h b/zlib.h index 5f06753631..ee5edde6fd 100644 --- a/zlib.h +++ b/zlib.h @@ -282,7 +282,7 @@ Z_EXTERN int Z_EXPORT deflate(z_stream *strm, int flush); == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), - which can be used if desired to determine whether or not there is more ouput + which can be used if desired to determine whether or not there is more output in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to @@ -664,7 +664,7 @@ Z_EXTERN int Z_EXPORT deflateGetDictionary (z_stream *strm, unsigned char *dicti to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is Z_NULL, then it is not set. + Similarly, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up @@ -901,7 +901,7 @@ Z_EXTERN int Z_EXPORT inflateGetDictionary(z_stream *strm, unsigned char *dictio to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to NULL, then only the dictionary length is returned, and nothing is copied. - Similary, if dictLength is NULL, then it is not set. + Similarly, if dictLength is NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. @@ -1418,7 +1418,7 @@ Z_EXTERN size_t Z_EXPORT gzfread (void *buf, size_t size, size_t nitems, gzFile provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written - file, reseting and retrying on end-of-file, when size is not 1. + file, resetting and retrying on end-of-file, when size is not 1. */ Z_EXTERN int Z_EXPORT gzwrite(gzFile file, void const *buf, unsigned len); From df218c12aac0eb69a48af77eac9ace35064af75d Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Thu, 13 May 2021 07:57:24 -0600 Subject: [PATCH 023/798] Fix compiler detection to avoid bad mpicc match --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7bfeba7e55..8582c22518 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,8 +134,8 @@ if(WITH_GZFILEOP) add_definitions(-DWITH_GZFILEOP) endif() -if("${CMAKE_C_COMPILER}" MATCHES "icc" OR "${CMAKE_C_COMPILER}" MATCHES "icpc" OR "${CMAKE_C_COMPILER}" MATCHES "icl") - if(CMAKE_HOST_UNIX OR APPLE) +if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR CMAKE_HOST_APPLE) set(WARNFLAGS "-w3") set(WARNFLAGS_MAINTAINER "-w3 -Wcheck -Wremarks") set(WARNFLAGS_DISABLE "") From bde11b12775aed5113040de319f484da879a3f04 Mon Sep 17 00:00:00 2001 From: Greg Sjaardema Date: Thu, 13 May 2021 08:41:22 -0600 Subject: [PATCH 024/798] Remove redundancy; apple is unix --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8582c22518..f800c0398a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,7 +135,7 @@ if(WITH_GZFILEOP) endif() if(CMAKE_C_COMPILER_ID MATCHES "Intel") - if(CMAKE_HOST_UNIX OR CMAKE_HOST_APPLE) + if(CMAKE_HOST_UNIX) set(WARNFLAGS "-w3") set(WARNFLAGS_MAINTAINER "-w3 -Wcheck -Wremarks") set(WARNFLAGS_DISABLE "") From c91806258805d243080a934ebd169333d4f8ba46 Mon Sep 17 00:00:00 2001 From: Kolby Crouch Date: Sat, 15 May 2021 13:17:42 -0500 Subject: [PATCH 025/798] Fix build on NetBSD --- zutil_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zutil_p.h b/zutil_p.h index 7dc2e3d353..f3830f35f6 100644 --- a/zutil_p.h +++ b/zutil_p.h @@ -16,7 +16,7 @@ /* Function to allocate 16 or 64-byte aligned memory */ static inline void *zng_alloc(size_t size) { -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__NetBSD__) void *ptr; return posix_memalign(&ptr, 64, size) ? NULL : ptr; #elif defined(_WIN32) From 8b5630050aa541c2e49632bf2dc69b70f4120f5d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 21 May 2021 20:36:21 +0100 Subject: [PATCH 026/798] OpenBSD build fix proposal --- zutil.h | 8 ++++++-- zutil_p.h | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/zutil.h b/zutil.h index 497cb22b40..11e4875761 100644 --- a/zutil.h +++ b/zutil.h @@ -183,12 +183,16 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr); # define ZSWAP32(q) bswap_32(q) # define ZSWAP64(q) bswap_64(q) -#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) # include # define ZSWAP16(q) bswap16(q) # define ZSWAP32(q) bswap32(q) # define ZSWAP64(q) bswap64(q) - +#elif defined(__OpenBSD__) +# include +# define ZSWAP16(q) swap16(q) +# define ZSWAP32(q) swap32(q) +# define ZSWAP64(q) swap64(q) #elif defined(__INTEL_COMPILER) /* ICC does not provide a two byte swap. */ # define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) diff --git a/zutil_p.h b/zutil_p.h index f3830f35f6..c8122607ea 100644 --- a/zutil_p.h +++ b/zutil_p.h @@ -5,7 +5,7 @@ #ifndef ZUTIL_P_H #define ZUTIL_P_H -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(__OpenBSD__) # include #elif defined(__FreeBSD__) # include @@ -16,7 +16,7 @@ /* Function to allocate 16 or 64-byte aligned memory */ static inline void *zng_alloc(size_t size) { -#if defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) void *ptr; return posix_memalign(&ptr, 64, size) ? NULL : ptr; #elif defined(_WIN32) From 414ec0f00d85394849d0ce26c799faf094e2b6fb Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 25 May 2021 17:46:46 +0300 Subject: [PATCH 027/798] Fix build under Cygwin. --- CMakeLists.txt | 7 ++++--- test/minideflate.c | 3 +++ test/switchlevels.c | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f800c0398a..a7ff3b09de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -945,13 +945,13 @@ set(ZLIB_GZFILE_SRCS gzwrite.c ) -if(NOT MINGW AND NOT MSYS) +if(NOT MINGW AND NOT MSYS AND NOT CYGWIN) set(ZLIB_DLL_SRCS win32/zlib${SUFFIX}1.rc # If present will override custom build rule below. ) endif() -if(MINGW OR MSYS) +if(MINGW OR MSYS OR CYGWIN) # This gets us DLL resource information when compiling on MinGW. if(NOT CMAKE_RC_COMPILER) set(CMAKE_RC_COMPILER windres.exe) @@ -1033,7 +1033,8 @@ if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) # Match configure/make's behavior (i.e. don't use @rpath on mac). set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "${LIB_INSTALL_DIR}") endif() - elseif(MSYS) + endif() + if(MSYS OR CYGWIN) # Suppress version number from shared library name set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 0) elseif(WIN32) diff --git a/test/minideflate.c b/test/minideflate.c index 392516852d..8ce57fad58 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -3,6 +3,9 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ +#define _POSIX_SOURCE 1 /* This file needs POSIX for fileno(). */ +#define _POSIX_C_SOURCE 200112 /* For snprintf(). */ + #include #include #include diff --git a/test/switchlevels.c b/test/switchlevels.c index 0f850113e2..a4ec4b7c76 100644 --- a/test/switchlevels.c +++ b/test/switchlevels.c @@ -2,6 +2,8 @@ * Each chunk is compressed with a user-specified level. */ +#define _POSIX_SOURCE 1 /* This file needs POSIX for fileno(). */ + #include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" From 07fa17104a4e19a496b38c816270097ede84445b Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 25 May 2021 19:55:27 +0300 Subject: [PATCH 028/798] Fix warnings in configure * Don't assign contents of variable to itself * Quote strings containing "=" --- configure | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/configure b/configure index fd02a6fea0..4e6645dc52 100755 --- a/configure +++ b/configure @@ -70,8 +70,6 @@ fi # set defaults before processing command line options LDCONFIG=${LDCONFIG-"ldconfig"} -LDFLAGS=${LDFLAGS} -LDSHAREDLIBC="${LDSHAREDLIBC}" DEFFILE= RC= RCFLAGS= @@ -209,9 +207,9 @@ show() { case "$*" in *$test.c*) - echo === $test.c === >> configure.log + echo "=== $test.c ===" >> configure.log cat $test.c >> configure.log - echo === >> configure.log;; + echo "===" >> configure.log;; esac echo $* >> configure.log } From b295830835bb51da3b2dd5f733b040b315d5464a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Wegner?= Date: Thu, 13 May 2021 17:15:37 +0200 Subject: [PATCH 029/798] Handle HAVE_UNISTD_H defined to 0. FFmpeg during the configure stage generates a config.h file with ``` #define HAVE_UNISTD_H 0 ``` on windows. Then somewhere in FFmpeg's code there is: ``` #include "config.h" // FFmpeg's config.h #include ``` which causes zlib.h to include unistd.h on windows. It is way easier to handle the issue here than in FFmpeg. Co-authored-by: Mika Lindqvist --- CMakeLists.txt | 2 +- configure | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7ff3b09de..f461b258a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1055,7 +1055,7 @@ endif() if(HAVE_UNISTD_H) SET(ZCONF_UNISTD_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") else() - SET(ZCONF_UNISTD_LINE "#ifdef HAVE_UNISTD_H /* may be set to #if 1 by configure/cmake/etc */") + SET(ZCONF_UNISTD_LINE "#if 0 /* was set to #if 0 by configure/cmake/etc */") endif() if(NEED_PTRDIFF_T) SET(ZCONF_PTRDIFF_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") diff --git a/configure b/configure index 4e6645dc52..353cad4d80 100755 --- a/configure +++ b/configure @@ -777,6 +777,8 @@ if try $CC -c $CFLAGS $test.c; then mv zconf${SUFFIX}.temp.h zconf${SUFFIX}.h echo "Checking for unistd.h... Yes." | tee -a configure.log else + sed < zconf${SUFFIX}.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be set to #if 1/ 0\1 was set to #if 0/" > zconf${SUFFIX}.temp.h + mv zconf${SUFFIX}.temp.h zconf${SUFFIX}.h echo "Checking for unistd.h... No." | tee -a configure.log fi From a3ed1321f3c22a45ffa6e282fe207c763b0ec052 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 25 May 2021 20:45:27 +0300 Subject: [PATCH 030/798] Remove unnecessary test for stdarg.h --- CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f461b258a4..a33fc17405 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,7 +331,6 @@ endif() # # Check for standard/system includes # -check_include_file(stdarg.h HAVE_STDARG_H) check_include_file(sys/sdt.h HAVE_SYS_SDT_H) if(HAVE_SYS_SDT_H) add_definitions(-DHAVE_SYS_SDT_H) @@ -836,7 +835,6 @@ macro(generate_cmakein input output) file(STRINGS ${input} _lines) foreach(_line IN LISTS _lines) string(REGEX REPLACE "#ifdef HAVE_UNISTD_H.*" "@ZCONF_UNISTD_LINE@" _line "${_line}") - string(REGEX REPLACE "#ifdef HAVE_STDARG_H.*" "@ZCONF_STDARG_LINE@" _line "${_line}") string(REGEX REPLACE "#ifdef NEED_PTRDIFF_T.*" "@ZCONF_PTRDIFF_LINE@" _line "${_line}") if(NEED_PTRDIFF_T) string(REGEX REPLACE "typedef PTRDIFF_TYPE" "typedef @PTRDIFF_TYPE@" _line "${_line}") @@ -1047,11 +1045,6 @@ if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) endif() endif() -if(HAVE_STDARG_H) - SET(ZCONF_STDARG_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") -else() - SET(ZCONF_STDARG_LINE "#ifdef HAVE_STDARG_H /* may be set to #if 1 by configure/cmake/etc */") -endif() if(HAVE_UNISTD_H) SET(ZCONF_UNISTD_LINE "#if 1 /* was set to #if 1 by configure/cmake/etc */") else() From 2c65dce35f0e109a6e05413730bfe698c8bf6407 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sat, 22 May 2021 08:38:46 +0300 Subject: [PATCH 031/798] Only when using Visual C++, the static library name should be "zlibstatic" * On CygWin, MSYS and MinGW, the static library name should be "z" like on other Unix-like systems --- CMakeLists.txt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a33fc17405..a9b51438a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -992,7 +992,24 @@ foreach(ZLIB_INSTALL_LIBRARY ${ZLIB_INSTALL_LIBRARIES}) endforeach() if(WIN32) - set_target_properties(${ZLIB_INSTALL_LIBRARIES} PROPERTIES OUTPUT_NAME zlib${SUFFIX}) + # Shared library + if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) + set_target_properties(zlib PROPERTIES OUTPUT_NAME zlib${SUFFIX}) + endif() + # Static library + if(NOT DEFINED BUILD_SHARED_LIBS) + if(MSVC) + set_target_properties(zlibstatic PROPERTIES OUTPUT_NAME zlibstatic${SUFFIX}) + else() + set_target_properties(zlibstatic PROPERTIES OUTPUT_NAME z${SUFFIX}) + endif() + elseif(NOT BUILD_SHARED_LIBS) + if(MSVC) + set_target_properties(zlib PROPERTIES OUTPUT_NAME zlibstatic${SUFFIX}) + else() + set_target_properties(zlib PROPERTIES OUTPUT_NAME z${SUFFIX}) + endif() + endif() else() # On unix-like platforms the library is almost always called libz set_target_properties(${ZLIB_INSTALL_LIBRARIES} PROPERTIES OUTPUT_NAME z${SUFFIX}) From a9df2ca9bdc3d37c0a9ff0402b0644d00cf54010 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 29 May 2021 11:14:48 -0700 Subject: [PATCH 032/798] Use latest version of llvm-cov 11 to prevent code coverage version mismatch when using clang. --- .github/workflows/cmake.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 1446ea7003..c43fcf2874 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -255,39 +255,39 @@ jobs: - name: Ubuntu Clang os: ubuntu-latest compiler: clang - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang - name: Ubuntu Clang Inflate Strict os: ubuntu-latest compiler: clang cmake-args: -DWITH_INFLATE_STRICT=ON - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_inflate_strict - name: Ubuntu Clang Inflate Allow Invalid Dist os: ubuntu-latest compiler: clang cmake-args: -DWITH_INFLATE_ALLOW_INVALID_DIST=ON - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_inflate_allow_invalid_dist - name: Ubuntu Clang Memory Map os: ubuntu-latest compiler: clang cflags: -DUSE_MMAP - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_mmap - name: Ubuntu Clang Debug os: ubuntu-latest compiler: clang - packages: llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_debug build-config: Debug @@ -295,8 +295,8 @@ jobs: os: ubuntu-latest compiler: clang cmake-args: -GNinja -DWITH_SANITIZER=Memory - packages: ninja-build llvm-6.0 - gcov-exec: llvm-cov-6.0 gcov + packages: ninja-build llvm-11-tools + gcov-exec: llvm-cov-11 gcov cflags: -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins codecov: ubuntu_clang_msan From e5fdfc77b8826d3c4ac818919d77685877090e29 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 29 May 2021 12:01:07 -0700 Subject: [PATCH 033/798] Explicitly state clang version to prevent future code coverage format mismatches. --- .github/workflows/cmake.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index c43fcf2874..6b5cea4e12 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -254,14 +254,14 @@ jobs: - name: Ubuntu Clang os: ubuntu-latest - compiler: clang + compiler: clang-11 packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang - name: Ubuntu Clang Inflate Strict os: ubuntu-latest - compiler: clang + compiler: clang-11 cmake-args: -DWITH_INFLATE_STRICT=ON packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov @@ -269,7 +269,7 @@ jobs: - name: Ubuntu Clang Inflate Allow Invalid Dist os: ubuntu-latest - compiler: clang + compiler: clang-11 cmake-args: -DWITH_INFLATE_ALLOW_INVALID_DIST=ON packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov @@ -277,7 +277,7 @@ jobs: - name: Ubuntu Clang Memory Map os: ubuntu-latest - compiler: clang + compiler: clang-11 cflags: -DUSE_MMAP packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov @@ -285,7 +285,7 @@ jobs: - name: Ubuntu Clang Debug os: ubuntu-latest - compiler: clang + compiler: clang-11 packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_debug @@ -293,7 +293,7 @@ jobs: - name: Ubuntu Clang MSAN os: ubuntu-latest - compiler: clang + compiler: clang-11 cmake-args: -GNinja -DWITH_SANITIZER=Memory packages: ninja-build llvm-11-tools gcov-exec: llvm-cov-11 gcov From c53fba58cd1cb0831ebccbd75d40a27d31e1f948 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 27 May 2021 09:31:47 -0700 Subject: [PATCH 034/798] Use different fuzzer bits in example_dict_fuzzer for more input value combinations. --- test/fuzz/example_dict_fuzzer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/fuzz/example_dict_fuzzer.c b/test/fuzz/example_dict_fuzzer.c index 027c9a806a..da1bb06c96 100644 --- a/test/fuzz/example_dict_fuzzer.c +++ b/test/fuzz/example_dict_fuzzer.c @@ -42,13 +42,13 @@ void test_dict_deflate(unsigned char **compr, size_t *comprLen) { int method = Z_DEFLATED; /* The deflate compression method (the only one supported in this version) */ - int windowBits = 8 + data[0] % 8; /* The windowBits parameter is the base + int windowBits = 8 + data[(dataLen > 1) ? 1:0] % 8; /* The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. */ - int memLevel = 1 + data[0] % 9; /* memLevel=1 uses minimum memory but is + int memLevel = 1 + data[(dataLen > 2) ? 2:0] % 9; /* memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. */ - int strategy = data[0] % 5; /* [0..4] + int strategy = data[(dataLen > 3) ? 3:0] % 5; /* [0..4] #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 From 634e01d76dc18ed92b6f4b659543e10bc871b045 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 27 May 2021 10:17:08 -0700 Subject: [PATCH 035/798] Fixed gz mode for compression level not using ascii numeric value. --- test/fuzz/minigzip_fuzzer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fuzz/minigzip_fuzzer.c b/test/fuzz/minigzip_fuzzer.c index 7c5d3ef635..6703ac58ff 100644 --- a/test/fuzz/minigzip_fuzzer.c +++ b/test/fuzz/minigzip_fuzzer.c @@ -265,7 +265,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { snprintf(outmode, sizeof(outmode), "%s", "wb"); /* Compression level: [0..9]. */ - outmode[2] = data[0] % 10; + outmode[2] = '0' + (data[0] % 10); switch (data[dataLen-1] % 6) { default: From 59306efa92411d7d70e1be5fa6c600a2f994bb0f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 27 May 2021 10:27:09 -0700 Subject: [PATCH 036/798] Fixed trying to uncompress after compressing in gzip direct mode which is not supported by gz functions. https://oss-fuzz.com/testcase-detail/6194422837542912 --- test/fuzz/minigzip_fuzzer.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/fuzz/minigzip_fuzzer.c b/test/fuzz/minigzip_fuzzer.c index 6703ac58ff..0c7a79a7d7 100644 --- a/test/fuzz/minigzip_fuzzer.c +++ b/test/fuzz/minigzip_fuzzer.c @@ -295,7 +295,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { } file_compress(inFileName, outmode); - file_uncompress(outFileName); + + /* gzopen does not support reading in direct mode */ + if (outmode[3] == 'T') + inFileName = outFileName; + else + file_uncompress(outFileName); /* Check that the uncompressed file matches the input data. */ in = fopen(inFileName, "rb"); From 025b27e3949b428bf8495c3a142b78384e95c4fa Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 29 May 2021 17:34:40 +0500 Subject: [PATCH 037/798] Replace CMAKE_CURRENT_SOURCE_DIR to CMAKE_CURRENT_LIST_DIR --- cmake/detect-arch.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/detect-arch.cmake b/cmake/detect-arch.cmake index 76b52b9f36..f0547ba310 100644 --- a/cmake/detect-arch.cmake +++ b/cmake/detect-arch.cmake @@ -25,7 +25,7 @@ else() run_result_unused compile_result_unused ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/detect-arch.c + ${CMAKE_CURRENT_LIST_DIR}/detect-arch.c COMPILE_OUTPUT_VARIABLE RAWOUTPUT CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} ) From 9ee1c5a9ed9cb6c4996beb7648963b2c4f31b406 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 2 Jun 2021 16:32:00 -0700 Subject: [PATCH 038/798] Use SET_BAD macro in inflateBack. --- infback.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/infback.c b/infback.c index eecf03ada4..62369396ff 100644 --- a/infback.c +++ b/infback.c @@ -188,8 +188,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in state->mode = TABLE; break; case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; + SET_BAD("invalid block type"); } DROPBITS(2); break; @@ -199,8 +198,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in BYTEBITS(); /* go to byte boundary */ NEEDBITS(32); if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; + SET_BAD("invalid stored block lengths"); break; } state->length = (uint16_t)hold; @@ -236,8 +234,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in DROPBITS(4); #ifndef PKZIP_BUG_WORKAROUND if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; + SET_BAD("too many length or distance symbols"); break; } #endif @@ -257,8 +254,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in state->lenbits = 7; ret = zng_inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; + SET_BAD("invalid code lengths set"); break; } Tracev((stderr, "inflate: code lengths ok\n")); @@ -279,8 +275,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in NEEDBITS(here.bits + 2); DROPBITS(here.bits); if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; + SET_BAD("invalid bit length repeat"); break; } len = state->lens[state->have - 1]; @@ -300,8 +295,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in DROPBITS(7); } if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; + SET_BAD("invalid bit length repeat"); break; } while (copy) { @@ -317,8 +311,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in /* check for end-of-block code (better have one) */ if (state->lens[256] == 0) { - strm->msg = (char *)"invalid code -- missing end-of-block"; - state->mode = BAD; + SET_BAD("invalid code -- missing end-of-block"); break; } @@ -330,8 +323,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in state->lenbits = 9; ret = zng_inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; + SET_BAD("invalid literal/lengths set"); break; } state->distcode = (const code *)(state->next); @@ -339,8 +331,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in ret = zng_inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; + SET_BAD("invalid distances set"); break; } Tracev((stderr, "inflate: codes ok\n")); @@ -399,8 +390,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in /* invalid code */ if (here.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; + SET_BAD("invalid literal/length code"); break; } @@ -432,8 +422,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in } DROPBITS(here.bits); if (here.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; + SET_BAD("invalid distance code"); break; } state->offset = here.val; @@ -447,8 +436,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in } #ifdef INFLATE_STRICT if (state->offset > state->wsize - (state->whave < state->wsize ? left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; + SET_BAD("invalid distance too far back"); break; } #endif From 4747276ffee6de9612e2dc265a7cc9e2d88328c9 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 3 Jun 2021 02:38:24 +0300 Subject: [PATCH 039/798] Move MIN() macro to zbuild.h --- deflate_p.h | 3 --- zbuild.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deflate_p.h b/deflate_p.h index 102a4de066..7cad8ab0ba 100644 --- a/deflate_p.h +++ b/deflate_p.h @@ -76,7 +76,4 @@ static inline int zng_tr_tally_dist(deflate_state *s, uint32_t dist, uint32_t le /* Maximum stored block length in deflate format (not including header). */ #define MAX_STORED 65535 -/* Minimum of a and b. */ -#define MIN(a, b) ((a) > (b) ? (b) : (a)) - #endif diff --git a/zbuild.h b/zbuild.h index 3bd4f4898d..c68fb109e4 100644 --- a/zbuild.h +++ b/zbuild.h @@ -26,4 +26,7 @@ # define z_size_t size_t #endif +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + #endif From 3b8489fe6c86d83ac0c0833fd256f9dc1b731a20 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 3 Jun 2021 18:02:03 -0700 Subject: [PATCH 040/798] Added CMake project for building pigz. Added GitHub Actions CI for testing pigz. --- .github/workflows/pigz.yml | 87 ++++++++++++++++++ test/pigz/CMakeLists.txt | 180 +++++++++++++++++++++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 .github/workflows/pigz.yml create mode 100644 test/pigz/CMakeLists.txt diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml new file mode 100644 index 0000000000..5b1a335d5b --- /dev/null +++ b/.github/workflows/pigz.yml @@ -0,0 +1,87 @@ +name: CI Pigz +on: [push, pull_request] +jobs: + ci-cmake: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - name: Ubuntu GCC + os: ubuntu-latest + compiler: gcc + codecov: ubuntu_gcc_pigz + + - name: Ubuntu Clang + os: ubuntu-latest + compiler: clang + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov + codecov: ubuntu_clang_pigz + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Checkout test corpora + uses: actions/checkout@v2 + with: + repository: zlib-ng/corpora + path: test/data/corpora + + - name: Install packages (Ubuntu) + if: runner.os == 'Linux' && matrix.packages + run: | + sudo apt-get update + sudo apt-get install -y ${{ matrix.packages }} + + - name: Install codecov.io tools + if: matrix.codecov + run: | + python -u -m pip install codecov + + - name: Generate project files + run: | + cd test/pigz + cmake ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DZLIB_ROOT=../.. -DWITH_CODE_COVERAGE=ON -DWITH_MAINTAINER_WARNINGS=ON + env: + CC: ${{ matrix.compiler }} + CFLAGS: ${{ matrix.cflags }} + LDFLAGS: ${{ matrix.ldflags }} + CI: true + + - name: Compile source code + run: | + cd test/pigz + cmake --build . --config ${{ matrix.build-config || 'Release' }} + + - name: Run test cases + run: | + cd test/pigz + ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '2' }} + + - name: Upload coverage report + if: matrix.codecov && ( env.CODECOV_TOKEN_SECRET != '' || github.repository == 'zlib-ng/zlib-ng' ) + shell: bash + run: | + bash tools/codecov-upload.sh + env: + # Codecov does not yet support GitHub Actions + CODECOV_TOKEN_SECRET: "${{secrets.CODECOV_TOKEN}}" + CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN || 'e4fdf847-f541-4ab1-9d50-3d27e5913906' }}" + CODECOV_FLAGS: "${{ matrix.codecov }}" + CODECOV_NAME: "${{ matrix.name }}" + CODECOV_EXEC: "${{ matrix.gcov-exec || 'gcov' }}" + CODECOV_DIR: "." + + - name: Upload build errors + uses: actions/upload-artifact@v2 + if: failure() + with: + name: ${{ matrix.name }} (cmake) + path: | + **/CMakeFiles/CMakeOutput.log + **/CMakeFiles/CMakeError.log + **/Testing/Temporary/* + retention-days: 30 diff --git a/test/pigz/CMakeLists.txt b/test/pigz/CMakeLists.txt new file mode 100644 index 0000000000..a9298201eb --- /dev/null +++ b/test/pigz/CMakeLists.txt @@ -0,0 +1,180 @@ +# CMakeLists.txt -- Build madler/pigz against zlib variant + +# Copyright (C) 2021 Nathan Moinvaziri +# Licensed under the Zlib license, see LICENSE.md for details + +# By default pigz will be linked against the system zlib and +# pthread libraries if installed. + +# Optional Variables +# PIGZ_ENABLE_TESTS - Enable adding unit tests +# ZLIB_ROOT - Path to the zlib source directory +# PTHREADS4W_ROOT - Path to pthreads4w source directory on Windows. +# If not specified then threading will be disabled. + +cmake_minimum_required(VERSION 3.11) + +include(CheckCCompilerFlag) +include(FeatureSummary) +include(FetchContent) + +include(../../cmake/detect-coverage.cmake) + +option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF) +option(PIGZ_ENABLE_TESTS "Build unit tests" ON) + +project(pigz LANGUAGES C) + +# Set code coverage compiler flags +if(WITH_CODE_COVERAGE) + add_code_coverage() +endif() + +# Compiler definitions +if(CMAKE_C_COMPILER_ID STREQUAL "Clang") + add_definitions(-fno-caret-diagnostics) +elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5.0) + add_definitions(-Wno-unused-result) + endif() + if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8.0) + add_definitions(-fno-diagnostics-show-caret) + endif() +elseif(MSVC) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) +endif() + +# Fetch pigz source code from official repository +FetchContent_Declare(pigz + GIT_REPOSITORY https://github.com/madler/pigz.git) +FetchContent_MakeAvailable(pigz) +FetchContent_GetProperties(pigz) + +if(NOT pigz_POPULATED) + FetchContent_Populate(pigz) +endif() + +set(PIGZ_SRCS + ${pigz_SOURCE_DIR}/pigz.c + ${pigz_SOURCE_DIR}/try.c + ${pigz_SOURCE_DIR}/yarn.c) + +set(PIGZ_HDRS + ${pigz_SOURCE_DIR}/try.h + ${pigz_SOURCE_DIR}/yarn.h) + +add_executable(${PROJECT_NAME} ${PIGZ_SRCS} ${PIGZ_HDRS}) +add_definitions(-DNOZOPFLI) + +# Find and link against pthreads or pthreads4w +if(WIN32) + add_definitions(-D_TIMESPEC_DEFINED) + + if(DEFINED PTHREADS4W_ROOT) + set(CLEANUP_STYLE VC) + set(PTHREADS4W_VERSION 3) + + add_subdirectory(${PTHREADS4W_ROOT} ${PTHREADS4W_ROOT} EXCLUDE_FROM_ALL) + target_link_libraries(${PROJECT_NAME} pthreadVC3) + target_include_directories(${PROJECT_NAME} PRIVATE win ${PTHREADS4W_ROOT}) + else() + message(WARNING "Missing pthreads4w root directory, disabling threading") + add_definitions(-DNOTHREAD) + endif() +else() + find_package(Threads REQUIRED) + target_link_libraries(${PROJECT_NAME} Threads::Threads) + if(NOT APPLE) + target_link_libraries(${PROJECT_NAME} m) + endif() +endif() + +# Find and link against zlib +if(NOT DEFINED ZLIB_ROOT) + find_package(Zlib REQUIRED) +endif() + +set(ZLIB_COMPAT ON) +set(ZLIB_ENABLE_TESTS OFF) + +add_subdirectory(${ZLIB_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/zlib EXCLUDE_FROM_ALL) + +if(NOT DEFINED BUILD_SHARED_LIBS OR NOT BUILD_SHARED_LIBS) + set(ZLIB_TARGET zlibstatic) +else() + set(ZLIB_TARGET zlib) +endif() + +target_include_directories(${PROJECT_NAME} PRIVATE ${ZLIB_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/zlib) +target_link_libraries(${PROJECT_NAME} ${ZLIB_TARGET}) + +if(NOT SKIP_INSTALL_BINARIES AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PROJECT_NAME} DESTINATION "bin") +endif() + +# Add unit tests +if(PIGZ_ENABLE_TESTS) + enable_testing() + + set(PIGZ_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) + + macro(test_pigz name path) + # Construct compression arguments for pigz + set(compress_args -k -c) + foreach(extra_arg IN ITEMS "${ARGN}") + list(APPEND compress_args ${extra_arg}) + endforeach() + + # Create unique friendly string for test + string(REPLACE ";" "" arg_list "${ARGN}") + string(REPLACE " " "" arg_list "${arg_list}") + string(REPLACE "-" "" arg_list "${arg_list}") + + set(test_id pigz-${name}-${arg_list}) + + if(NOT TEST ${test_id}) + add_test(NAME ${test_id} + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${PIGZ_COMMAND}" + "-DCOMPRESS_ARGS=${compress_args}" + "-DDECOMPRESS_ARGS=-d;-c" + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${path} + -DTEST_NAME=${test_id} + -P ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/test-compress.cmake) + endif() + endmacro() + + set(TEST_CONFIGS + -U # RLE compression + #-H # Z_HUFFMAN_ONLY (broken in 2.6) + -0 # No compression + -1 # Deflate quick + -4 # Deflate medium (lazy matches) + -6 # Deflate medium + -9 # Deflate slow + ) + + file(GLOB_RECURSE TEST_FILE_PATHS + LIST_DIRECTORIES false + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../data/*) + + foreach(TEST_FILE_PATH ${TEST_FILE_PATHS}) + if("${TEST_FILE_PATH}" MATCHES ".gz$" OR "${TEST_FILE_PATH}" MATCHES ".out$" OR + "${TEST_FILE_PATH}" MATCHES "/.git/" OR "${TEST_FILE_PATH}" MATCHES ".md$") + continue() + endif() + foreach(TEST_CONFIG ${TEST_CONFIGS}) + get_filename_component(TEST_NAME ${TEST_FILE_PATH} NAME) + if (TEST_NAME STREQUAL "") + continue() + endif() + test_pigz(${TEST_NAME} ${TEST_FILE_PATH} ${TEST_CONFIG}) + endforeach() + endforeach() +endif() + +add_feature_info(WITH_CODE_COVERAGE WITH_CODE_COVERAGE "Enable code coverage reporting") +add_feature_info(PIGZ_ENABLE_TESTS PIGZ_ENABLE_TESTS "Build unit tests") + +FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) From 187ee5fcdd5a2c5dd2981812511c4bfa4b9f4a8c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 3 Jun 2021 18:44:08 -0700 Subject: [PATCH 041/798] Added GH-979 failure test case against for inflateBack. --- test/GH-979/pigz-2.6.tar.gz | Bin 0 -> 106840 bytes test/pigz/CMakeLists.txt | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 test/GH-979/pigz-2.6.tar.gz diff --git a/test/GH-979/pigz-2.6.tar.gz b/test/GH-979/pigz-2.6.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..0d76ef8757e36dc5ab02e579a99442c211b6d978 GIT binary patch literal 106840 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 z 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%0A!*@!_1l*%gn{T*uEUOk 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

TW z_IDONo{|>HAW1G>TyRtpbmwk{?E;Qe^keeoFsDM3S=2db6)SXNcKE5%&&Ar#_N zpb@o8hS`1wgDDbLa&s+bs8dLKx3^4*zmN|i^7+?GCYx*0-1L2GVTM3%-hPWrrhz0e zbXNHB3HfPmGwCS)c;aGu`*;sb-s8nk=U{GPS59ihrvy=D!4Vx`q}533<6z$ck`Pyq z#Wp|O#O4)elSw*QD!!Er{iJ0~8m2>w=uzx@uM&gU0r$C!=YYmjU1aUBHf`trIflpm zFq{>9Y%Ab4N$mgk2oo{wij86SPzFIw|MoSMh>+=?vK%06Ri5?N6y32 zPWFhl#BhsY+gB&zX;_uy28Xzn@#4NH&UCg_=suUja2QPKb-V!m%U6KxcfYDXI(>KVeZLk1dpU8 zJ(yC4l)g7U9lQo+6a{OuE#k*r-jT#E>0I?o6F>I7yPufUqKPKv}ds~3-?2-x{@=kJ>}nO93O zI3+2XM938mPr#0cVU!2=Wwm_oC}TP=y|_@ywlY%`>@9xa$lSI=tkviJnbecM0g6D; z#gnR7xopbk>jjl(OpGP8cT&dDJ^}*|cYn&W;+mV3&0>yf)w#>nwHu1yokd8ym zQAEeQj_R{r_lrFHT8M}S83BAw2~OKeB5i}Q1uX)2R?d&}r0rzF4H>KEf;v|b}({Pj53@@LXZ!rbM&_B91^_?a$7^_jgH z_D&VwOkJ-?ckMq0-)0KKW|}6YyN3ro2heX%gbj1Kpnk|b734y1tAZb=i8QY5bMHOC zbUYV^l|Rp`f6{L!GWTHZr zoJeOTZ>=xYHk|0I*rr{Y?@X3*1y^kuJ3YGuir-S?3uMz24JJ&d@LXC^AIqx2430Mw zxhP8Ewks}5ddx7a%H&Pkvbe{q+$Hm?zRF9aZnQP@uchGsl#Cc}$!-uw4xA^8 zJTo>TdPw1Sw;2$~;fGv{;q(+?rngoV%qxM9sMp!{!D53t zHYX@;Z65KdeOE|7NY41K;ryCh*ITJZc-|E5k=47tbg`vkV>v}>cYd6|SMWCm>(jj> z(Y-IP3MMF`@7?wsDi;HW<_vO~T(l=k={JY>LsPax4pbFHZ{$NzksGQkw&_C{BRM

?-Y#xg4rj7}S3taUTj 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 sizeof(size_t), "crc32_z takes size_t but internally we have a uint64_t len"); - functable.crc32 = &crc32_byfour; + functable.crc32 = &crc32_braid; cpu_check_features(); #ifdef ARM_ACLE_CRC_HASH if (arm_cpu_has_crc32) diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index 06a11cfa0e..c781c626f7 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -55,7 +55,7 @@ class crc32: public benchmark::Fixture { } \ BENCHMARK_REGISTER_F(crc32, name)->Range(1, MAX_RANDOM_INTS_SIZE); -BENCHMARK_CRC32(byfour, crc32_byfour, 1); +BENCHMARK_CRC32(braid, crc32_braid, 1); #ifdef ARM_ACLE_CRC_HASH BENCHMARK_CRC32(acle, crc32_acle, arm_cpu_has_crc32); diff --git a/test/fuzz/fuzzer_checksum.c b/test/fuzz/fuzzer_checksum.c index e2002d5167..cedd284dbe 100644 --- a/test/fuzz/fuzzer_checksum.c +++ b/test/fuzz/fuzzer_checksum.c @@ -19,7 +19,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { /* Checksum with a buffer of size equal to the first byte in the input. */ uint32_t buffSize = data[0]; uint32_t offset = 0; - uint32_t op[32]; + uint32_t op; /* Discard inputs larger than 1Mb. */ static size_t kMaxSize = 1024 * 1024; @@ -31,7 +31,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { ++buffSize; /* CRC32 */ - PREFIX(crc32_combine_gen)(op, buffSize); + op = PREFIX(crc32_combine_gen)(buffSize); for (offset = 0; offset + buffSize <= dataLen; offset += buffSize) { uint32_t crc3 = PREFIX(crc32_z)(crc0, data + offset, buffSize); uint32_t crc4 = PREFIX(crc32_combine_op)(crc1, crc3, op); @@ -52,7 +52,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { assert(combine1 == combine2); /* Fast CRC32 combine. */ - PREFIX(crc32_combine_gen)(op, (z_off_t)dataLen); + op = PREFIX(crc32_combine_gen)((z_off_t)dataLen); combine1 = PREFIX(crc32_combine_op)(crc1, crc2, op); combine2 = PREFIX(crc32_combine_op)(crc2, crc1, op); assert(combine1 == combine2); diff --git a/test/test_crc32.cc b/test/test_crc32.cc index f76f838adf..1d839d78df 100644 --- a/test/test_crc32.cc +++ b/test/test_crc32.cc @@ -206,7 +206,7 @@ INSTANTIATE_TEST_SUITE_P(crc32, crc32_variant, testing::ValuesIn(tests)); hash(GetParam(), func); \ } -TEST_CRC32(byfour, crc32_byfour, 1) +TEST_CRC32(braid, crc32_braid, 1) #ifdef ARM_ACLE_CRC_HASH TEST_CRC32(acle, crc32_acle, arm_cpu_has_crc32) diff --git a/tools/makecrct.c b/tools/makecrct.c index 3f6b37b13d..bfc2b96551 100644 --- a/tools/makecrct.c +++ b/tools/makecrct.c @@ -1,4 +1,4 @@ -/* crc32.c -- output crc32 tables +/* makecrct.c -- output crc32 tables * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -6,172 +6,245 @@ #include #include #include "zbuild.h" -#include "deflate.h" -#include "crc32_p.h" +#include "zutil.h" -static uint32_t crc_table[8][256]; -static uint32_t crc_comb[GF2_DIM][GF2_DIM]; +/* + The crc32 table header file contains tables for both 32-bit and 64-bit + z_word_t's, and so requires a 64-bit type be available. In that case, + z_word_t must be defined to be 64-bits. This code then also generates + and writes out the tables for the case that z_word_t is 32 bits. +*/ + +#define W 8 /* Need a 64-bit integer type in order to generate crc32 tables. */ + +#include "crc32_braid_p.h" + +static uint32_t crc_table[256]; +static z_word_t crc_big_table[256]; + +static uint32_t crc_braid_table[W][256]; +static z_word_t crc_braid_big_table[W][256]; +static uint32_t x2n_table[32]; + +#include "crc32_braid_comb_p.h" -static void gf2_matrix_square(uint32_t *square, const uint32_t *mat); static void make_crc_table(void); -static void make_crc_combine_table(void); static void print_crc_table(void); -static void print_crc_combine_table(void); -static void write_table(const uint32_t *, int); +static void braid(uint32_t ltl[][256], z_word_t big[][256], int n, int w); -/* ========================================================================= */ -static void gf2_matrix_square(uint32_t *square, const uint32_t *mat) { - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} +static void write_table(const uint32_t *table, int k); +static void write_table32hi(const z_word_t *table, int k); +static void write_table64(const z_word_t *table, int k); -/* ========================================================================= +/* ========================================================================= */ +/* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials + with the lowest powers in the most significant bit. Then adding polynomials is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the + one. If we call the above polynomial p, and represent a byte as the polynomial q, also with the lowest power in the most significant bit (so the byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p, where a mod b means the remainder after dividing a by b. This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each + taking the remainder. The register is initialized to zero, and for each incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x + (which is shifting right by one and adding x^32 mod p if the bit shifted out + is a one). We start with the highest power (least significant bit) of q and + repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all the + information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. */ -static void make_crc_table(void) { - int n, k; - uint32_t c; - uint32_t poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static const unsigned char p[] = {0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26}; - - /* make exclusive-or pattern from polynomial (0xedb88320) */ - poly = 0; - for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) - poly |= (uint32_t)1 << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (uint32_t)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; +static void make_crc_table() { + unsigned i, j, n; + uint32_t p; + + /* initialize the CRC of bytes tables */ + for (i = 0; i < 256; i++) { + p = i; + for (j = 0; j < 8; j++) + p = p & 1 ? (p >> 1) ^ POLY : p >> 1; + crc_table[i] = p; + crc_big_table[i] = ZSWAP64(p); } - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = ZSWAP32(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = ZSWAP32(c); - } - } + /* initialize the x^2^n mod p(x) table */ + p = (uint32_t)1 << 30; /* x^1 */ + x2n_table[0] = p; + for (n = 1; n < 32; n++) + x2n_table[n] = p = multmodp(p, p); + + /* initialize the braiding tables -- needs x2n_table[] */ + braid(crc_braid_table, crc_braid_big_table, N, W); } -static void make_crc_combine_table(void) { - int n, k; - /* generate zero operators table for crc32_combine() */ - - /* generate the operator to apply a single zero bit to a CRC -- the - first row adds the polynomial if the low bit is a 1, and the - remaining rows shift the CRC right one bit */ - k = GF2_DIM - 3; - crc_comb[k][0] = 0xedb88320UL; /* CRC-32 polynomial */ - uint32_t row = 1; - for (n = 1; n < GF2_DIM; n++) { - crc_comb[k][n] = row; - row <<= 1; +/* + Generate the little and big-endian braid tables for the given n and z_word_t + size w. Each array must have room for w blocks of 256 elements. + */ +static void braid(uint32_t ltl[][256], z_word_t big[][256], int n, int w) { + int k; + uint32_t i, p, q; + for (k = 0; k < w; k++) { + p = x2nmodp((n * w + 3 - k) << 3, 0); + ltl[k][0] = 0; + big[w - 1 - k][0] = 0; + for (i = 1; i < 256; i++) { + ltl[k][i] = q = multmodp(i << 24, p); + big[w - 1 - k][i] = ZSWAP64(q); + } } - /* generate operators that apply 2, 4, and 8 zeros to a CRC, putting - the last one, the operator for one zero byte, at the 0 position */ - gf2_matrix_square(crc_comb[k + 1], crc_comb[k]); - gf2_matrix_square(crc_comb[k + 2], crc_comb[k + 1]); - gf2_matrix_square(crc_comb[0], crc_comb[k + 2]); - - /* generate operators for applying 2^n zero bytes to a CRC, filling out - the remainder of the table -- the operators repeat after GF2_DIM - values of n, so the table only needs GF2_DIM entries, regardless of - the size of the length being processed */ - for (n = 1; n < k; n++) - gf2_matrix_square(crc_comb[n], crc_comb[n - 1]); } +/* + Write the 32-bit values in table[0..k-1] to out, five per line in + hexadecimal separated by commas. + */ static void write_table(const uint32_t *table, int k) { int n; for (n = 0; n < k; n++) - printf("%s0x%08" PRIx32 "%s", n % 5 ? "" : " ", + printf("%s0x%08" PRIx32 "%s", n == 0 || n % 5 ? "" : " ", (uint32_t)(table[n]), - n == k - 1 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); } -static void print_crc_table(void) { - int k; - printf("#ifndef CRC32_TBL_H_\n"); - printf("#define CRC32_TBL_H_\n\n"); - printf("/* crc32_tbl.h -- tables for rapid CRC calculation\n"); - printf(" * Generated automatically by makecrct.c\n */\n\n"); +/* + Write the high 32-bits of each value in table[0..k-1] to out, five per line + in hexadecimal separated by commas. + */ +static void write_table32hi(const z_word_t *table, int k) { + int n; - /* print CRC table */ - printf("static const uint32_t "); - printf("crc_table[8][256] =\n{\n {\n"); - write_table(crc_table[0], 256); - for (k = 1; k < 8; k++) { - printf(" },\n {\n"); - write_table(crc_table[k], 256); - } - printf(" }\n};\n\n"); + for (n = 0; n < k; n++) + printf("%s0x%08" PRIx32 "%s", n == 0 || n % 5 ? "" : " ", + (uint32_t)(table[n] >> 32), + n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", ")); +} - printf("#endif /* CRC32_TBL_H_ */\n"); +/* + Write the 64-bit values in table[0..k-1] to out, three per line in + hexadecimal separated by commas. This assumes that if there is a 64-bit + type, then there is also a long long integer type, and it is at least 64 + bits. If not, then the type cast and format string can be adjusted + accordingly. + */ +static void write_table64(const z_word_t *table, int k) { + int n; + + for (n = 0; n < k; n++) + printf("%s0x%016" PRIx64 "%s", n == 0 || n % 3 ? "" : " ", + (uint64_t)(table[n]), + n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", ")); } -static void print_crc_combine_table(void) { - int k; - printf("#ifndef CRC32_COMB_TBL_H_\n"); - printf("#define CRC32_COMB_TBL_H_\n\n"); - printf("/* crc32_comb_tbl.h -- zero operators table for CRC combine\n"); +static void print_crc_table(void) { + int k, n; + uint32_t ltl[8][256]; + z_word_t big[8][256]; + + printf("#ifndef CRC32_BRAID_TBL_H_\n"); + printf("#define CRC32_BRAID_TBL_H_\n\n"); + printf("/* crc32_braid_tbl.h -- tables for braided CRC calculation\n"); printf(" * Generated automatically by makecrct.c\n */\n\n"); - /* print zero operator table */ - printf("static const uint32_t "); - printf("crc_comb[%d][%d] =\n{\n {\n", GF2_DIM, GF2_DIM); - write_table(crc_comb[0], GF2_DIM); - for (k = 1; k < GF2_DIM; k++) { - printf(" },\n {\n"); - write_table(crc_comb[k], GF2_DIM); + /* print little-endian CRC table */ + printf("static const uint32_t crc_table[] = {\n"); + printf(" "); + write_table(crc_table, 256); + printf("};\n\n"); + + /* print big-endian CRC table for 64-bit z_word_t */ + printf("#ifdef W\n\n"); + printf("#if W == 8\n\n"); + printf("static const z_word_t crc_big_table[] = {\n"); + printf(" "); + write_table64(crc_big_table, 256); + printf("};\n\n"); + + /* print big-endian CRC table for 32-bit z_word_t */ + printf("#else /* W == 4 */\n\n"); + printf("static const z_word_t crc_big_table[] = {\n"); + printf(" "); + write_table32hi(crc_big_table, 256); + printf("};\n\n"); + printf("#endif\n\n"); + printf("#endif /* W */\n\n"); + + /* write out braid tables for each value of N */ + for (n = 1; n <= 6; n++) { + printf("#if N == %d\n", n); + + /* compute braid tables for this N and 64-bit word_t */ + braid(ltl, big, n, 8); + + /* write out braid tables for 64-bit z_word_t */ + printf("\n"); + printf("#if W == 8\n\n"); + printf("static const uint32_t crc_braid_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + printf(" {"); + write_table(ltl[k], 256); + printf("}%s", k < 7 ? ",\n" : ""); + } + printf("};\n\n"); + printf("static const z_word_t crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 8; k++) { + printf(" {"); + write_table64(big[k], 256); + printf("}%s", k < 7 ? ",\n" : ""); + } + printf("};\n"); + + /* compute braid tables for this N and 32-bit word_t */ + braid(ltl, big, n, 4); + + /* write out braid tables for 32-bit z_word_t */ + printf("\n"); + printf("#else /* W == 4 */\n\n"); + printf("static const uint32_t crc_braid_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + printf(" {"); + write_table(ltl[k], 256); + printf("}%s", k < 3 ? ",\n" : ""); + } + printf("};\n\n"); + printf("static const z_word_t crc_braid_big_table[][256] = {\n"); + for (k = 0; k < 4; k++) { + printf(" {"); + write_table32hi(big[k], 256); + printf("}%s", k < 3 ? ",\n" : ""); + } + printf("};\n\n"); + printf("#endif /* W */\n\n"); + + printf("#endif /* N == %d */\n", n); } - printf(" }\n};\n\n"); + printf("\n"); + + /* write out zeros operator table */ + printf("static const uint32_t x2n_table[] = {\n"); + printf(" "); + write_table(x2n_table, 32); + printf("};\n"); - printf("#endif /* CRC32_COMB_TBL_H_ */\n"); + printf("\n"); + printf("#endif /* CRC32_BRAID_TBL_H_ */\n"); } -// The output of this application can be piped out to recreate crc32.h +// The output of this application can be piped out to recreate crc32 tables int main(int argc, char *argv[]) { - if (argc > 1 && strcmp(argv[1], "-c") == 0) { - make_crc_combine_table(); - print_crc_combine_table(); - } else { - make_crc_table(); - print_crc_table(); - } + Z_UNUSED(argc); + Z_UNUSED(argv); + + make_crc_table(); + print_crc_table(); return 0; } diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 5d5824bda3..efcb0a64cc 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -49,8 +49,8 @@ OBJS = \ compare256.obj \ compress.obj \ cpu_features.obj \ - crc32.obj \ - crc32_comb.obj \ + crc32_braid.obj \ + crc32_braid_comb.obj \ crc32_fold.obj \ deflate.obj \ deflate_fast.obj \ @@ -189,8 +189,8 @@ gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR) compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h -crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h +crc32_braid.obj: $(SRCDIR)/crc32_braid.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h +crc32_braid_comb.obj: $(SRCDIR)/crc32_braid_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h $(SRCDIR)/crc32_braid_comb_p.h crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 765bbb83ba..34dff1a700 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -53,8 +53,8 @@ OBJS = \ compare256.obj \ compress.obj \ cpu_features.obj \ - crc32.obj \ - crc32_comb.obj \ + crc32_braid.obj \ + crc32_braid_comb.obj \ crc32_fold.obj \ deflate.obj \ deflate_fast.obj \ @@ -202,8 +202,8 @@ compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h -crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h +crc32_braid.obj: $(SRCDIR)/crc32_braid.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h +crc32_braid_comb.obj: $(SRCDIR)/crc32_braid_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h $(SRCDIR)/crc32_braid_comb_p.h crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 8a398e4993..445b673bc3 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -65,8 +65,8 @@ OBJS = \ compare256_sse2.obj \ compress.obj \ cpu_features.obj \ - crc32.obj \ - crc32_comb.obj \ + crc32_braid.obj \ + crc32_braid_comb.obj \ crc32_fold.obj \ crc32_fold_pclmulqdq.obj \ deflate.obj \ @@ -208,8 +208,8 @@ chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_avx.obj: $(SRCDIR)/arch/x86/chunkset_avx.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_sse2.obj: $(SRCDIR)/arch/x86/chunkset_sse2.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h -crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h +crc32_braid.obj: $(SRCDIR)/crc32_braid.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h +crc32_braid_comb.obj: $(SRCDIR)/crc32_braid_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h $(SRCDIR)/crc32_braid_comb_p.h crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h crc32_fold_pclmulqdq.obj: $(SRCDIR)/arch/x86/crc32_fold_pclmulqdq.c $(SRCDIR)/crc32_fold.h $(SRCDIR)/zbuild.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 9274f75e6f..c059cd0917 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -1774,20 +1774,19 @@ uint32_t zng_crc32_combine(uint32_t crc1, uint32_t crc2, z_off64_t len2); */ Z_EXTERN Z_EXPORT -void zng_crc32_combine_gen(uint32_t op[32], z_off64_t len2); +uint32_t zng_crc32_combine_gen(z_off64_t len2); /* - Generate the operator op corresponding to length len2, to be used with - crc32_combine_op(). op must have room for 32 uint32_t values. (32 is the - number of bits in the CRC.) + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). */ Z_EXTERN Z_EXPORT -uint32_t zng_crc32_combine_op(uint32_t crc1, uint32_t crc2, const uint32_t *op); +uint32_t zng_crc32_combine_op(uint32_t crc1, uint32_t crc2, const uint32_t op); /* Give the same result as crc32_combine(), using op in place of len2. op is is generated from len2 by crc32_combine_gen(). This will be faster than - crc32_combine() if the generated op is used many times. + crc32_combine() if the generated op is used more than once. */ /* various hacks, don't look :) */ diff --git a/zlib.h.in b/zlib.h.in index 5dcba8e944..9de5e91b16 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -1732,19 +1732,18 @@ Z_EXTERN unsigned long Z_EXPORT crc32_combine(unsigned long crc1, unsigned long */ /* -Z_EXTERN void Z_EXPORT crc32_combine_gen(uint32_t op[32], z_off_t len2); +Z_EXTERN unsigned long Z_EXPORT crc32_combine_gen(z_off_t len2); - Generate the operator op corresponding to length len2, to be used with - crc32_combine_op(). op must have room for 32 z_crc_t values. (32 is the - number of bits in the CRC.) + Return the operator corresponding to length len2, to be used with + crc32_combine_op(). */ -Z_EXTERN uint32_t Z_EXPORT crc32_combine_op(uint32_t crc1, uint32_t crc2, - const uint32_t *op); +Z_EXTERN unsigned long Z_EXPORT crc32_combine_op(unsigned long crc1, unsigned long crc2, + const unsigned long op); /* Give the same result as crc32_combine(), using op in place of len2. op is is generated from len2 by crc32_combine_gen(). This will be faster than - crc32_combine() if the generated op is used many times. + crc32_combine() if the generated op is used more than once. */ @@ -1799,7 +1798,7 @@ Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ Z_EXTERN z_off64_t Z_EXPORT gzoffset64(gzFile); Z_EXTERN unsigned long Z_EXPORT adler32_combine64(unsigned long, unsigned long, z_off64_t); Z_EXTERN unsigned long Z_EXPORT crc32_combine64(unsigned long, unsigned long, z_off64_t); - Z_EXTERN void Z_EXPORT crc32_combine_gen64(uint32_t *op, z_off64_t); + Z_EXTERN unsigned long Z_EXPORT crc32_combine_gen64(z_off64_t); #endif #endif @@ -1818,7 +1817,7 @@ Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzoffset64(gzFile); Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@adler32_combine64(unsigned long, unsigned long, z_off_t); Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine64(unsigned long, unsigned long, z_off_t); - Z_EXTERN void Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64(uint32_t *op, z_off64_t); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64(z_off64_t); # endif #else # ifndef Z_SOLO @@ -1826,10 +1825,10 @@ Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzseek(gzFile, z_off_t, int); Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gztell(gzFile); Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzoffset(gzFile); -# endif +# endif Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@adler32_combine(unsigned long, unsigned long, z_off_t); Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine(unsigned long, unsigned long, z_off_t); - Z_EXTERN void Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen(uint32_t *op, z_off_t); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen(z_off_t); #endif /* undocumented functions */ From 8c945465c614788b5db043e0043d53c17f55de5a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 9 May 2022 23:42:00 -0700 Subject: [PATCH 409/798] Define W = 8 on powerpc64 for braided crc32 generation. --- crc32_braid_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crc32_braid_p.h b/crc32_braid_p.h index 28a8a9e7a9..80c0f14b9c 100644 --- a/crc32_braid_p.h +++ b/crc32_braid_p.h @@ -25,7 +25,7 @@ # endif #else # ifndef W -# if defined(__x86_64__) || defined(__aarch64__) +# if defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) # define W 8 # else # define W 4 From 0aacc11829406cf8c0057f71057a300a49ffc12d Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Tue, 10 May 2022 08:04:47 -0700 Subject: [PATCH 410/798] Correct comment for x2nmodp. --- crc32_braid_comb_p.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crc32_braid_comb_p.h b/crc32_braid_comb_p.h index 8a00cfa778..a269e7f5b7 100644 --- a/crc32_braid_comb_p.h +++ b/crc32_braid_comb_p.h @@ -23,7 +23,8 @@ static uint32_t multmodp(uint32_t a, uint32_t b) { } /* - Return x^(n+k) modulo p(x). Requires that x2n_table[] has been initialized. + Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been + initialized. */ static uint32_t x2nmodp(z_off64_t n, unsigned k) { uint32_t p; From 856884022cc7202b159ba76c8e89bb1d9f7300d5 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Tue, 10 May 2022 08:11:32 -0700 Subject: [PATCH 411/798] Correct incorrect inputs provided to the CRC functions. The previous releases of zlib were not sensitive to incorrect CRC inputs with bits set above the low 32. This commit restores that behavior, so that applications with such bugs will continue to operate as before. Co-authored-by: Nathan Moinvaziri --- crc32_braid.c | 4 ++-- crc32_braid_comb.c | 30 ++++++++++++------------------ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/crc32_braid.c b/crc32_braid.c index 3c3cedffbd..fee7992bb5 100644 --- a/crc32_braid.c +++ b/crc32_braid.c @@ -112,10 +112,10 @@ static z_word_t crc_word(z_word_t data) { /* ========================================================================= */ Z_INTERNAL uint32_t crc32_braid(uint32_t crc, const unsigned char *buf, uint64_t len) { - Z_REGISTER uint32_t c = crc; + Z_REGISTER uint32_t c; /* Pre-condition the CRC */ - c ^= 0xffffffff; + c = (~crc) & 0xffffffff; #ifdef W /* If provided enough bytes, do a braided CRC calculation. */ diff --git a/crc32_braid_comb.c b/crc32_braid_comb.c index 51ebf9d009..e33fccfd6d 100644 --- a/crc32_braid_comb.c +++ b/crc32_braid_comb.c @@ -17,31 +17,22 @@ static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) { return multmodp(x2nmodp(len2, 3), crc1) ^ crc2; } +static uint32_t crc32_combine_gen_(z_off64_t len2) { + return x2nmodp(len2, 3); +} +static uint32_t crc32_combine_op_(uint32_t crc1, uint32_t crc2, const uint32_t op) { + return multmodp(op, crc1) ^ crc2; +} /* ========================================================================= */ + #ifdef ZLIB_COMPAT unsigned long Z_EXPORT PREFIX(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off_t len2) { return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); } - unsigned long Z_EXPORT PREFIX4(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off64_t len2) { return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); } -#else -uint32_t Z_EXPORT PREFIX4(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off64_t len2) { - return crc32_combine_(crc1, crc2, len2); -} -#endif - -/* ========================================================================= */ - -static uint32_t crc32_combine_gen_(z_off64_t len2) { - return x2nmodp(len2, 3); -} - -/* ========================================================================= */ - -#ifdef ZLIB_COMPAT unsigned long Z_EXPORT PREFIX(crc32_combine_gen)(z_off_t len2) { return crc32_combine_gen_(len2); } @@ -49,14 +40,17 @@ unsigned long Z_EXPORT PREFIX4(crc32_combine_gen)(z_off64_t len2) { return crc32_combine_gen_(len2); } unsigned long Z_EXPORT PREFIX(crc32_combine_op)(unsigned long crc1, unsigned long crc2, const unsigned long op) { - return multmodp(op, crc1) ^ crc2; + return (unsigned long)crc32_combine_op_((uint32_t)crc1, (uint32_t)crc2, (uint32_t)op); } #else +uint32_t Z_EXPORT PREFIX4(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off64_t len2) { + return crc32_combine_(crc1, crc2, len2); +} uint32_t Z_EXPORT PREFIX(crc32_combine_gen)(z_off64_t len2) { return crc32_combine_gen_(len2); } uint32_t Z_EXPORT PREFIX(crc32_combine_op)(uint32_t crc1, uint32_t crc2, const uint32_t op) { - return multmodp(op, crc1) ^ crc2; + return crc32_combine_op_(crc1, crc2, op); } #endif From 19c649838ae7ae82b2cf4d81c9471c8deaac80ff Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 26 May 2022 23:39:04 +0500 Subject: [PATCH 412/798] Allow external gtest Signed-off-by: Vladislav Shchapov --- test/CMakeLists.txt | 57 ++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8b250ed780..fc06ce7ba0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,35 +18,38 @@ if(WITH_SANITIZER STREQUAL "Memory") add_compile_options(-stdlib=libc++ -g) endif() -# Prevent overriding the parent project's compiler/linker settings for Windows -set(gtest_force_shared_crt ON CACHE BOOL - "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) -# Disable pthreads for simplicity -set(gtest_disable_pthreads ON CACHE BOOL - "Disable uses of pthreads in gtest." FORCE) - -# Allow specifying alternative Google test repository -if(NOT DEFINED GTEST_REPOSITORY) - set(GTEST_REPOSITORY https://github.com/google/googletest.git) -endif() -if(NOT DEFINED GTEST_TAG) - # Use older version of Google test to support older versions of GCC - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3) - set(GTEST_TAG release-1.10.0) - else() - set(GTEST_TAG release-1.11.0) +if(NOT TARGET GTest::GTest) + # Prevent overriding the parent project's compiler/linker settings for Windows + set(gtest_force_shared_crt ON CACHE BOOL + "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) + # Disable pthreads for simplicity + set(gtest_disable_pthreads ON CACHE BOOL + "Disable uses of pthreads in gtest." FORCE) + + # Allow specifying alternative Google test repository + if(NOT DEFINED GTEST_REPOSITORY) + set(GTEST_REPOSITORY https://github.com/google/googletest.git) + endif() + if(NOT DEFINED GTEST_TAG) + # Use older version of Google test to support older versions of GCC + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3) + set(GTEST_TAG release-1.10.0) + else() + set(GTEST_TAG release-1.11.0) + endif() endif() -endif() -# Fetch Google test source code from official repository -FetchContent_Declare(googletest - GIT_REPOSITORY ${GTEST_REPOSITORY} - GIT_TAG ${GTEST_TAG}) + # Fetch Google test source code from official repository + FetchContent_Declare(googletest + GIT_REPOSITORY ${GTEST_REPOSITORY} + GIT_TAG ${GTEST_TAG}) -FetchContent_GetProperties(googletest) -if(NOT googletest_POPULATED) - FetchContent_Populate(googletest) - add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) + FetchContent_GetProperties(googletest) + if(NOT googletest_POPULATED) + FetchContent_Populate(googletest) + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() + add_library(GTest::GTest ALIAS gtest) endif() set(TEST_SRCS @@ -95,7 +98,7 @@ if(WITH_SANITIZER STREQUAL "Memory") -fsanitize-memory-track-origins) endif() -target_link_libraries(gtest_zlib zlibstatic gtest) +target_link_libraries(gtest_zlib zlibstatic GTest::GTest) if(ZLIB_ENABLE_TESTS) add_test(NAME gtest_zlib From 6038b6443257e725b3aa3b0bbeeb8ee01474a565 Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Fri, 27 May 2022 23:25:21 +0200 Subject: [PATCH 413/798] CMakeLists.txt: fix version in zlib.pc when building statically When building statically (i.e. with BUILD_SHARED_LIBS=OFF), ZLIB_FULL_VERSION is not set resulting in an empty version in zlib.pc and the following build failure with transmission: checking for ZLIB... configure: error: Package requirements (zlib >= 1.2.3) were not met: Package dependency requirement 'zlib >= 1.2.3' could not be satisfied. Package 'zlib' has version '', required version is '>= 1.2.3' Fixes: - http://autobuild.buildroot.org/results/b3b882482f517726e5c780ba4c37818bd379df82 Signed-off-by: Fabrice Fontaine --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a62a95ed18..6a26d597cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,8 +150,10 @@ if(ZLIB_COMPAT) add_definitions(-DZLIB_COMPAT) set(WITH_GZFILEOP ON) set(SUFFIX "") + set(ZLIB_FULL_VERSION ${ZLIB_HEADER_VERSION}.zlib-ng) else() set(SUFFIX "-ng") + set(ZLIB_FULL_VERSION ${ZLIBNG_HEADER_VERSION}) endif() if(WITH_GZFILEOP) @@ -1068,10 +1070,8 @@ if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) if(ZLIB_COMPAT) - set(ZLIB_FULL_VERSION ${ZLIB_HEADER_VERSION}.zlib-ng) set_target_properties(zlib PROPERTIES SOVERSION 1) else() - set(ZLIB_FULL_VERSION ${ZLIBNG_HEADER_VERSION}) set_target_properties(zlib PROPERTIES SOVERSION 2) endif() From c62b35ffac42940ba97af241140839cbc84f6f04 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 31 May 2022 15:58:17 +0300 Subject: [PATCH 414/798] [ARM] We need to include NEON headers when testing for -mfpu=neon. * If -mfpu is already specified in C_FLAGS, it can disable NEON support. --- cmake/detect-intrinsics.cmake | 7 ++++++- configure | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index c638b3bc26..1ddab22537 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -152,7 +152,12 @@ macro(check_neon_compiler_flag) # Check whether compiler supports NEON flag set(CMAKE_REQUIRED_FLAGS "${NEONFLAG} ${NATIVEFLAG}") check_c_source_compiles( - "int main() { return 0; }" + "#ifdef _M_ARM64 + # include + #else + # include + #endif + int main() { return 0; }" MFPU_NEON_AVAILABLE FAIL_REGEX "not supported") set(CMAKE_REQUIRED_FLAGS) endmacro() diff --git a/configure b/configure index b90c2342fc..26529dbb5c 100755 --- a/configure +++ b/configure @@ -1106,6 +1106,11 @@ EOF check_neon_compiler_flag() { # Check whether -mfpu=neon is available on ARM processors. cat > $test.c << EOF +#ifdef _M_ARM64 + # include + #else + # include +#endif int main() { return 0; } EOF if try $CC -c $CFLAGS -mfpu=neon $test.c; then From 2f4e2372a207bf9f56e62351455dacfb84c6d8d3 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 11 Feb 2022 11:11:04 +0100 Subject: [PATCH 415/798] Simplify zlib-ng native API by removing version and struct size checks. This should be backwards compatible with applications compiled for 2.0.x. --- deflate.c | 43 ++++++++++++++----- infback.c | 21 ++++++++-- inflate.c | 29 +++++++++++-- test/infcover.c | 5 +++ win32/zlib-ng.def.in | 10 ++--- zconf-ng.h.in | 3 ++ zconf.h.in | 3 ++ zlib-ng.h.in | 98 +++++++++++++++----------------------------- zlib-ng.map | 9 ++++ 9 files changed, 131 insertions(+), 90 deletions(-) diff --git a/deflate.c b/deflate.c index c2700f2b5f..369b17b5bb 100644 --- a/deflate.c +++ b/deflate.c @@ -53,6 +53,12 @@ #include "deflate_p.h" #include "functable.h" +/* Avoid conflicts with zlib.h macros */ +#ifdef ZLIB_COMPAT +# undef deflateInit +# undef deflateInit2 +#endif + const char PREFIX(deflate_copyright)[] = " deflate 1.2.11.f Copyright 1995-2016 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome @@ -181,24 +187,16 @@ static const config configuration_table[10] = { } while (0) /* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateInit_)(PREFIX3(stream) *strm, int32_t level, const char *version, int32_t stream_size) { - return PREFIX(deflateInit2_)(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); +/* This function is hidden in ZLIB_COMPAT builds. */ +int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level, int32_t method, int32_t windowBits, + int32_t memLevel, int32_t strategy) { /* Todo: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int32_t method, int32_t windowBits, - int32_t memLevel, int32_t strategy, const char *version, int32_t stream_size) { uint32_t window_padding = 0; deflate_state *s; int wrap = 1; - static const char my_version[] = PREFIX2(VERSION); cpu_check_features(); - if (version == NULL || version[0] != my_version[0] || stream_size != sizeof(PREFIX3(stream))) { - return Z_VERSION_ERROR; - } if (strm == NULL) return Z_STREAM_ERROR; @@ -319,6 +317,29 @@ int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int return PREFIX(deflateReset)(strm); } +#ifndef ZLIB_COMPAT +int32_t Z_EXPORT PREFIX(deflateInit)(PREFIX3(stream) *strm, int32_t level) { + return PREFIX(deflateInit2)(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +} +#endif + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(deflateInit_)(PREFIX3(stream) *strm, int32_t level, const char *version, int32_t stream_size) { + if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != sizeof(PREFIX3(stream))) { + return Z_VERSION_ERROR; + } + return PREFIX(deflateInit2)(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +} + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int32_t method, int32_t windowBits, + int32_t memLevel, int32_t strategy, const char *version, int32_t stream_size) { + if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != sizeof(PREFIX3(stream))) { + return Z_VERSION_ERROR; + } + return PREFIX(deflateInit2)(strm, level, method, windowBits, memLevel, strategy); +} + /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ diff --git a/infback.c b/infback.c index 5112a332b4..8002425721 100644 --- a/infback.c +++ b/infback.c @@ -18,19 +18,23 @@ #include "inflate_p.h" #include "functable.h" +/* Avoid conflicts with zlib.h macros */ +#ifdef ZLIB_COMPAT +# undef inflateBackInit +#endif + /* strm provides memory allocation functions in zalloc and zfree, or NULL to use the library memory allocation functions. windowBits is in the range 8..15, and window is a user-supplied window and output buffer that is 2**windowBits bytes. + + This function is hidden in ZLIB_COMPAT builds. */ -int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window, - const char *version, int32_t stream_size) { +int32_t ZNG_CONDEXPORT PREFIX(inflateBackInit)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window) { struct inflate_state *state; - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) - return Z_VERSION_ERROR; if (strm == NULL || window == NULL || windowBits < 8 || windowBits > 15) return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ @@ -55,6 +59,15 @@ int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowB return Z_OK; } +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window, + const char *version, int32_t stream_size) { + if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) { + return Z_VERSION_ERROR; + } + return PREFIX(inflateBackInit)(strm, windowBits, window); +} + /* Private macros for inflateBack() Look in inflate_p.h for macros shared with inflate() diff --git a/inflate.c b/inflate.c index b9c3aa7973..68531ab9aa 100644 --- a/inflate.c +++ b/inflate.c @@ -13,6 +13,12 @@ #include "inffixed_tbl.h" #include "functable.h" +/* Avoid conflicts with zlib.h macros */ +#ifdef ZLIB_COMPAT +# undef inflateInit +# undef inflateInit2 +#endif + /* function prototypes */ static int inflateStateCheck(PREFIX3(stream) *strm); static int updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t len, int32_t cksum); @@ -128,14 +134,13 @@ int32_t Z_EXPORT PREFIX(inflateReset2)(PREFIX3(stream) *strm, int32_t windowBits return PREFIX(inflateReset)(strm); } -int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits, const char *version, int32_t stream_size) { +/* This function is hidden in ZLIB_COMPAT builds. */ +int32_t ZNG_CONDEXPORT PREFIX(inflateInit2)(PREFIX3(stream) *strm, int32_t windowBits) { int32_t ret; struct inflate_state *state; cpu_check_features(); - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) - return Z_VERSION_ERROR; if (strm == NULL) return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ @@ -162,8 +167,24 @@ int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits return ret; } +#ifndef ZLIB_COMPAT +int32_t Z_EXPORT PREFIX(inflateInit)(PREFIX3(stream) *strm) { + return PREFIX(inflateInit2)(strm, DEF_WBITS); +} +#endif + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ int32_t Z_EXPORT PREFIX(inflateInit_)(PREFIX3(stream) *strm, const char *version, int32_t stream_size) { - return PREFIX(inflateInit2_)(strm, DEF_WBITS, version, stream_size); + if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) + return Z_VERSION_ERROR; + return PREFIX(inflateInit2)(strm, DEF_WBITS); +} + +/* Function used by zlib.h and zlib-ng version 2.0 macros */ +int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits, const char *version, int32_t stream_size) { + if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) + return Z_VERSION_ERROR; + return PREFIX(inflateInit2)(strm, windowBits); } int32_t Z_EXPORT PREFIX(inflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32_t value) { diff --git a/test/infcover.c b/test/infcover.c index 974185d0a3..63f5b3a29a 100644 --- a/test/infcover.c +++ b/test/infcover.c @@ -368,12 +368,14 @@ static void cover_support(void) { inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); +#ifdef ZLIB_COMPAT mem_setup(&strm); strm.avail_in = 0; strm.next_in = NULL; ret = PREFIX(inflateInit_)(&strm, &PREFIX2(VERSION)[1], (int)sizeof(PREFIX3(stream))); assert(ret == Z_VERSION_ERROR); mem_done(&strm, "wrong version"); +#endif strm.avail_in = 0; strm.next_in = NULL; @@ -474,8 +476,11 @@ static void cover_back(void) { PREFIX3(stream) strm; unsigned char win[32768]; +#ifdef ZLIB_COMPAT ret = PREFIX(inflateBackInit_)(NULL, 0, win, 0, 0); assert(ret == Z_VERSION_ERROR); +#endif + ret = PREFIX(inflateBackInit)(NULL, 0, win); assert(ret == Z_STREAM_ERROR); ret = PREFIX(inflateBack)(NULL, NULL, NULL, NULL, NULL); diff --git a/win32/zlib-ng.def.in b/win32/zlib-ng.def.in index 642acf7db6..53b2bc21f7 100644 --- a/win32/zlib-ng.def.in +++ b/win32/zlib-ng.def.in @@ -4,8 +4,13 @@ EXPORTS @ZLIB_SYMBOL_PREFIX@zlibng_version @ZLIB_SYMBOL_PREFIX@zng_deflate @ZLIB_SYMBOL_PREFIX@zng_deflateEnd + @ZLIB_SYMBOL_PREFIX@zng_deflateInit + @ZLIB_SYMBOL_PREFIX@zng_deflateInit2 @ZLIB_SYMBOL_PREFIX@zng_inflate @ZLIB_SYMBOL_PREFIX@zng_inflateEnd + @ZLIB_SYMBOL_PREFIX@zng_inflateInit + @ZLIB_SYMBOL_PREFIX@zng_inflateInit2 + @ZLIB_SYMBOL_PREFIX@zng_inflateBackInit ; advanced functions @ZLIB_SYMBOL_PREFIX@zng_deflateSetDictionary @ZLIB_SYMBOL_PREFIX@zng_deflateGetDictionary @@ -45,11 +50,6 @@ EXPORTS @ZLIB_SYMBOL_PREFIX@zng_adler32_combine @ZLIB_SYMBOL_PREFIX@zng_crc32_combine ; various hacks, don't look :) - @ZLIB_SYMBOL_PREFIX@zng_deflateInit_ - @ZLIB_SYMBOL_PREFIX@zng_deflateInit2_ - @ZLIB_SYMBOL_PREFIX@zng_inflateInit_ - @ZLIB_SYMBOL_PREFIX@zng_inflateInit2_ - @ZLIB_SYMBOL_PREFIX@zng_inflateBackInit_ @ZLIB_SYMBOL_PREFIX@zng_zError @ZLIB_SYMBOL_PREFIX@zng_inflateSyncPoint @ZLIB_SYMBOL_PREFIX@zng_get_crc_table diff --git a/zconf-ng.h.in b/zconf-ng.h.in index 21629c7b30..16fdcfa0fc 100644 --- a/zconf-ng.h.in +++ b/zconf-ng.h.in @@ -88,6 +88,9 @@ # define Z_EXPORTVA #endif +/* Conditional exports */ +#define ZNG_CONDEXPORT Z_EXPORT + /* Fallback for something that includes us. */ typedef unsigned char Byte; typedef Byte Bytef; diff --git a/zconf.h.in b/zconf.h.in index fef6bab42d..eea3c4ac7e 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -96,6 +96,9 @@ # define Z_EXPORTVA #endif +/* Conditional exports */ +#define ZNG_CONDEXPORT Z_INTERNAL + /* For backwards compatibility */ #ifndef ZEXTERN diff --git a/zlib-ng.h.in b/zlib-ng.h.in index c059cd0917..c46f776ae6 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -219,14 +219,12 @@ Z_EXTERN Z_EXPORT const char *zlibng_version(void); /* The application can compare zlibng_version and ZLIBNG_VERSION for consistency. If the first character differs, the library code actually used is not - compatible with the zlib-ng.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. + compatible with the zlib-ng.h header file used by the application. */ -/* Z_EXTERN Z_EXPORT -int zng_deflateInit(zng_stream *strm, int level); - +int32_t zng_deflateInit(zng_stream *strm, int32_t level); +/* Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to NULL, deflateInit updates them to use default @@ -239,11 +237,9 @@ int zng_deflateInit(zng_stream *strm, int level); equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zng_version) is incompatible - with the version assumed by the caller (ZLIBNG_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). + memory, Z_STREAM_ERROR if level is not a valid compression level. + msg is set to null if there is no error message. deflateInit does not perform + any compression: this will be done by deflate(). */ @@ -376,10 +372,9 @@ int32_t zng_deflateEnd(zng_stream *strm); */ -/* Z_EXTERN Z_EXPORT -int zng_inflateInit(zng_stream *strm); - +int32_t zng_inflateInit(zng_stream *strm); +/* Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. In the current version of inflate, the provided input is not @@ -389,14 +384,13 @@ int zng_inflateInit(zng_stream *strm); them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression. - Actual decompression will be done by inflate(). So next_in, and avail_in, - next_out, and avail_out are unused and unchanged. The current - implementation of inflateInit() does not process any header information -- - that is deferred until inflate() is called. + memory, or Z_STREAM_ERROR if the parameters are invalid, such as a null + pointer to the structure. msg is set to null if there is no error message. + inflateInit does not perform any decompression. Actual decompression will + be done by inflate(). So next_in, and avail_in, next_out, and avail_out + are unused and unchanged. The current implementation of inflateInit() + does not process any header information -- that is deferred until inflate() + is called. */ @@ -539,10 +533,9 @@ int32_t zng_inflateEnd(zng_stream *strm); The following functions are needed only in some special applications. */ -/* Z_EXTERN Z_EXPORT -int zng_deflateInit2(zng_stream *strm, int level, int method, int windowBits, int memLevel, int strategy); - +int32_t zng_deflateInit2(zng_stream *strm, int32_t level, int32_t method, int32_t windowBits, int32_t memLevel, int32_t strategy); +/* This is another version of deflateInit with more compression options. The fields zalloc, zfree and opaque must be initialized before by the caller. @@ -601,11 +594,9 @@ int zng_deflateInit2(zng_stream *strm, int level, int method, int windowBits, decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zng_version) is - incompatible with the version assumed by the caller (ZLIBNG_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid method). + msg is set to null if there is no error message. deflateInit2 does not perform + any compression: this will be done by deflate(). */ Z_EXTERN Z_EXPORT @@ -822,10 +813,9 @@ int32_t zng_deflateSetHeader(zng_stream *strm, zng_gz_headerp head); stream state was inconsistent. */ -/* Z_EXTERN Z_EXPORT -int zng_inflateInit2(zng_stream *strm, int windowBits); - +int32_t zng_inflateInit2(zng_stream *strm, int32_t windowBits); +/* This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. @@ -866,15 +856,13 @@ int zng_inflateInit2(zng_stream *strm, int windowBits); decompression to be compliant with the gzip standard (RFC 1952). inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. + memory, or Z_STREAM_ERROR if the parameters are invalid, such as a null + pointer to the structure. msg is set to null if there is no error message. + inflateInit2 does not perform any decompression apart from possibly reading + the zlib header if present: actual decompression will be done by inflate(). + (So next_in and avail_in may be modified, but next_out and avail_out are + unused and unchanged.) The current implementation of inflateInit2() does not + process any header information -- that is deferred until inflate() is called. */ Z_EXTERN Z_EXPORT @@ -1063,10 +1051,9 @@ int32_t zng_inflateGetHeader(zng_stream *strm, zng_gz_headerp head); stream state was inconsistent. */ -/* Z_EXTERN Z_EXPORT -int zng_inflateBackInit(zng_stream *strm, int windowBits, unsigned char *window); - +int32_t zng_inflateBackInit(zng_stream *strm, int32_t windowBits, uint8_t *window); +/* Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are NULL, then the default library- @@ -1081,8 +1068,7 @@ int zng_inflateBackInit(zng_stream *strm, int windowBits, unsigned char *window) inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the parameters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. + allocated. */ typedef uint32_t (*in_func) (void *, const uint8_t * *); @@ -1791,26 +1777,6 @@ uint32_t zng_crc32_combine_op(uint32_t crc1, uint32_t crc2, const uint32_t op); /* various hacks, don't look :) */ -/* zng_deflateInit and zng_inflateInit are macros to allow checking the zlib version - * and the compiler's view of zng_stream: - */ -Z_EXTERN Z_EXPORT int32_t zng_deflateInit_(zng_stream *strm, int32_t level, const char *version, int32_t stream_size); -Z_EXTERN Z_EXPORT int32_t zng_inflateInit_(zng_stream *strm, const char *version, int32_t stream_size); -Z_EXTERN Z_EXPORT int32_t zng_deflateInit2_(zng_stream *strm, int32_t level, int32_t method, int32_t windowBits, int32_t memLevel, - int32_t strategy, const char *version, int32_t stream_size); -Z_EXTERN Z_EXPORT int32_t zng_inflateInit2_(zng_stream *strm, int32_t windowBits, const char *version, int32_t stream_size); -Z_EXTERN Z_EXPORT int32_t zng_inflateBackInit_(zng_stream *strm, int32_t windowBits, uint8_t *window, - const char *version, int32_t stream_size); - -#define @ZLIB_SYMBOL_PREFIX@zng_deflateInit(strm, level) zng_deflateInit_((strm), (level), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define @ZLIB_SYMBOL_PREFIX@zng_inflateInit(strm) zng_inflateInit_((strm), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define @ZLIB_SYMBOL_PREFIX@zng_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - zng_deflateInit2_((strm), (level), (method), (windowBits), (memLevel), \ - (strategy), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define @ZLIB_SYMBOL_PREFIX@zng_inflateInit2(strm, windowBits) zng_inflateInit2_((strm), (windowBits), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define @ZLIB_SYMBOL_PREFIX@zng_inflateBackInit(strm, windowBits, window) \ - zng_inflateBackInit_((strm), (windowBits), (window), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) - #ifdef WITH_GZFILEOP /* gzgetc() macro and its supporting function and exposed data structure. Note diff --git a/zlib-ng.map b/zlib-ng.map index 461c2566e1..5ac114731c 100644 --- a/zlib-ng.map +++ b/zlib-ng.map @@ -1,3 +1,12 @@ +ZLIB_NG_2.1.0 { + global: + zng_deflateInit; + zng_deflateInit2; + zng_inflateBackInit; + zng_inflateInit; + zng_inflateInit2; +}; + ZLIB_NG_2.0.0 { global: zng_adler32; From 28b029c7261e2bff16d66b3cc138241db5e837c2 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 11 Feb 2022 12:08:43 +0100 Subject: [PATCH 416/798] Simplify version and struct size checking, and ensure we do it the same way everywhere. --- deflate.c | 6 ++---- infback.c | 3 +-- inflate.c | 4 ++-- zutil.h | 4 ++++ 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/deflate.c b/deflate.c index 369b17b5bb..878033355c 100644 --- a/deflate.c +++ b/deflate.c @@ -325,18 +325,16 @@ int32_t Z_EXPORT PREFIX(deflateInit)(PREFIX3(stream) *strm, int32_t level) { /* Function used by zlib.h and zlib-ng version 2.0 macros */ int32_t Z_EXPORT PREFIX(deflateInit_)(PREFIX3(stream) *strm, int32_t level, const char *version, int32_t stream_size) { - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != sizeof(PREFIX3(stream))) { + if (CHECK_VER_STSIZE(version, stream_size)) return Z_VERSION_ERROR; - } return PREFIX(deflateInit2)(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); } /* Function used by zlib.h and zlib-ng version 2.0 macros */ int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int32_t method, int32_t windowBits, int32_t memLevel, int32_t strategy, const char *version, int32_t stream_size) { - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != sizeof(PREFIX3(stream))) { + if (CHECK_VER_STSIZE(version, stream_size)) return Z_VERSION_ERROR; - } return PREFIX(deflateInit2)(strm, level, method, windowBits, memLevel, strategy); } diff --git a/infback.c b/infback.c index 8002425721..dd549a89fb 100644 --- a/infback.c +++ b/infback.c @@ -62,9 +62,8 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateBackInit)(PREFIX3(stream) *strm, int32_t wi /* Function used by zlib.h and zlib-ng version 2.0 macros */ int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window, const char *version, int32_t stream_size) { - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) { + if (CHECK_VER_STSIZE(version, stream_size)) return Z_VERSION_ERROR; - } return PREFIX(inflateBackInit)(strm, windowBits, window); } diff --git a/inflate.c b/inflate.c index 68531ab9aa..6192148233 100644 --- a/inflate.c +++ b/inflate.c @@ -175,14 +175,14 @@ int32_t Z_EXPORT PREFIX(inflateInit)(PREFIX3(stream) *strm) { /* Function used by zlib.h and zlib-ng version 2.0 macros */ int32_t Z_EXPORT PREFIX(inflateInit_)(PREFIX3(stream) *strm, const char *version, int32_t stream_size) { - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) + if (CHECK_VER_STSIZE(version, stream_size)) return Z_VERSION_ERROR; return PREFIX(inflateInit2)(strm, DEF_WBITS); } /* Function used by zlib.h and zlib-ng version 2.0 macros */ int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits, const char *version, int32_t stream_size) { - if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) + if (CHECK_VER_STSIZE(version, stream_size)) return Z_VERSION_ERROR; return PREFIX(inflateInit2)(strm, windowBits); } diff --git a/zutil.h b/zutil.h index f70eb4bdbb..53c7cdf148 100644 --- a/zutil.h +++ b/zutil.h @@ -120,6 +120,10 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ # define OS_CODE 3 /* assume Unix */ #endif + /* macros */ + +#define CHECK_VER_STSIZE(_ver,_stsize) ((_ver) == NULL || (_ver)[0] != PREFIX2(VERSION)[0] || (_stsize) != (int32_t)sizeof(PREFIX3(stream))) + /* memory allocation functions */ void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size); From 4fe1affc6d0ef240c071e950f5127a482646c681 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 11 Feb 2022 13:49:28 +0100 Subject: [PATCH 417/798] Remove zng_gzgetc_ function from zlib-ng native API. It exists in zlib for backwards compatibility, but has never been documented/advertised for use in zlib-ngs native API. --- gzread.c.in | 2 ++ zlib-ng.h.in | 1 - zlib-ng.map | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gzread.c.in b/gzread.c.in index 3e1dc1d132..f17a5f8880 100644 --- a/gzread.c.in +++ b/gzread.c.in @@ -432,9 +432,11 @@ int Z_EXPORT PREFIX(gzgetc)(gzFile file) { return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; } +#ifdef ZLIB_COMPAT int Z_EXPORT PREFIX(gzgetc_)(gzFile file) { return PREFIX(gzgetc)(file); } +#endif /* -- see zlib.h -- */ int Z_EXPORT PREFIX(gzungetc)(int c, gzFile file) { diff --git a/zlib-ng.h.in b/zlib-ng.h.in index c46f776ae6..38a5225f7b 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -1791,7 +1791,6 @@ struct gzFile_s { unsigned char *next; z_off64_t pos; }; -Z_EXTERN Z_EXPORT int32_t zng_gzgetc_(gzFile file); /* backward compatibility */ # define @ZLIB_SYMBOL_PREFIX@zng_gzgetc(g) ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (@ZLIB_SYMBOL_PREFIX@zng_gzgetc)(g)) #endif /* WITH_GZFILEOP */ diff --git a/zlib-ng.map b/zlib-ng.map index 5ac114731c..aa29a54ef6 100644 --- a/zlib-ng.map +++ b/zlib-ng.map @@ -93,7 +93,6 @@ ZLIB_NG_GZ_2.0.0 { zng_gzfread; zng_gzfwrite; zng_gzgetc; - zng_gzgetc_; zng_gzgets; zng_gzoffset; zng_gzoffset64; From 843c16c87afd53a20bf915661012b02acdd30281 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 14 Apr 2022 19:49:32 -0700 Subject: [PATCH 418/798] Move crc32 fold functions into templates. Don't store xmm_crc_part between runs because it is automatically folded into the checksum in partial_fold. Co-authored-by: Adam Stylinski --- arch/x86/crc32_fold_pclmulqdq.c | 275 ++------------------------- arch/x86/crc32_fold_pclmulqdq_tpl.h | 189 ++++++++++++++++++ arch/x86/crc32_fold_vpclmulqdq.c | 197 +------------------ arch/x86/crc32_fold_vpclmulqdq_tpl.h | 116 +++++++++++ cpu_features.h | 6 +- crc32_fold.h | 4 +- functable.c | 6 +- 7 files changed, 329 insertions(+), 464 deletions(-) create mode 100644 arch/x86/crc32_fold_pclmulqdq_tpl.h create mode 100644 arch/x86/crc32_fold_vpclmulqdq_tpl.h diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 6bb2c985cc..01c753b485 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -33,10 +33,10 @@ #ifdef X86_VPCLMULQDQ_CRC extern size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len); -extern size_t fold_16_vpclmulqdq_nocp(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, __m128i init_crc, int32_t first); +extern size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len); #endif static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { @@ -245,271 +245,19 @@ static inline void crc32_fold_save(__m128i *fold, __m128i fold0, __m128i fold1, _mm_storeu_si128(fold + 3, fold3); } -static inline void crc32_fold_save_partial(__m128i *fold, __m128i foldp) { - _mm_store_si128(fold + 4, foldp); -} - -Z_INTERNAL uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc) { +Z_INTERNAL uint32_t crc32_fold_pclmulqdq_reset(crc32_fold *crc) { __m128i xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); __m128i xmm_zero = _mm_setzero_si128(); crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_zero, xmm_zero, xmm_zero); return 0; } -Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { - unsigned long algn_diff; - __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; - __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3, xmm_crc_part; - char ALIGNED_(16) partial_buf[16] = { 0 }; - - crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - if (len < 16) { - if (len == 0) - return; - - memcpy(partial_buf, src, len); - xmm_crc_part = _mm_load_si128((const __m128i *)partial_buf); - memcpy(dst, partial_buf, len); - goto partial; - } - - algn_diff = ((uintptr_t)16 - ((uintptr_t)src & 0xF)) & 0xF; - if (algn_diff) { - xmm_crc_part = _mm_loadu_si128((__m128i *)src); - _mm_storeu_si128((__m128i *)dst, xmm_crc_part); - - dst += algn_diff; - src += algn_diff; - len -= algn_diff; - - partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); - } else { - xmm_crc_part = _mm_setzero_si128(); - } - -#ifdef X86_VPCLMULQDQ_CRC - if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { - size_t n = fold_16_vpclmulqdq(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); - - len -= n; - src += n; - dst += n; - } -#endif - - while (len >= 64) { - crc32_fold_load((__m128i *)src, &xmm_t0, &xmm_t1, &xmm_t2, &xmm_t3); - - fold_4(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - crc32_fold_save((__m128i *)dst, xmm_t0, xmm_t1, xmm_t2, xmm_t3); - - xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); - xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); - - src += 64; - dst += 64; - len -= 64; - } - - /* - * len = num bytes left - 64 - */ - if (len >= 48) { - xmm_t0 = _mm_load_si128((__m128i *)src); - xmm_t1 = _mm_load_si128((__m128i *)src + 1); - xmm_t2 = _mm_load_si128((__m128i *)src + 2); - - fold_3(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - _mm_storeu_si128((__m128i *)dst, xmm_t0); - _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); - _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); - - xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); - len -= 48; - if (len == 0) - goto done; - - dst += 48; - memcpy(&xmm_crc_part, (__m128i *)src + 3, len); - } else if (len >= 32) { - xmm_t0 = _mm_load_si128((__m128i *)src); - xmm_t1 = _mm_load_si128((__m128i *)src + 1); - - fold_2(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - _mm_storeu_si128((__m128i *)dst, xmm_t0); - _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); - - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); +#define ONCE(op) if (first) { first = 0; op; } +#define XOR_INITIAL(where) ONCE(where = _mm_xor_si128(where, xmm_initial)) - len -= 32; - if (len == 0) - goto done; - - dst += 32; - memcpy(&xmm_crc_part, (__m128i *)src + 2, len); - } else if (len >= 16) { - xmm_t0 = _mm_load_si128((__m128i *)src); - - fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - _mm_storeu_si128((__m128i *)dst, xmm_t0); - - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); - - len -= 16; - if (len == 0) - goto done; - - dst += 16; - memcpy(&xmm_crc_part, (__m128i *)src + 1, len); - } else { - if (len == 0) - goto done; - memcpy(&xmm_crc_part, src, len); - } - - _mm_storeu_si128((__m128i *)partial_buf, xmm_crc_part); - memcpy(dst, partial_buf, len); - -partial: - partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); -done: - crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3); - crc32_fold_save_partial((__m128i *)crc->fold, xmm_crc_part); -} - -#define ONCE(op) if (first) { \ - first = 0; \ - (op); \ -} -#define XOR_INITIAL(where) ONCE(where = _mm_xor_si128(where, xmm_initial)) - -Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { - unsigned long algn_diff; - __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; - __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3, xmm_crc_part; - __m128i xmm_initial = _mm_cvtsi32_si128(init_crc); - xmm_crc_part = _mm_setzero_si128(); - int32_t first = init_crc != 0; - - /* Technically the CRC functions don't even call this for input < 64, but a bare minimum of 31 - * bytes of input is needed for the aligning load that occurs. If there's an initial CRC, to - * carry it forward through the folded CRC there must be 16 - src % 16 + 16 bytes available, which - * by definition can be up to 15 bytes + one full vector load. */ - assert(len >= 31 || first == 0); - crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - if (len < 16) { - goto partial_nocpy; - } - - algn_diff = ((uintptr_t)16 - ((uintptr_t)src & 0xF)) & 0xF; - if (algn_diff) { - if (algn_diff >= 4 || init_crc == 0) { - xmm_crc_part = _mm_loadu_si128((__m128i *)src); - - src += algn_diff; - len -= algn_diff; - - XOR_INITIAL(xmm_crc_part); - partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); - } else { - xmm_t0 = _mm_loadu_si128((__m128i*)src); - xmm_crc_part = _mm_loadu_si128((__m128i*)src + 1); - XOR_INITIAL(xmm_t0); - fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); - partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); - - src += (algn_diff + 16); - len -= (algn_diff + 16); - } - - xmm_crc_part = _mm_setzero_si128(); - } - -#ifdef X86_VPCLMULQDQ_CRC - if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { - size_t n = fold_16_vpclmulqdq_nocp(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, src, len, - xmm_initial, first); - first = 0; - - len -= n; - src += n; - } -#endif - - while (len >= 64) { - crc32_fold_load((__m128i *)src, &xmm_t0, &xmm_t1, &xmm_t2, &xmm_t3); - XOR_INITIAL(xmm_t0); - fold_4(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); - xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); - - src += 64; - len -= 64; - } - - /* - * len = num bytes left - 64 - */ - if (len >= 48) { - xmm_t0 = _mm_load_si128((__m128i *)src); - xmm_t1 = _mm_load_si128((__m128i *)src + 1); - xmm_t2 = _mm_load_si128((__m128i *)src + 2); - XOR_INITIAL(xmm_t0); - - fold_3(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); - len -= 48; - src += 48; - } else if (len >= 32) { - xmm_t0 = _mm_load_si128((__m128i *)src); - xmm_t1 = _mm_load_si128((__m128i *)src + 1); - XOR_INITIAL(xmm_t0); - - fold_2(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); - - len -= 32; - src += 32; - } else if (len >= 16) { - xmm_t0 = _mm_load_si128((__m128i *)src); - XOR_INITIAL(xmm_t0); - - fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - - xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); - - len -= 16; - src += 16; - } - -partial_nocpy: - if (len) { - memcpy(&xmm_crc_part, src, len); - partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); - } - - crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3); -} +#include "crc32_fold_pclmulqdq_tpl.h" +#define COPY +#include "crc32_fold_pclmulqdq_tpl.h" static const unsigned ALIGNED_(16) crc_k[] = { 0xccaa009e, 0x00000000, /* rk1 */ @@ -528,7 +276,7 @@ static const unsigned ALIGNED_(16) crc_mask2[4] = { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; -Z_INTERNAL uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc) { +Z_INTERNAL uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc) { const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3; @@ -600,9 +348,8 @@ uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len) return crc32_braid(crc32, buf, len); crc32_fold ALIGNED_(16) crc_state; - crc32_fold_reset_pclmulqdq(&crc_state); + crc32_fold_pclmulqdq_reset(&crc_state); crc32_fold_pclmulqdq(&crc_state, buf, len, crc32); - return crc32_fold_final_pclmulqdq(&crc_state); + return crc32_fold_pclmulqdq_final(&crc_state); } - #endif diff --git a/arch/x86/crc32_fold_pclmulqdq_tpl.h b/arch/x86/crc32_fold_pclmulqdq_tpl.h new file mode 100644 index 0000000000..12681b8025 --- /dev/null +++ b/arch/x86/crc32_fold_pclmulqdq_tpl.h @@ -0,0 +1,189 @@ +/* + * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ + * instruction. + * + * A white paper describing this algorithm can be found at: + * https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Copyright (C) 2016 Marian Beermann (support for initial value) + * Authors: + * Wajdi Feghali + * Jim Guilford + * Vinodh Gopal + * Erdinc Ozturk + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef X86_PCLMULQDQ_CRC + +#ifdef COPY +Z_INTERNAL void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { +#else +Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { +#endif + unsigned long algn_diff; + __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; + __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3; + __m128i xmm_crc_part = _mm_setzero_si128(); +#ifdef COPY + char ALIGNED_(16) partial_buf[16] = { 0 }; +#else + __m128i xmm_initial = _mm_cvtsi32_si128(init_crc); + int32_t first = init_crc != 0; + + /* Technically the CRC functions don't even call this for input < 64, but a bare minimum of 31 + * bytes of input is needed for the aligning load that occurs. If there's an initial CRC, to + * carry it forward through the folded CRC there must be 16 - src % 16 + 16 bytes available, which + * by definition can be up to 15 bytes + one full vector load. */ + assert(len >= 31 || first == 0); +#endif + crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + if (len < 16) { +#ifdef COPY + if (len == 0) + return; + + memcpy(partial_buf, src, len); + xmm_crc_part = _mm_load_si128((const __m128i *)partial_buf); + memcpy(dst, partial_buf, len); +#endif + goto partial; + } + + algn_diff = ((uintptr_t)16 - ((uintptr_t)src & 0xF)) & 0xF; + if (algn_diff) { + xmm_crc_part = _mm_loadu_si128((__m128i *)src); +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_crc_part); + dst += algn_diff; +#else + XOR_INITIAL(xmm_crc_part); + + if (algn_diff < 4 && init_crc != 0) { + xmm_t0 = xmm_crc_part; + xmm_crc_part = _mm_loadu_si128((__m128i*)src + 1); + fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + src += 16; + len -= 16; + } +#endif + + partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + + src += algn_diff; + len -= algn_diff; + } + +#ifdef X86_VPCLMULQDQ_CRC + if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { +#ifdef COPY + size_t n = fold_16_vpclmulqdq_copy(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); + dst += n; +#else + size_t n = fold_16_vpclmulqdq(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, src, len, + xmm_initial, first); + first = 0; +#endif + len -= n; + src += n; + } +#endif + + while (len >= 64) { + len -= 64; + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + xmm_t3 = _mm_load_si128((__m128i *)src + 3); + src += 64; + + fold_4(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); + _mm_storeu_si128((__m128i *)dst + 3, xmm_t3); + dst += 64; +#else + XOR_INITIAL(xmm_t0); +#endif + + xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); + } + + /* + * len = num bytes left - 64 + */ + if (len >= 48) { + len -= 48; + + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + src += 48; +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); + dst += 48; +#else + XOR_INITIAL(xmm_t0); +#endif + fold_3(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); + } else if (len >= 32) { + len -= 32; + + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + src += 32; +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_t0); + _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); + dst += 32; +#else + XOR_INITIAL(xmm_t0); +#endif + fold_2(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); + } else if (len >= 16) { + len -= 16; + xmm_t0 = _mm_load_si128((__m128i *)src); + src += 16; +#ifdef COPY + _mm_storeu_si128((__m128i *)dst, xmm_t0); + dst += 16; +#else + XOR_INITIAL(xmm_t0); +#endif + fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + } + +partial: + if (len) { + memcpy(&xmm_crc_part, src, len); +#ifdef COPY + _mm_storeu_si128((__m128i *)partial_buf, xmm_crc_part); + memcpy(dst, partial_buf, len); +#endif + partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + } + + crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3); +} +#endif diff --git a/arch/x86/crc32_fold_vpclmulqdq.c b/arch/x86/crc32_fold_vpclmulqdq.c index dfcdc8a8cc..d9c43be742 100644 --- a/arch/x86/crc32_fold_vpclmulqdq.c +++ b/arch/x86/crc32_fold_vpclmulqdq.c @@ -9,198 +9,11 @@ #include -#define ONCE(op) if (first) { \ - first = 0; \ - (op); \ -} -#define XOR_INITIAL(where) ONCE(where = _mm512_xor_si512(where, zmm_initial)) +#define ONCE(op) if (first) { first = 0; op; } +#define XOR_INITIAL(where) ONCE(where = _mm512_xor_si512(where, zmm_initial)) -size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len) { - size_t len_tmp = len; - __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; - __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; - __m512i z0, z1, z2, z3; - const __m512i zmm_fold4 = _mm512_set4_epi32( - 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); - const __m512i zmm_fold16 = _mm512_set4_epi32( - 0x00000001, 0x1542778a, 0x00000001, 0x322d1430); +#include "crc32_fold_vpclmulqdq_tpl.h" +#define COPY +#include "crc32_fold_vpclmulqdq_tpl.h" - // zmm register init - zmm_crc0 = _mm512_setzero_si512(); - zmm_t0 = _mm512_loadu_si512((__m512i *)src); - zmm_crc1 = _mm512_loadu_si512((__m512i *)src + 1); - zmm_crc2 = _mm512_loadu_si512((__m512i *)src + 2); - zmm_crc3 = _mm512_loadu_si512((__m512i *)src + 3); - - /* already have intermediate CRC in xmm registers - * fold4 with 4 xmm_crc to get zmm_crc0 - */ - zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc0, 0); - zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc1, 1); - zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc2, 2); - zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc3, 3); - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); - - _mm512_storeu_si512((__m512i *)dst, zmm_t0); - _mm512_storeu_si512((__m512i *)dst + 1, zmm_crc1); - _mm512_storeu_si512((__m512i *)dst + 2, zmm_crc2); - _mm512_storeu_si512((__m512i *)dst + 3, zmm_crc3); - len -= 256; - src += 256; - dst += 256; - - // fold-16 loops - while (len >= 256) { - zmm_t0 = _mm512_loadu_si512((__m512i *)src); - zmm_t1 = _mm512_loadu_si512((__m512i *)src + 1); - zmm_t2 = _mm512_loadu_si512((__m512i *)src + 2); - zmm_t3 = _mm512_loadu_si512((__m512i *)src + 3); - - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x01); - z1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x01); - z2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x01); - z3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x01); - - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x10); - zmm_crc1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x10); - zmm_crc2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x10); - zmm_crc3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x10); - - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc1 = _mm512_xor_si512(z1, zmm_crc1); - zmm_crc2 = _mm512_xor_si512(z2, zmm_crc2); - zmm_crc3 = _mm512_xor_si512(z3, zmm_crc3); - - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); - zmm_crc1 = _mm512_xor_si512(zmm_crc1, zmm_t1); - zmm_crc2 = _mm512_xor_si512(zmm_crc2, zmm_t2); - zmm_crc3 = _mm512_xor_si512(zmm_crc3, zmm_t3); - - _mm512_storeu_si512((__m512i *)dst, zmm_t0); - _mm512_storeu_si512((__m512i *)dst + 1, zmm_t1); - _mm512_storeu_si512((__m512i *)dst + 2, zmm_t2); - _mm512_storeu_si512((__m512i *)dst + 3, zmm_t3); - len -= 256; - src += 256; - dst += 256; - } - // zmm_crc[0,1,2,3] -> zmm_crc0 - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc1); - - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc2); - - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc3); - - // zmm_crc0 -> xmm_crc[0, 1, 2, 3] - *xmm_crc0 = _mm512_extracti32x4_epi32(zmm_crc0, 0); - *xmm_crc1 = _mm512_extracti32x4_epi32(zmm_crc0, 1); - *xmm_crc2 = _mm512_extracti32x4_epi32(zmm_crc0, 2); - *xmm_crc3 = _mm512_extracti32x4_epi32(zmm_crc0, 3); - - return (len_tmp - len); // return n bytes processed -} - -size_t fold_16_vpclmulqdq_nocp(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, - __m128i init_crc, int32_t first) { - size_t len_tmp = len; - __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; - __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; - __m512i z0, z1, z2, z3; - __m512i zmm_initial = _mm512_zextsi128_si512(init_crc); - const __m512i zmm_fold4 = _mm512_set4_epi32( - 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); - const __m512i zmm_fold16 = _mm512_set4_epi32( - 0x00000001, 0x1542778a, 0x00000001, 0x322d1430); - - // zmm register init - zmm_crc0 = _mm512_setzero_si512(); - zmm_t0 = _mm512_loadu_si512((__m512i *)src); - XOR_INITIAL(zmm_t0); - zmm_crc1 = _mm512_loadu_si512((__m512i *)src + 1); - zmm_crc2 = _mm512_loadu_si512((__m512i *)src + 2); - zmm_crc3 = _mm512_loadu_si512((__m512i *)src + 3); - - /* already have intermediate CRC in xmm registers - * fold4 with 4 xmm_crc to get zmm_crc0 - */ - zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc0, 0); - zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc1, 1); - zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc2, 2); - zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc3, 3); - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); - - len -= 256; - src += 256; - - // fold-16 loops - while (len >= 256) { - zmm_t0 = _mm512_loadu_si512((__m512i *)src); - zmm_t1 = _mm512_loadu_si512((__m512i *)src + 1); - zmm_t2 = _mm512_loadu_si512((__m512i *)src + 2); - zmm_t3 = _mm512_loadu_si512((__m512i *)src + 3); - - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x01); - z1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x01); - z2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x01); - z3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x01); - - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x10); - zmm_crc1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x10); - zmm_crc2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x10); - zmm_crc3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x10); - - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc1 = _mm512_xor_si512(z1, zmm_crc1); - zmm_crc2 = _mm512_xor_si512(z2, zmm_crc2); - zmm_crc3 = _mm512_xor_si512(z3, zmm_crc3); - - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); - zmm_crc1 = _mm512_xor_si512(zmm_crc1, zmm_t1); - zmm_crc2 = _mm512_xor_si512(zmm_crc2, zmm_t2); - zmm_crc3 = _mm512_xor_si512(zmm_crc3, zmm_t3); - - len -= 256; - src += 256; - } - // zmm_crc[0,1,2,3] -> zmm_crc0 - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc1); - - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc2); - - z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); - zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc3); - - // zmm_crc0 -> xmm_crc[0, 1, 2, 3] - *xmm_crc0 = _mm512_extracti32x4_epi32(zmm_crc0, 0); - *xmm_crc1 = _mm512_extracti32x4_epi32(zmm_crc0, 1); - *xmm_crc2 = _mm512_extracti32x4_epi32(zmm_crc0, 2); - *xmm_crc3 = _mm512_extracti32x4_epi32(zmm_crc0, 3); - - return (len_tmp - len); // return n bytes processed -} #endif diff --git a/arch/x86/crc32_fold_vpclmulqdq_tpl.h b/arch/x86/crc32_fold_vpclmulqdq_tpl.h new file mode 100644 index 0000000000..89378aef99 --- /dev/null +++ b/arch/x86/crc32_fold_vpclmulqdq_tpl.h @@ -0,0 +1,116 @@ +/* crc32_fold_vpclmulqdq_tpl.h -- VPCMULQDQ-based CRC32 folding template. + * Copyright Wangyang Guo (wangyang.guo@intel.com) + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef COPY +size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len) { +#else +size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, + __m128i init_crc, int32_t first) { + __m512i zmm_initial = _mm512_zextsi128_si512(init_crc); +#endif + __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; + __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; + __m512i z0, z1, z2, z3; + size_t len_tmp = len; + const __m512i zmm_fold4 = _mm512_set4_epi32( + 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); + const __m512i zmm_fold16 = _mm512_set4_epi32( + 0x00000001, 0x1542778a, 0x00000001, 0x322d1430); + + // zmm register init + zmm_crc0 = _mm512_setzero_si512(); + zmm_t0 = _mm512_loadu_si512((__m512i *)src); +#ifndef COPY + XOR_INITIAL(zmm_t0); +#endif + zmm_crc1 = _mm512_loadu_si512((__m512i *)src + 1); + zmm_crc2 = _mm512_loadu_si512((__m512i *)src + 2); + zmm_crc3 = _mm512_loadu_si512((__m512i *)src + 3); + + /* already have intermediate CRC in xmm registers + * fold4 with 4 xmm_crc to get zmm_crc0 + */ + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc0, 0); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc1, 1); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc2, 2); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc3, 3); + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); + +#ifdef COPY + _mm512_storeu_si512((__m512i *)dst, zmm_t0); + _mm512_storeu_si512((__m512i *)dst + 1, zmm_crc1); + _mm512_storeu_si512((__m512i *)dst + 2, zmm_crc2); + _mm512_storeu_si512((__m512i *)dst + 3, zmm_crc3); + dst += 256; +#endif + len -= 256; + src += 256; + + // fold-16 loops + while (len >= 256) { + zmm_t0 = _mm512_loadu_si512((__m512i *)src); + zmm_t1 = _mm512_loadu_si512((__m512i *)src + 1); + zmm_t2 = _mm512_loadu_si512((__m512i *)src + 2); + zmm_t3 = _mm512_loadu_si512((__m512i *)src + 3); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x01); + z1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x01); + z2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x01); + z3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x01); + + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x10); + zmm_crc1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x10); + zmm_crc2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x10); + zmm_crc3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x10); + + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc1 = _mm512_xor_si512(z1, zmm_crc1); + zmm_crc2 = _mm512_xor_si512(z2, zmm_crc2); + zmm_crc3 = _mm512_xor_si512(z3, zmm_crc3); + + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); + zmm_crc1 = _mm512_xor_si512(zmm_crc1, zmm_t1); + zmm_crc2 = _mm512_xor_si512(zmm_crc2, zmm_t2); + zmm_crc3 = _mm512_xor_si512(zmm_crc3, zmm_t3); + +#ifdef COPY + _mm512_storeu_si512((__m512i *)dst, zmm_t0); + _mm512_storeu_si512((__m512i *)dst + 1, zmm_t1); + _mm512_storeu_si512((__m512i *)dst + 2, zmm_t2); + _mm512_storeu_si512((__m512i *)dst + 3, zmm_t3); + dst += 256; +#endif + len -= 256; + src += 256; + } + // zmm_crc[0,1,2,3] -> zmm_crc0 + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc1); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc2); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc3); + + // zmm_crc0 -> xmm_crc[0, 1, 2, 3] + *xmm_crc0 = _mm512_extracti32x4_epi32(zmm_crc0, 0); + *xmm_crc1 = _mm512_extracti32x4_epi32(zmm_crc0, 1); + *xmm_crc2 = _mm512_extracti32x4_epi32(zmm_crc0, 2); + *xmm_crc3 = _mm512_extracti32x4_epi32(zmm_crc0, 3); + + return (len_tmp - len); // return n bytes processed +} diff --git a/cpu_features.h b/cpu_features.h index ca1465d5d2..fb9ffe7a33 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -64,10 +64,10 @@ extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, cons /* CRC32 folding */ #ifdef X86_PCLMULQDQ_CRC -extern uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc); -extern void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t crc32_fold_pclmulqdq_reset(crc32_fold *crc); +extern void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); -extern uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc); +extern uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc); extern uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len); #endif diff --git a/crc32_fold.h b/crc32_fold.h index ecfad454e6..0d2ff66967 100644 --- a/crc32_fold.h +++ b/crc32_fold.h @@ -5,8 +5,8 @@ #ifndef CRC32_FOLD_H_ #define CRC32_FOLD_H_ -#define CRC32_FOLD_BUFFER_SIZE (16 * 5) -/* sizeof(__m128i) * (4 folds & 1 partial fold) */ +#define CRC32_FOLD_BUFFER_SIZE (16 * 4) +/* sizeof(__m128i) * (4 folds) */ typedef struct crc32_fold_s { uint8_t fold[CRC32_FOLD_BUFFER_SIZE]; diff --git a/functable.c b/functable.c index dbb8256b71..ca95df55d7 100644 --- a/functable.c +++ b/functable.c @@ -228,7 +228,7 @@ Z_INTERNAL uint32_t crc32_fold_reset_stub(crc32_fold *crc) { cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_reset = &crc32_fold_reset_pclmulqdq; + functable.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; #endif return functable.crc32_fold_reset(crc); } @@ -238,7 +238,7 @@ Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_ cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_copy = &crc32_fold_copy_pclmulqdq; + functable.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; #endif functable.crc32_fold_copy(crc, dst, src, len); } @@ -258,7 +258,7 @@ Z_INTERNAL uint32_t crc32_fold_final_stub(crc32_fold *crc) { cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_final = &crc32_fold_final_pclmulqdq; + functable.crc32_fold_final = &crc32_fold_pclmulqdq_final; #endif return functable.crc32_fold_final(crc); } From ae28e03549d8a8fb2e32d3558769d8c1cff1b4dc Mon Sep 17 00:00:00 2001 From: Dan Kegel Date: Sat, 4 Jun 2022 09:44:10 -0700 Subject: [PATCH 419/798] abicheck.sh: update reference versions. Co-authored-by: Nathan Moinvaziri --- ...661012b02acdd30281-x86_64-pc-linux-gnu.abi | 1533 +++++++++++++++++ test/abi/zlib-v1.2.12-x86_64-pc-linux-gnu.abi | 1281 ++++++++++++++ test/abicheck.sh | 11 +- 3 files changed, 2818 insertions(+), 7 deletions(-) create mode 100644 test/abi/zlib-ng-843c16c87afd53a20bf915661012b02acdd30281-x86_64-pc-linux-gnu.abi create mode 100644 test/abi/zlib-v1.2.12-x86_64-pc-linux-gnu.abi diff --git a/test/abi/zlib-ng-843c16c87afd53a20bf915661012b02acdd30281-x86_64-pc-linux-gnu.abi b/test/abi/zlib-ng-843c16c87afd53a20bf915661012b02acdd30281-x86_64-pc-linux-gnu.abi new file mode 100644 index 0000000000..68b313d7fb --- /dev/null +++ b/test/abi/zlib-ng-843c16c87afd53a20bf915661012b02acdd30281-x86_64-pc-linux-gnu.abi @@ -0,0 +1,1533 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-v1.2.12-x86_64-pc-linux-gnu.abi b/test/abi/zlib-v1.2.12-x86_64-pc-linux-gnu.abi new file mode 100644 index 0000000000..efe7e02ac4 --- /dev/null +++ b/test/abi/zlib-v1.2.12-x86_64-pc-linux-gnu.abi @@ -0,0 +1,1281 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abicheck.sh b/test/abicheck.sh index 4267aff97d..30cbcf5061 100755 --- a/test/abicheck.sh +++ b/test/abicheck.sh @@ -67,17 +67,14 @@ done # Choose reference repo and commit if test "$suffix" = "" then - # Reference is zlib 1.2.11 + # Reference is zlib 1.2.12 develop due to errors compiling shared library in the 1.2.12 tag. ABI_GIT_REPO=https://github.com/madler/zlib.git - ABI_GIT_COMMIT=v1.2.11 + ABI_GIT_COMMIT=ec3df00224d4b396e2ac6586ab5d25f673caa4c2 else - # Reference should be the tag for zlib-ng 2.0 - # but until that bright, shining day, use some - # random recent SHA. Annoyingly, can't shorten it. + # Reference is most recent zlib-ng develop with zlib 1.2.12 compatible api. ABI_GIT_REPO=https://github.com/zlib-ng/zlib-ng.git - ABI_GIT_COMMIT=56ce27343bf295ae9457f8e3d38ec96d2f949a1c + ABI_GIT_COMMIT=843c16c87afd53a20bf915661012b02acdd30281 fi -# FIXME: even when using a tag, check the hash. # Test compat build for ABI compatibility with zlib if test "$CHOST" = "" From 413bbfaece941c9f6931a45e796aa40ab20dd8c3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 4 Jun 2022 09:20:46 -0700 Subject: [PATCH 420/798] Upload abi files when pkgcheck failure occurs. --- .github/workflows/pkgcheck.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 1c4b1dcbba..7b8a5df595 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -160,6 +160,7 @@ jobs: with: name: ${{ matrix.name }} path: | + **/*.abi btmp1/configure.log btmp1/CMakeFiles/CMakeOutput.log btmp1/CMakeFiles/CMakeError.log From 443905a451bcb871220420f12f3785c940afca04 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 5 Jun 2022 13:38:51 -0700 Subject: [PATCH 421/798] Added Intel's Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction paper to docs folder. --- arch/x86/crc32_fold_pclmulqdq.c | 2 +- arch/x86/crc32_fold_pclmulqdq_tpl.h | 2 +- doc/crc-pclmulqdq.pdf | Bin 0 -> 384202 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 doc/crc-pclmulqdq.pdf diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 01c753b485..3e0372bf9c 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -3,7 +3,7 @@ * instruction. * * A white paper describing this algorithm can be found at: - * https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf + * doc/crc-pclmulqdq.pdf * * Copyright (C) 2013 Intel Corporation. All rights reserved. * Copyright (C) 2016 Marian Beermann (support for initial value) diff --git a/arch/x86/crc32_fold_pclmulqdq_tpl.h b/arch/x86/crc32_fold_pclmulqdq_tpl.h index 12681b8025..4227c72cda 100644 --- a/arch/x86/crc32_fold_pclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_pclmulqdq_tpl.h @@ -3,7 +3,7 @@ * instruction. * * A white paper describing this algorithm can be found at: - * https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf + * doc/crc-pclmulqdq.pdf * * Copyright (C) 2013 Intel Corporation. All rights reserved. * Copyright (C) 2016 Marian Beermann (support for initial value) diff --git a/doc/crc-pclmulqdq.pdf b/doc/crc-pclmulqdq.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d0eca86b33851a18132d39983b2118e8da3ee7aa GIT binary patch literal 384202 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

{LABC35aZ+t^w!fb%kfniC0^^)fHUEz8(f& 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 Cetk@ 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

  • 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 z Date: Mon, 6 Jun 2022 16:18:19 -0700 Subject: [PATCH 422/798] Fixed signed warnings in GZ unit tests. test_gzio.cc(44): warning C4389: '!=': signed/unsigned mismatch test_gzio.cc(72): warning C4389: '!=': signed/unsigned mismatch --- test/test_gzio.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_gzio.cc b/test/test_gzio.cc index 46baa028eb..59e46f520a 100644 --- a/test/test_gzio.cc +++ b/test/test_gzio.cc @@ -41,7 +41,7 @@ TEST(gzip, readwrite) { EXPECT_GE(PREFIX(gzseek)(file, 1L, SEEK_CUR), 0); /* Write hello, hello! using gzfwrite using best compression level */ EXPECT_EQ(PREFIX(gzsetparams)(file, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY), Z_OK); - EXPECT_NE(PREFIX(gzfwrite)(hello, hello_len, 1, file), 0); + EXPECT_NE(PREFIX(gzfwrite)(hello, hello_len, 1, file), 0UL); /* Flush compressed bytes to file */ EXPECT_EQ(PREFIX(gzflush)(file, Z_SYNC_FLUSH), Z_OK); compr_len = (uint32_t)PREFIX(gzoffset)(file); @@ -69,7 +69,7 @@ TEST(gzip, readwrite) { /* Read first hello, hello! string with gzgets */ strcpy((char*)uncompr, "garbages"); PREFIX(gzgets)(file, (char*)uncompr, (int)uncompr_len); - EXPECT_EQ(strlen((char*)uncompr), 7); /* " hello!" */ + EXPECT_EQ(strlen((char*)uncompr), 7UL); /* " hello!" */ EXPECT_STREQ((char*)uncompr, hello + 6); /* Seek to second hello, hello! string */ From 201188691a990468ae1c6ebba4e12bd1a62166b0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 6 Jun 2022 16:20:17 -0700 Subject: [PATCH 423/798] Remove unused chunkcopy_safe function prototypes. --- arch/arm/chunkset_neon.c | 1 - arch/power/chunkset_power8.c | 1 - arch/x86/chunkset_avx.c | 1 - arch/x86/chunkset_sse2.c | 1 - chunkset.c | 1 - cpu_features.h | 5 ----- 6 files changed, 10 deletions(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index e2b9b8be4b..ca8420d345 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -38,7 +38,6 @@ static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { #define CHUNKSIZE chunksize_neon #define CHUNKCOPY chunkcopy_neon -#define CHUNKCOPY_SAFE chunkcopy_safe_neon #define CHUNKUNROLL chunkunroll_neon #define CHUNKMEMSET chunkmemset_neon #define CHUNKMEMSET_SAFE chunkmemset_safe_neon diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index 5db782144d..47e5485262 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -34,7 +34,6 @@ static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { #define CHUNKSIZE chunksize_power8 #define CHUNKCOPY chunkcopy_power8 -#define CHUNKCOPY_SAFE chunkcopy_safe_power8 #define CHUNKUNROLL chunkunroll_power8 #define CHUNKMEMSET chunkmemset_power8 #define CHUNKMEMSET_SAFE chunkmemset_safe_power8 diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index 91aaa458ec..bf49c712d0 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -122,7 +122,6 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t #define CHUNKSIZE chunksize_avx #define CHUNKCOPY chunkcopy_avx -#define CHUNKCOPY_SAFE chunkcopy_safe_avx #define CHUNKUNROLL chunkunroll_avx #define CHUNKMEMSET chunkmemset_avx #define CHUNKMEMSET_SAFE chunkmemset_safe_avx diff --git a/arch/x86/chunkset_sse2.c b/arch/x86/chunkset_sse2.c index be195cf73c..8e3166f70e 100644 --- a/arch/x86/chunkset_sse2.c +++ b/arch/x86/chunkset_sse2.c @@ -43,7 +43,6 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { #define CHUNKSIZE chunksize_sse2 #define CHUNKCOPY chunkcopy_sse2 -#define CHUNKCOPY_SAFE chunkcopy_safe_sse2 #define CHUNKUNROLL chunkunroll_sse2 #define CHUNKMEMSET chunkmemset_sse2 #define CHUNKMEMSET_SAFE chunkmemset_safe_sse2 diff --git a/chunkset.c b/chunkset.c index 96684f4707..ca35929f3a 100644 --- a/chunkset.c +++ b/chunkset.c @@ -31,7 +31,6 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { #define CHUNKSIZE chunksize_c #define CHUNKCOPY chunkcopy_c -#define CHUNKCOPY_SAFE chunkcopy_safe_c #define CHUNKUNROLL chunkunroll_c #define CHUNKMEMSET chunkmemset_c #define CHUNKMEMSET_SAFE chunkmemset_safe_c diff --git a/cpu_features.h b/cpu_features.h index fb9ffe7a33..aec267bf48 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -74,14 +74,12 @@ extern uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64 /* memory chunking */ extern uint32_t chunksize_c(void); extern uint8_t* chunkcopy_c(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_c(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); extern uint8_t* chunkunroll_c(uint8_t *out, unsigned *dist, unsigned *len); extern uint8_t* chunkmemset_c(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_c(uint8_t *out, unsigned dist, unsigned len, unsigned left); #ifdef X86_SSE2_CHUNKSET extern uint32_t chunksize_sse2(void); extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_sse2(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); extern uint8_t* chunkmemset_sse2(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); @@ -93,7 +91,6 @@ extern uint8_t* chunkmemset_safe_sse41(uint8_t *out, unsigned dist, unsigned len #ifdef X86_AVX_CHUNKSET extern uint32_t chunksize_avx(void); extern uint8_t* chunkcopy_avx(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_avx(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); extern uint8_t* chunkunroll_avx(uint8_t *out, unsigned *dist, unsigned *len); extern uint8_t* chunkmemset_avx(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_avx(uint8_t *out, unsigned dist, unsigned len, unsigned left); @@ -101,7 +98,6 @@ extern uint8_t* chunkmemset_safe_avx(uint8_t *out, unsigned dist, unsigned len, #ifdef ARM_NEON_CHUNKSET extern uint32_t chunksize_neon(void); extern uint8_t* chunkcopy_neon(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_neon(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); extern uint8_t* chunkunroll_neon(uint8_t *out, unsigned *dist, unsigned *len); extern uint8_t* chunkmemset_neon(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, unsigned left); @@ -109,7 +105,6 @@ extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, #ifdef POWER8_VSX_CHUNKSET extern uint32_t chunksize_power8(void); extern uint8_t* chunkcopy_power8(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_power8(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); extern uint8_t* chunkunroll_power8(uint8_t *out, unsigned *dist, unsigned *len); extern uint8_t* chunkmemset_power8(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); From d43822b9a7491681c54bcf31e2f0e99a0293fe0c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 7 Jun 2022 14:21:48 -0700 Subject: [PATCH 424/798] zlib 1.2.12 --- README.md | 2 +- crc32_braid.c | 2 +- crc32_braid_comb.c | 2 +- deflate.c | 4 ++-- gzguts.h | 2 +- gzlib.c | 2 +- gzread.c.in | 2 +- gzwrite.c | 2 +- infback.c | 2 +- inflate.c | 2 +- inflate.h | 2 +- inftrees.c | 4 ++-- inftrees.h | 2 +- tools/makecrct.c | 2 +- trees.c | 2 +- zlib.h.in | 10 +++++----- zutil.h | 2 +- 17 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 0dd1b1c37e..1efe7f2f47 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ with zlib, then zlib-ng will temporarily be used instead by the program, without risking system-wide instability. ``` -LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.11.zlib-ng /usr/bin/program +LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.12.zlib-ng /usr/bin/program ``` ### Cmake diff --git a/crc32_braid.c b/crc32_braid.c index fee7992bb5..f5b223eeab 100644 --- a/crc32_braid.c +++ b/crc32_braid.c @@ -1,5 +1,5 @@ /* crc32_braid.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * This interleaved implementation of a CRC makes use of pipelined multiple diff --git a/crc32_braid_comb.c b/crc32_braid_comb.c index e33fccfd6d..75fb474258 100644 --- a/crc32_braid_comb.c +++ b/crc32_braid_comb.c @@ -1,5 +1,5 @@ /* crc32_braid_comb.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * This interleaved implementation of a CRC makes use of pipelined multiple diff --git a/deflate.c b/deflate.c index 878033355c..986c5fddf6 100644 --- a/deflate.c +++ b/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2016 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -59,7 +59,7 @@ # undef deflateInit2 #endif -const char PREFIX(deflate_copyright)[] = " deflate 1.2.11.f Copyright 1995-2016 Jean-loup Gailly and Mark Adler "; +const char PREFIX(deflate_copyright)[] = " deflate 1.2.12.f Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot diff --git a/gzguts.h b/gzguts.h index 7db7099088..fe09270639 100644 --- a/gzguts.h +++ b/gzguts.h @@ -1,7 +1,7 @@ #ifndef GZGUTS_H_ #define GZGUTS_H_ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * Copyright (C) 2004-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/gzlib.c b/gzlib.c index c19284035c..e1290fc611 100644 --- a/gzlib.c +++ b/gzlib.c @@ -1,5 +1,5 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004-2017 Mark Adler + * Copyright (C) 2004-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/gzread.c.in b/gzread.c.in index f17a5f8880..c421f9f56f 100644 --- a/gzread.c.in +++ b/gzread.c.in @@ -1,5 +1,5 @@ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/gzwrite.c b/gzwrite.c index b3e93e8d08..ba716bc20b 100644 --- a/gzwrite.c +++ b/gzwrite.c @@ -1,5 +1,5 @@ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004-2017 Mark Adler + * Copyright (C) 2004-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/infback.c b/infback.c index dd549a89fb..95798511f7 100644 --- a/infback.c +++ b/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/inflate.c b/inflate.c index 6192148233..5f52dd140a 100644 --- a/inflate.c +++ b/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/inflate.h b/inflate.h index 941e8b0a28..f9a7edd597 100644 --- a/inflate.h +++ b/inflate.h @@ -1,5 +1,5 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2019 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/inftrees.c b/inftrees.c index eb82ff4427..369fd09dfe 100644 --- a/inftrees.c +++ b/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2016 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 -const char PREFIX(inflate_copyright)[] = " inflate 1.2.11.f Copyright 1995-2016 Mark Adler "; +const char PREFIX(inflate_copyright)[] = " inflate 1.2.12.f Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot diff --git a/inftrees.h b/inftrees.h index 031c2a1b94..bb6274a128 100644 --- a/inftrees.h +++ b/inftrees.h @@ -2,7 +2,7 @@ #define INFTREES_H_ /* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005, 2010 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/tools/makecrct.c b/tools/makecrct.c index bfc2b96551..8ed0cf5cfd 100644 --- a/tools/makecrct.c +++ b/tools/makecrct.c @@ -1,5 +1,5 @@ /* makecrct.c -- output crc32 tables - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler + * Copyright (C) 1995-2022 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/trees.c b/trees.c index 7bc70075b5..111ead01ff 100644 --- a/trees.c +++ b/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2017 Jean-loup Gailly + * Copyright (C) 1995-2021 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/zlib.h.in b/zlib.h.in index 9de5e91b16..7e77a5bb78 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -1,9 +1,9 @@ #ifndef ZLIB_H_ #define ZLIB_H_ /* zlib.h -- interface of the 'zlib-ng' compression library - Forked from and compatible with zlib 1.2.11 + Forked from and compatible with zlib 1.2.12 - Copyright (C) 1995-2016 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -57,11 +57,11 @@ extern "C" { #define ZLIBNG_VER_STATUS 0 /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ -#define ZLIB_VERSION "1.2.11.zlib-ng" -#define ZLIB_VERNUM 0x12bf +#define ZLIB_VERSION "1.2.12.zlib-ng" +#define ZLIB_VERNUM 0x12cf #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_REVISION 12 #define ZLIB_VER_SUBREVISION 0 /* diff --git a/zutil.h b/zutil.h index 53c7cdf148..25716c5711 100644 --- a/zutil.h +++ b/zutil.h @@ -1,7 +1,7 @@ #ifndef ZUTIL_H_ #define ZUTIL_H_ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ From 7092c2be688b6e69f63ccf54f6069343fd81c6b3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 6 Jun 2022 16:22:26 -0700 Subject: [PATCH 425/798] Fixed inflate size conversion warning in chunkcopy_safe. inflate_p.h(142,27): warning C4244: 'function': conversion from 'uint64_t' to 'size_t', possible loss of data --- inflate_p.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/inflate_p.h b/inflate_p.h index 65bbd4448a..20f6b1a8c3 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -130,16 +130,16 @@ } while (0) /* Behave like chunkcopy, but avoid writing beyond of legal output. */ -static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, size_t len, uint8_t *safe) { - uint32_t safelen = (uint32_t)((safe - out) + 1); +static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, uint64_t len, uint8_t *safe) { + uint64_t safelen = (safe - out) + 1; len = MIN(len, safelen); int32_t olap_src = from >= out && from < out + len; int32_t olap_dst = out >= from && out < from + len; - size_t tocopy; + uint64_t tocopy; /* For all cases without overlap, memcpy is ideal */ if (!(olap_src || olap_dst)) { - memcpy(out, from, len); + memcpy(out, from, (size_t)len); return out + len; } @@ -148,9 +148,9 @@ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, size_t len, u * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look * behind or lookahead distance. */ - size_t non_olap_size = llabs(from - out); // llabs vs labs for compatibility with windows + uint64_t non_olap_size = llabs(from - out); // llabs vs labs for compatibility with windows - memcpy(out, from, non_olap_size); + memcpy(out, from, (size_t)non_olap_size); out += non_olap_size; from += non_olap_size; len -= non_olap_size; From a7598c1d8f6d3e226875052376abdd1ae3b331fe Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 7 Jun 2022 08:54:26 -0700 Subject: [PATCH 426/798] Fixed conversion warnings for wsize in slide_hash_c. slide_hash.c(50,44): warning C4244: 'function': conversion from 'unsigned int' to 'uint16_t', possible loss of data slide_hash.c(51,40): warning C4244: 'function': conversion from 'unsigned int' to 'uint16_t', possible loss of data --- slide_hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slide_hash.c b/slide_hash.c index d25e710a85..b9fbbdb69f 100644 --- a/slide_hash.c +++ b/slide_hash.c @@ -45,7 +45,7 @@ static inline void slide_hash_c_chain(Pos *table, uint32_t entries, uint16_t wsi } Z_INTERNAL void slide_hash_c(deflate_state *s) { - unsigned int wsize = s->w_size; + uint16_t wsize = (uint16_t)s->w_size; slide_hash_c_chain(s->head, HASH_SIZE, wsize); slide_hash_c_chain(s->prev, wsize, wsize); From 3f7b0b411d7c063609065e76cb674dccbf4f3df9 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Mon, 13 Jun 2022 18:46:00 +0200 Subject: [PATCH 427/798] Extend GZIP conditional If gzip support has been disabled during compilation then also consider gzip relevant states as invalid in deflateStateCheck. Also the gzip state definitions can be removed. This change leads to failure in test/example, and I am not sure what the GZIP conditional is trying to achieve. All gzip related functions are still defined in zlib.h Alternative approach is to remove the GZIP define. --- deflate.c | 2 +- deflate.h | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/deflate.c b/deflate.c index 986c5fddf6..71920982d4 100644 --- a/deflate.c +++ b/deflate.c @@ -349,11 +349,11 @@ static int deflateStateCheck (PREFIX3(stream) *strm) { if (s == NULL || s->strm != strm || (s->status != INIT_STATE && #ifdef GZIP s->status != GZIP_STATE && -#endif s->status != EXTRA_STATE && s->status != NAME_STATE && s->status != COMMENT_STATE && s->status != HCRC_STATE && +#endif s->status != BUSY_STATE && s->status != FINISH_STATE)) return 1; diff --git a/deflate.h b/deflate.h index 1b59c7539d..f8920df59c 100644 --- a/deflate.h +++ b/deflate.h @@ -54,16 +54,16 @@ #define END_BLOCK 256 /* end of block literal code */ -#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ #ifdef GZIP -# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +# define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ +# define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ +# define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ +# define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ #endif -#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ -#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ -#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ -#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ -#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ -#define FINISH_STATE 666 /* stream complete */ +#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 666 /* stream complete */ /* Stream status */ #define HASH_BITS 16u /* log2(HASH_SIZE) */ From 956ff053837dee0adef4c8d42d883486f9667e19 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Mon, 13 Jun 2022 18:43:16 +0200 Subject: [PATCH 428/798] Handle invalid windowBits in init functions Negative windowBits arguments are eventually turned positive in deflateInit2_ and inflateInit2_ (more precisely in inflateReset2). Such values are used to indicate that raw deflate/inflate should be performed. If a user supplies INT32_MIN for windowBits, the code will perform -INT32_MIN which does not fit into int32_t. In fact, this is undefined behavior in C and should be avoided. Clearly this is a user error, but given the careful validation of input arguments a few lines later in deflateInit2_ I think this might be of interest. Proof of Concept: - Compile zlib-ng with gcc -ftrapv or -fsanitize=undefined - Compile and run this program: ``` #include #include #include int main(void) { zng_stream de_stream = { 0 }, in_stream = { 0 }; int result; result = zng_deflateInit2(&de_stream, 0, Z_DEFLATED, INT32_MIN, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); printf("zng_deflateInit2: %d\n", result); result = zng_inflateInit2(&in_stream, INT32_MIN); printf("zng_inflateInit2: %d\n", result); return 0; } ``` --- deflate.c | 2 ++ inflate.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/deflate.c b/deflate.c index 71920982d4..2970aa4e08 100644 --- a/deflate.c +++ b/deflate.c @@ -213,6 +213,8 @@ int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; + if (windowBits < -15) + return Z_STREAM_ERROR; windowBits = -windowBits; #ifdef GZIP } else if (windowBits > 15) { diff --git a/inflate.c b/inflate.c index 5f52dd140a..4bd9b938a2 100644 --- a/inflate.c +++ b/inflate.c @@ -111,6 +111,8 @@ int32_t Z_EXPORT PREFIX(inflateReset2)(PREFIX3(stream) *strm, int32_t windowBits /* extract wrap request from windowBits parameter */ if (windowBits < 0) { wrap = 0; + if (windowBits < -15) + return Z_STREAM_ERROR; windowBits = -windowBits; } else { wrap = (windowBits >> 4) + 5; From 54ea2398bce7f072eff06aab3d3fed600eef0659 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 12 Jun 2022 09:01:15 -0700 Subject: [PATCH 429/798] Add public compile definition for zlib-ng API so that other projects that use CMake and link against the zlib project can easily determine whether or not to include "zlib-ng.h" or "zlib.h". --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a26d597cd..07c7753776 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1037,6 +1037,9 @@ else() endif() foreach(ZLIB_INSTALL_LIBRARY ${ZLIB_INSTALL_LIBRARIES}) + if(NOT ZLIB_COMPAT) + target_compile_definitions(${ZLIB_INSTALL_LIBRARY} PUBLIC ZLIBNG_NATIVE_API) + endif() target_include_directories(${ZLIB_INSTALL_LIBRARY} PUBLIC "$" "$") From 5181fe6f6fe471c7cabb78ded318c2d5beb0bcf2 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Sat, 18 Jun 2022 21:00:10 +0200 Subject: [PATCH 430/798] Fix typo Typo found with codespell. --- arch/x86/chunkset_sse41.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/chunkset_sse41.c b/arch/x86/chunkset_sse41.c index c6f982183a..9789df76a7 100644 --- a/arch/x86/chunkset_sse41.c +++ b/arch/x86/chunkset_sse41.c @@ -71,7 +71,7 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t #ifdef Z_MEMORY_SANITIZER /* Important to note: * This is _not_ to subvert the memory sanitizer but to instead unpoison some - * bytes we willingly and purposefully load unitialized that we swizzle over + * bytes we willingly and purposefully load uninitialized that we swizzle over * in a vector register, anyway. If what we assume is wrong about what is used, * the memory sanitizer will still usefully flag it */ __msan_unpoison(buf + dist, 16 - dist); From ff9162c1a0da8d60ae664e5930b256de99ad83b3 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 17 Jun 2022 13:06:56 +0300 Subject: [PATCH 431/798] In compatibility mode, always define z_crc_t as uint32_t for backwards compatibility. --- configure | 1 + zconf-ng.h.in | 1 - zconf.h.in | 3 ++- zlib-ng.h.in | 5 +++-- zlib.h.in | 4 ++-- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/configure b/configure index 26529dbb5c..ffee400548 100755 --- a/configure +++ b/configure @@ -874,6 +874,7 @@ echo >> configure.log # Check for ANSI C compliant compiler cat > $test.c < #include #include #include "zconf${SUFFIX}.h" diff --git a/zconf-ng.h.in b/zconf-ng.h.in index 16fdcfa0fc..7f8983bf46 100644 --- a/zconf-ng.h.in +++ b/zconf-ng.h.in @@ -116,7 +116,6 @@ typedef PTRDIFF_TYPE ptrdiff_t; #endif #include /* for off_t */ -#include /* for va_list */ #include /* for wchar_t and NULL */ diff --git a/zconf.h.in b/zconf.h.in index eea3c4ac7e..c82a8ad009 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -127,6 +127,8 @@ typedef void const *voidpc; typedef void *voidpf; typedef void *voidp; +typedef uint32_t z_crc_t; + #ifdef HAVE_UNISTD_H /* may be set to #if 1 by configure/cmake/etc */ # define Z_HAVE_UNISTD_H #endif @@ -136,7 +138,6 @@ typedef PTRDIFF_TYPE ptrdiff_t; #endif #include /* for off_t */ -#include /* for va_list */ #include /* for wchar_t and NULL */ diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 38a5225f7b..a1536b76d2 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -34,9 +34,10 @@ #endif #ifndef RC_INVOKED -#include "zconf-ng.h" - #include +#include + +#include "zconf-ng.h" #ifndef ZCONFNG_H # error Missing zconf-ng.h add binary output directory to include directories diff --git a/zlib.h.in b/zlib.h.in index 7e77a5bb78..09ea336ff3 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -35,11 +35,11 @@ #endif #ifndef RC_INVOKED -#include "zconf.h" - #include #include +#include "zconf.h" + #ifndef ZCONF_H # error Missing zconf.h add binary output directory to include directories #endif From 805aee36adadd39dc2b864fc41c4c45850a789ad Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 20 Jun 2022 20:27:00 -0700 Subject: [PATCH 432/798] Print gtest_zlib test results using color. --- .github/workflows/cmake.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 0525836169..43eb8d5c34 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,5 +1,8 @@ name: CI CMake on: [push, pull_request] +env: + TERM: xterm-256color + GTEST_COLOR: 1 jobs: ci-cmake: name: ${{ matrix.name }} From 7e243e4436ce968a6d5261e6ff9203aa80614177 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 5 Jun 2022 16:54:32 -0700 Subject: [PATCH 433/798] Fix MSVC possible loss of data warning in crc32_pclmulqdq by converting len types to use uint64_t. arch\x86\crc32_fold_pclmulqdq.c(604,43): warning C4244: 'function': conversion from 'uint64_t' to 'size_t', possible loss of data --- arch/s390/crc32-vx.c | 2 +- arch/x86/crc32_fold_pclmulqdq.c | 10 +++++----- arch/x86/crc32_fold_pclmulqdq_tpl.h | 16 ++++++++-------- arch/x86/crc32_fold_vpclmulqdq_tpl.h | 10 +++++----- cpu_features.h | 4 ++-- crc32_fold.c | 14 +++++++++++--- crc32_fold.h | 4 ++-- functable.c | 4 ++-- functable.h | 4 ++-- 9 files changed, 38 insertions(+), 30 deletions(-) diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index d0df83cce7..0888003445 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -21,7 +21,7 @@ typedef unsigned char uv16qi __attribute__((vector_size(16))); typedef unsigned int uv4si __attribute__((vector_size(16))); typedef unsigned long long uv2di __attribute__((vector_size(16))); -static uint32_t crc32_le_vgfm_16(uint32_t crc, const unsigned char *buf, size_t len) { +static uint32_t crc32_le_vgfm_16(uint32_t crc, const unsigned char *buf, uint64_t len) { /* * The CRC-32 constant block contains reduction constants to fold and * process particular chunks of the input data stream in parallel. diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 3e0372bf9c..3d0eaf3531 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -32,11 +32,11 @@ #include #ifdef X86_VPCLMULQDQ_CRC -extern size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, __m128i init_crc, +extern uint64_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, uint64_t len, __m128i init_crc, int32_t first); -extern size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len); +extern uint64_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, uint64_t len); #endif static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { @@ -185,7 +185,7 @@ static const unsigned ALIGNED_(32) pshufb_shf_table[60] = { 0x0201008f, 0x06050403, 0x0a090807, 0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ }; -static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, +static void partial_fold(const uint64_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, __m128i *xmm_crc_part) { const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, diff --git a/arch/x86/crc32_fold_pclmulqdq_tpl.h b/arch/x86/crc32_fold_pclmulqdq_tpl.h index 4227c72cda..36207953bc 100644 --- a/arch/x86/crc32_fold_pclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_pclmulqdq_tpl.h @@ -20,9 +20,9 @@ #ifdef X86_PCLMULQDQ_CRC #ifdef COPY -Z_INTERNAL void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len) { #else -Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { +Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc) { #endif unsigned long algn_diff; __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; @@ -47,9 +47,9 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t if (len == 0) return; - memcpy(partial_buf, src, len); + memcpy(partial_buf, src, (size_t)len); xmm_crc_part = _mm_load_si128((const __m128i *)partial_buf); - memcpy(dst, partial_buf, len); + memcpy(dst, partial_buf, (size_t)len); #endif goto partial; } @@ -82,10 +82,10 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t #ifdef X86_VPCLMULQDQ_CRC if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { #ifdef COPY - size_t n = fold_16_vpclmulqdq_copy(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); + uint64_t n = fold_16_vpclmulqdq_copy(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); dst += n; #else - size_t n = fold_16_vpclmulqdq(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, src, len, + uint64_t n = fold_16_vpclmulqdq(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, src, len, xmm_initial, first); first = 0; #endif @@ -176,10 +176,10 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t partial: if (len) { - memcpy(&xmm_crc_part, src, len); + memcpy(&xmm_crc_part, src, (size_t)len); #ifdef COPY _mm_storeu_si128((__m128i *)partial_buf, xmm_crc_part); - memcpy(dst, partial_buf, len); + memcpy(dst, partial_buf, (size_t)len); #endif partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); } diff --git a/arch/x86/crc32_fold_vpclmulqdq_tpl.h b/arch/x86/crc32_fold_vpclmulqdq_tpl.h index 89378aef99..e75278f984 100644 --- a/arch/x86/crc32_fold_vpclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_vpclmulqdq_tpl.h @@ -4,18 +4,18 @@ */ #ifdef COPY -size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len) { +uint64_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, uint64_t len) { #else -size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, +uint64_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, uint64_t len, __m128i init_crc, int32_t first) { __m512i zmm_initial = _mm512_zextsi128_si512(init_crc); #endif __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; __m512i z0, z1, z2, z3; - size_t len_tmp = len; + uint64_t len_tmp = len; const __m512i zmm_fold4 = _mm512_set4_epi32( 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); const __m512i zmm_fold16 = _mm512_set4_epi32( diff --git a/cpu_features.h b/cpu_features.h index aec267bf48..50fdf6156f 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -65,8 +65,8 @@ extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, cons /* CRC32 folding */ #ifdef X86_PCLMULQDQ_CRC extern uint32_t crc32_fold_pclmulqdq_reset(crc32_fold *crc); -extern void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); -extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); +extern void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); +extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); extern uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc); extern uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len); #endif diff --git a/crc32_fold.c b/crc32_fold.c index b3072e374b..eb0aeeb761 100644 --- a/crc32_fold.c +++ b/crc32_fold.c @@ -12,12 +12,20 @@ Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc) { return crc->value; } -Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len) { crc->value = functable.crc32(crc->value, src, len); - memcpy(dst, src, len); + while (len > SIZE_MAX) { + memcpy(dst, src, SIZE_MAX); + dst += SIZE_MAX; + src += SIZE_MAX; + len -= SIZE_MAX; + } + if (len) { + memcpy(dst, src, (size_t)len); + } } -Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { +Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc) { /* Note: while this is basically the same thing as the vanilla CRC function, we still need * a functable entry for it so that we can generically dispatch to this function with the * same arguments for the versions that _do_ do a folding CRC but we don't want a copy. The diff --git a/crc32_fold.h b/crc32_fold.h index 0d2ff66967..6aef546709 100644 --- a/crc32_fold.h +++ b/crc32_fold.h @@ -14,8 +14,8 @@ typedef struct crc32_fold_s { } crc32_fold; Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc); -Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); -Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); +Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); +Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); Z_INTERNAL uint32_t crc32_fold_final_c(crc32_fold *crc); #endif diff --git a/functable.c b/functable.c index ca95df55d7..0e0418c25f 100644 --- a/functable.c +++ b/functable.c @@ -233,7 +233,7 @@ Z_INTERNAL uint32_t crc32_fold_reset_stub(crc32_fold *crc) { return functable.crc32_fold_reset(crc); } -Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len) { functable.crc32_fold_copy = &crc32_fold_copy_c; cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC @@ -243,7 +243,7 @@ Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_ functable.crc32_fold_copy(crc, dst, src, len); } -Z_INTERNAL void crc32_fold_stub(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { +Z_INTERNAL void crc32_fold_stub(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc) { functable.crc32_fold = &crc32_fold_c; cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC diff --git a/functable.h b/functable.h index da7726e45a..6d6d7e4608 100644 --- a/functable.h +++ b/functable.h @@ -15,8 +15,8 @@ struct functable_s { uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); uint32_t (* crc32_fold_reset) (crc32_fold *crc); - void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); - void (* crc32_fold) (crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); + void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); + void (* crc32_fold) (crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); uint32_t (* crc32_fold_final) (crc32_fold *crc); uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* chunksize) (void); From 5f370cd887796a14a7a27c7427e8f42fc63937f7 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 5 Jun 2022 21:28:49 -0700 Subject: [PATCH 434/798] Use uint64_t instead of size_t for len in adler32 to be consistent with crc32. --- adler32.c | 2 +- adler32_fold.c | 17 +++++++++++---- adler32_fold.h | 2 +- adler32_p.h | 8 +++---- arch/arm/adler32_neon.c | 6 +++--- arch/power/adler32_power8.c | 2 +- arch/power/adler32_vmx.c | 6 +++--- arch/x86/adler32_avx2_tpl.h | 25 +++++++++++----------- arch/x86/adler32_avx512_tpl.h | 12 +++++------ arch/x86/adler32_avx512_vnni.c | 22 +++++++++---------- arch/x86/adler32_sse42.c | 6 +++--- arch/x86/adler32_ssse3.c | 10 ++++----- cpu_features.h | 26 +++++++++++------------ functable.c | 4 ++-- functable.h | 4 ++-- test/benchmarks/benchmark_adler32_copy.cc | 4 ++-- 16 files changed, 83 insertions(+), 73 deletions(-) diff --git a/adler32.c b/adler32.c index 42e7b0fe25..7590d96790 100644 --- a/adler32.c +++ b/adler32.c @@ -8,7 +8,7 @@ #include "adler32_p.h" /* ========================================================================= */ -Z_INTERNAL uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len) { +Z_INTERNAL uint32_t adler32_c(uint32_t adler, const unsigned char *buf, uint64_t len) { uint32_t sum2; unsigned n; diff --git a/adler32_fold.c b/adler32_fold.c index 20fec2bd3c..66d63dd351 100644 --- a/adler32_fold.c +++ b/adler32_fold.c @@ -1,5 +1,5 @@ /* adler32_fold.c -- adler32 folding interface - * Copyright (C) 2022 Adam Stylinski + * Copyright (C) 2022 Adam Stylinski * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -7,7 +7,16 @@ #include "functable.h" #include "adler32_fold.h" -Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { - memcpy(dst, src, len); - return functable.adler32(adler, src, len); +Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { + adler = functable.adler32(adler, src, len); + while (len > SIZE_MAX) { + memcpy(dst, src, SIZE_MAX); + dst += SIZE_MAX; + src += SIZE_MAX; + len -= SIZE_MAX; + } + if (len) { + memcpy(dst, src, (size_t)len); + } + return adler; } diff --git a/adler32_fold.h b/adler32_fold.h index 20aa1c7400..bdaf2130fe 100644 --- a/adler32_fold.h +++ b/adler32_fold.h @@ -6,6 +6,6 @@ #ifndef ADLER32_FOLD_H_ #define ADLER32_FOLD_H_ -Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); #endif diff --git a/adler32_p.h b/adler32_p.h index 1d2e77f49f..e97f2eac33 100644 --- a/adler32_p.h +++ b/adler32_p.h @@ -26,7 +26,7 @@ static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, u return adler | (sum2 << 16); } -static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) { +static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, uint64_t len, uint32_t sum2) { while (len) { --len; adler += *buf++; @@ -38,9 +38,9 @@ static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, return adler | (sum2 << 16); } -static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char *buf, uint8_t *dst, size_t len, uint32_t sum2) { +static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char *buf, uint8_t *dst, uint64_t len, uint32_t sum2) { while (len--) { - *dst = *buf++; + *dst = *buf++; adler += *dst++; sum2 += adler; } @@ -50,7 +50,7 @@ static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char * return adler | (sum2 << 16); } -static inline uint32_t adler32_len_64(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) { +static inline uint32_t adler32_len_64(uint32_t adler, const unsigned char *buf, uint64_t len, uint32_t sum2) { #ifdef UNROLL_MORE while (len >= 16) { len -= 16; diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index 7c2c51fae0..08032672e7 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -15,7 +15,7 @@ #include "../../adler32_p.h" #include "../../fallback_builtins.h" -static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) { +static void NEON_accum32(uint32_t *s, const unsigned char *buf, uint64_t len) { static const uint16_t ALIGNED_(16) taps[64] = { 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, @@ -138,7 +138,7 @@ static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) { s[1] = vget_lane_u32(as, 1); } -static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf, size_t len) { +static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf, uint64_t len) { unsigned int i; for (i = 0; i < len; ++i) { pair[0] += buf[i]; @@ -146,7 +146,7 @@ static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf, size_t le } } -uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len) { +uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, uint64_t len) { /* split Adler-32 into component sums */ uint32_t sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; diff --git a/arch/power/adler32_power8.c b/arch/power/adler32_power8.c index f39f00246c..fe5e46eaa8 100644 --- a/arch/power/adler32_power8.c +++ b/arch/power/adler32_power8.c @@ -52,7 +52,7 @@ static inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsi return __a; } -uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len) { +uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, uint64_t len) { uint32_t s1 = adler & 0xffff; uint32_t s2 = (adler >> 16) & 0xffff; diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index 6b7d9153b4..11fe559449 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -12,7 +12,7 @@ #define vmx_zero() (vec_splat_u32(0)) -static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char *buf, size_t len) { +static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char *buf, uint64_t len) { unsigned int i; for (i = 0; i < len; ++i) { pair[0] += buf[i]; @@ -20,7 +20,7 @@ static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char * } } -static void vmx_accum32(uint32_t *s, const unsigned char *buf, size_t len) { +static void vmx_accum32(uint32_t *s, const unsigned char *buf, uint64_t len) { /* Different taps for the separable components of sums */ const vector unsigned char t0 = {64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49}; const vector unsigned char t1 = {48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33}; @@ -113,7 +113,7 @@ static void vmx_accum32(uint32_t *s, const unsigned char *buf, size_t len) { vec_ste(s2acc, 0, s+1); } -uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len) { +uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, uint64_t len) { uint32_t sum2; uint32_t pair[16] ALIGNED_(16); memset(&pair[2], 0, 14); diff --git a/arch/x86/adler32_avx2_tpl.h b/arch/x86/adler32_avx2_tpl.h index 59cacfa483..4ff1838de0 100644 --- a/arch/x86/adler32_avx2_tpl.h +++ b/arch/x86/adler32_avx2_tpl.h @@ -11,8 +11,9 @@ #include "adler32_avx2_p.h" #ifdef X86_SSE42_ADLER32 -extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); -extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len); +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); +extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, uint64_t len); + #define copy_sub32(a, b, c, d) adler32_fold_copy_sse42(a, b, c, d) #define sub32(a, b, c) adler32_ssse3(a, b, c) #else @@ -21,16 +22,16 @@ extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len); #endif #ifdef COPY -Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { #else -Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, uint64_t len) { #endif if (src == NULL) return 1L; if (len == 0) return adler; uint32_t adler0, adler1; adler1 = (adler >> 16) & 0xffff; - adler0 = adler & 0xffff; + adler0 = adler & 0xffff; rem_peel: if (len < 16) { @@ -60,7 +61,7 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) __m256i vs1_0 = vs1; __m256i vs3 = _mm256_setzero_si256(); - size_t k = MIN(len, NMAX); + uint64_t k = MIN(len, NMAX); k -= k % 32; len -= k; @@ -93,7 +94,7 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) /* The compiler is generating the following sequence for this integer modulus * when done the scalar way, in GPRs: - + adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); @@ -101,9 +102,9 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) ... vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax - imul %rdi,%rsi // do a signed multiplication with magic constant and vector element + imul %rdi,%rsi // do a signed multiplication with magic constant and vector element shr $0x2f,%rsi // shift right by 47 - imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 + imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above ... // repeats for each element with vpextract instructions @@ -111,17 +112,17 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) This is tricky with AVX2 for a number of reasons: 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate - back down to 32 bit precision later (there is in AVX512) + back down to 32 bit precision later (there is in AVX512) 3.) Full width integer multiplications aren't cheap - We can, however, and do a relatively cheap sequence for horizontal sums. + We can, however, and do a relatively cheap sequence for horizontal sums. Then, we simply do the integer modulus on the resulting 64 bit GPR, on a scalar value. It was previously thought that casting to 64 bit precision was needed prior to the horizontal sum, but that is simply not the case, as NMAX is defined as the maximum number of scalar sums that can be performed on the maximum possible inputs before overflow */ - + /* In AVX2-land, this trip through GPRs will probably be unvoidable, as there's no cheap and easy * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly diff --git a/arch/x86/adler32_avx512_tpl.h b/arch/x86/adler32_avx512_tpl.h index d324ce9859..2419865988 100644 --- a/arch/x86/adler32_avx512_tpl.h +++ b/arch/x86/adler32_avx512_tpl.h @@ -14,9 +14,9 @@ #ifdef X86_AVX512_ADLER32 #ifdef COPY -Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { #else -Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, uint64_t len) { #endif if (src == NULL) return 1L; @@ -24,7 +24,7 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t le uint32_t adler0, adler1; adler1 = (adler >> 16) & 0xffff; - adler0 = adler & 0xffff; + adler0 = adler & 0xffff; rem_peel: if (len < 64) { @@ -40,7 +40,7 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t le #elif defined(X86_SSSE3_ADLER32) return adler32_ssse3(adler, src, len); #else - return adler32_len_16(adler0, src, len, adler1); + return adler32_len_16(adler0, src, len, adler1); #endif } @@ -52,7 +52,7 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t le 56, 57, 58, 59, 60, 61, 62, 63, 64); const __m512i dot3v = _mm512_set1_epi16(1); const __m512i zero = _mm512_setzero_si512(); - size_t k; + uint64_t k; while (len >= 64) { __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); @@ -100,7 +100,7 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t le goto rem_peel; } - return adler; + return adler; } #endif diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index 330bfe38e7..ecebdec733 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -18,20 +18,20 @@ #include "adler32_avx512_p.h" #include "adler32_avx2_p.h" -Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, uint64_t len) { if (src == NULL) return 1L; if (len == 0) return adler; uint32_t adler0, adler1; adler1 = (adler >> 16) & 0xffff; - adler0 = adler & 0xffff; + adler0 = adler & 0xffff; rem_peel: if (len < 32) #if defined(X86_SSSE3_ADLER32) return adler32_ssse3(adler, src, len); #else - return adler32_len_16(adler0, src, len, adler1); + return adler32_len_16(adler0, src, len, adler1); #endif if (len < 64) @@ -40,7 +40,7 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size #elif defined(X86_SSE3_ADLER32) return adler32_ssse3(adler, src, len); #else - return adler32_len_16(adler0, src, len, adler1); + return adler32_len_16(adler0, src, len, adler1); #endif const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, @@ -54,7 +54,7 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size while (len >= 64) { vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1)); - size_t k = MIN(len, NMAX); + uint64_t k = MIN(len, NMAX); k -= k % 64; len -= k; __m512i vs1_0 = vs1; @@ -117,16 +117,16 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size goto rem_peel; } - return adler; + return adler; } -Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { if (src == NULL) return 1L; if (len == 0) return adler; uint32_t adler0, adler1; adler1 = (adler >> 16) & 0xffff; - adler0 = adler & 0xffff; + adler0 = adler & 0xffff; rem_peel_copy: if (len < 32) { @@ -138,7 +138,7 @@ Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, #if defined(X86_SSSE3_ADLER32) return adler32_ssse3(adler, src, len); #else - return adler32_len_16(adler0, src, len, adler1); + return adler32_len_16(adler0, src, len, adler1); #endif } @@ -151,7 +151,7 @@ Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, while (len >= 32) { vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0)); vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1)); - size_t k = MIN(len, NMAX); + uint64_t k = MIN(len, NMAX); k -= k % 32; len -= k; __m256i vs1_0 = vs1; @@ -219,7 +219,7 @@ Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, goto rem_peel_copy; } - return adler; + return adler; } #endif diff --git a/arch/x86/adler32_sse42.c b/arch/x86/adler32_sse42.c index 92efe4d8db..5e68e4c41e 100644 --- a/arch/x86/adler32_sse42.c +++ b/arch/x86/adler32_sse42.c @@ -14,10 +14,10 @@ #ifdef X86_SSE42_ADLER32 -Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { uint32_t adler0, adler1; adler1 = (adler >> 16) & 0xffff; - adler0 = adler & 0xffff; + adler0 = adler & 0xffff; rem_peel: if (len < 16) { @@ -31,7 +31,7 @@ Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); const __m128i dot3v = _mm_set1_epi16(1); - size_t k; + uint64_t k; while (len >= 16) { diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 8c55badf98..1c9f58486d 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -14,7 +14,7 @@ #include -Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len) { +Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, uint64_t len) { uint32_t sum2; /* split Adler-32 into component sums */ @@ -46,10 +46,10 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size * additions worthwhile or if it's worth it to just eat the cost of an unaligned * load. This is a pretty simple test, just test if 16 - the remainder + len is * < 16 */ - size_t max_iters = NMAX; - size_t rem = (uintptr_t)buf & 15; - size_t align_offset = 16 - rem; - size_t k = 0; + uint64_t max_iters = NMAX; + uint64_t rem = (uintptr_t)buf & 15; + uint64_t align_offset = 16 - rem; + uint64_t k = 0; if (rem) { if (len < 16 + align_offset) { /* Let's eat the cost of this one unaligned load so that diff --git a/cpu_features.h b/cpu_features.h index 50fdf6156f..84ce3cfdf9 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -23,43 +23,43 @@ extern void cpu_check_features(void); /* adler32 */ -typedef uint32_t (*adler32_func)(uint32_t adler, const unsigned char *buf, size_t len); +typedef uint32_t (*adler32_func)(uint32_t adler, const unsigned char *buf, uint64_t len); -extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len); +extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, uint64_t len); #ifdef ARM_NEON_ADLER32 -extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len); +extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, uint64_t len); #endif #ifdef PPC_VMX_ADLER32 -extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len); +extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, uint64_t len); #endif #ifdef X86_SSSE3_ADLER32 -extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); +extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, uint64_t len); #endif #ifdef X86_AVX2_ADLER32 -extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); +extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, uint64_t len); #endif #ifdef X86_AVX512_ADLER32 -extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len); +extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, uint64_t len); #endif #ifdef X86_AVX512VNNI_ADLER32 -extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len); +extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, uint64_t len); #endif #ifdef POWER8_VSX_ADLER32 -extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len); +extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, uint64_t len); #endif /* adler32 folding */ #ifdef X86_SSE42_ADLER32 -extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); #endif #ifdef X86_AVX2_ADLER32 -extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); #endif #ifdef X86_AVX512_ADLER32 -extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); #endif #ifdef X86_AVX512VNNI_ADLER32 -extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); #endif /* CRC32 folding */ diff --git a/functable.c b/functable.c index 0e0418c25f..4c9bc2d425 100644 --- a/functable.c +++ b/functable.c @@ -162,7 +162,7 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc return functable.longest_match_slow(s, cur_match); } -Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_t len) { +Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, uint64_t len) { // Initialize default functable.adler32 = &adler32_c; cpu_check_features(); @@ -202,7 +202,7 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ return functable.adler32(adler, buf, len); } -Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { functable.adler32_fold_copy = &adler32_fold_copy_c; #if (defined X86_SSE42_ADLER32) if (x86_cpu_has_sse42) diff --git a/functable.h b/functable.h index 6d6d7e4608..932ddcc898 100644 --- a/functable.h +++ b/functable.h @@ -11,8 +11,8 @@ #include "adler32_fold.h" struct functable_s { - uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, size_t len); - uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); + uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, uint64_t len); + uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); uint32_t (* crc32_fold_reset) (crc32_fold *crc); void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index fac4c7f1cd..acc3fe5c11 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -18,7 +18,7 @@ extern "C" { #define MAX_RANDOM_INTS (1024 * 1024) #define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t)) -typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const unsigned char *buf, size_t len); +typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const unsigned char *buf, uint64_t len); class adler32_copy: public benchmark::Fixture { private: @@ -75,7 +75,7 @@ class adler32_copy: public benchmark::Fixture { state.SkipWithError("CPU does not support " #name); \ } \ Bench(state, [](uint32_t init_sum, unsigned char *dst, \ - const unsigned char *buf, size_t len) -> uint32_t { \ + const unsigned char *buf, uint64_t len) -> uint32_t { \ memcpy(dst, buf, len); \ return fptr(init_sum, buf, len); \ }); \ From 2ca4a777612b81c5f811ff27f3b8af1a10bd8ed3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 5 Jun 2022 13:59:44 -0700 Subject: [PATCH 435/798] Used fixed width uint8_t for crc32 and adler32 function declarations. --- adler32.c | 2 +- adler32_p.h | 8 +++--- arch/arm/adler32_neon.c | 6 ++--- arch/arm/crc32_acle.c | 2 +- arch/power/adler32_power8.c | 2 +- arch/power/adler32_vmx.c | 6 ++--- arch/s390/crc32-vx.c | 2 +- arch/x86/adler32_ssse3.c | 2 +- arch/x86/crc32_fold_pclmulqdq.c | 2 +- cpu_features.h | 30 +++++++++++------------ crc32_braid.c | 2 +- crc32_braid_p.h | 2 +- functable.c | 4 +-- functable.h | 4 +-- test/benchmarks/benchmark_adler32_copy.cc | 4 +-- 15 files changed, 39 insertions(+), 39 deletions(-) diff --git a/adler32.c b/adler32.c index 7590d96790..c47f764586 100644 --- a/adler32.c +++ b/adler32.c @@ -8,7 +8,7 @@ #include "adler32_p.h" /* ========================================================================= */ -Z_INTERNAL uint32_t adler32_c(uint32_t adler, const unsigned char *buf, uint64_t len) { +Z_INTERNAL uint32_t adler32_c(uint32_t adler, const uint8_t *buf, uint64_t len) { uint32_t sum2; unsigned n; diff --git a/adler32_p.h b/adler32_p.h index e97f2eac33..8fe41b1422 100644 --- a/adler32_p.h +++ b/adler32_p.h @@ -18,7 +18,7 @@ #define DO8(sum1, sum2, buf, i) {DO4(sum1, sum2, buf, i); DO4(sum1, sum2, buf, i+4);} #define DO16(sum1, sum2, buf) {DO8(sum1, sum2, buf, 0); DO8(sum1, sum2, buf, 8);} -static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, uint32_t sum2) { +static inline uint32_t adler32_len_1(uint32_t adler, const uint8_t *buf, uint32_t sum2) { adler += buf[0]; adler %= BASE; sum2 += adler; @@ -26,7 +26,7 @@ static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, u return adler | (sum2 << 16); } -static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, uint64_t len, uint32_t sum2) { +static inline uint32_t adler32_len_16(uint32_t adler, const uint8_t *buf, uint64_t len, uint32_t sum2) { while (len) { --len; adler += *buf++; @@ -38,7 +38,7 @@ static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, return adler | (sum2 << 16); } -static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char *buf, uint8_t *dst, uint64_t len, uint32_t sum2) { +static inline uint32_t adler32_copy_len_16(uint32_t adler, const uint8_t *buf, uint8_t *dst, uint64_t len, uint32_t sum2) { while (len--) { *dst = *buf++; adler += *dst++; @@ -50,7 +50,7 @@ static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char * return adler | (sum2 << 16); } -static inline uint32_t adler32_len_64(uint32_t adler, const unsigned char *buf, uint64_t len, uint32_t sum2) { +static inline uint32_t adler32_len_64(uint32_t adler, const uint8_t *buf, uint64_t len, uint32_t sum2) { #ifdef UNROLL_MORE while (len >= 16) { len -= 16; diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index 08032672e7..0e2a1b4033 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -15,7 +15,7 @@ #include "../../adler32_p.h" #include "../../fallback_builtins.h" -static void NEON_accum32(uint32_t *s, const unsigned char *buf, uint64_t len) { +static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { static const uint16_t ALIGNED_(16) taps[64] = { 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, @@ -138,7 +138,7 @@ static void NEON_accum32(uint32_t *s, const unsigned char *buf, uint64_t len) { s[1] = vget_lane_u32(as, 1); } -static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf, uint64_t len) { +static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, uint64_t len) { unsigned int i; for (i = 0; i < len; ++i) { pair[0] += buf[i]; @@ -146,7 +146,7 @@ static void NEON_handle_tail(uint32_t *pair, const unsigned char *buf, uint64_t } } -uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, uint64_t len) { +uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, uint64_t len) { /* split Adler-32 into component sums */ uint32_t sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index 6f6ed45373..68cdafa314 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -11,7 +11,7 @@ #endif #include "../../zbuild.h" -uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len) { +uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { Z_REGISTER uint32_t c; Z_REGISTER const uint16_t *buf2; Z_REGISTER const uint32_t *buf4; diff --git a/arch/power/adler32_power8.c b/arch/power/adler32_power8.c index fe5e46eaa8..0e8e0d162c 100644 --- a/arch/power/adler32_power8.c +++ b/arch/power/adler32_power8.c @@ -52,7 +52,7 @@ static inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsi return __a; } -uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, uint64_t len) { +uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, uint64_t len) { uint32_t s1 = adler & 0xffff; uint32_t s2 = (adler >> 16) & 0xffff; diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index 11fe559449..2c8eb68270 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -12,7 +12,7 @@ #define vmx_zero() (vec_splat_u32(0)) -static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char *buf, uint64_t len) { +static inline void vmx_handle_head_or_tail(uint32_t *pair, const uint8_t *buf, uint64_t len) { unsigned int i; for (i = 0; i < len; ++i) { pair[0] += buf[i]; @@ -20,7 +20,7 @@ static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char * } } -static void vmx_accum32(uint32_t *s, const unsigned char *buf, uint64_t len) { +static void vmx_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { /* Different taps for the separable components of sums */ const vector unsigned char t0 = {64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49}; const vector unsigned char t1 = {48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33}; @@ -113,7 +113,7 @@ static void vmx_accum32(uint32_t *s, const unsigned char *buf, uint64_t len) { vec_ste(s2acc, 0, s+1); } -uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, uint64_t len) { +uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, uint64_t len) { uint32_t sum2; uint32_t pair[16] ALIGNED_(16); memset(&pair[2], 0, 14); diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index 0888003445..340846083e 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -21,7 +21,7 @@ typedef unsigned char uv16qi __attribute__((vector_size(16))); typedef unsigned int uv4si __attribute__((vector_size(16))); typedef unsigned long long uv2di __attribute__((vector_size(16))); -static uint32_t crc32_le_vgfm_16(uint32_t crc, const unsigned char *buf, uint64_t len) { +static uint32_t crc32_le_vgfm_16(uint32_t crc, const uint8_t *buf, uint64_t len) { /* * The CRC-32 constant block contains reduction constants to fold and * process particular chunks of the input data stream in parallel. diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 1c9f58486d..45fddd42af 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -14,7 +14,7 @@ #include -Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, uint64_t len) { +Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, uint64_t len) { uint32_t sum2; /* split Adler-32 into component sums */ diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 3d0eaf3531..104455e36e 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -341,7 +341,7 @@ Z_INTERNAL uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc) { return crc->value; } -uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len) { +uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, uint64_t len) { /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for * these short lengths might also prove to be effective */ if (len < 64) diff --git a/cpu_features.h b/cpu_features.h index 84ce3cfdf9..84c5115632 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -23,29 +23,29 @@ extern void cpu_check_features(void); /* adler32 */ -typedef uint32_t (*adler32_func)(uint32_t adler, const unsigned char *buf, uint64_t len); +typedef uint32_t (*adler32_func)(uint32_t adler, const uint8_t *buf, uint64_t len); -extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, uint64_t len); +extern uint32_t adler32_c(uint32_t adler, const uint8_t *buf, uint64_t len); #ifdef ARM_NEON_ADLER32 -extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, uint64_t len); +extern uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, uint64_t len); #endif #ifdef PPC_VMX_ADLER32 -extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, uint64_t len); +extern uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, uint64_t len); #endif #ifdef X86_SSSE3_ADLER32 -extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, uint64_t len); +extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, uint64_t len); #endif #ifdef X86_AVX2_ADLER32 -extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, uint64_t len); +extern uint32_t adler32_avx2(uint32_t adler, const uint8_t *buf, uint64_t len); #endif #ifdef X86_AVX512_ADLER32 -extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, uint64_t len); +extern uint32_t adler32_avx512(uint32_t adler, const uint8_t *buf, uint64_t len); #endif #ifdef X86_AVX512VNNI_ADLER32 -extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, uint64_t len); +extern uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *buf, uint64_t len); #endif #ifdef POWER8_VSX_ADLER32 -extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, uint64_t len); +extern uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, uint64_t len); #endif /* adler32 folding */ @@ -68,7 +68,7 @@ extern uint32_t crc32_fold_pclmulqdq_reset(crc32_fold *crc); extern void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); extern uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc); -extern uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len); +extern uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, uint64_t len); #endif /* memory chunking */ @@ -111,15 +111,15 @@ extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned le #endif /* CRC32 */ -typedef uint32_t (*crc32_func)(uint32_t crc32, const unsigned char * buf, uint64_t len); +typedef uint32_t (*crc32_func)(uint32_t crc32, const uint8_t *buf, uint64_t len); -extern uint32_t crc32_braid(uint32_t crc, const unsigned char *buf, uint64_t len); +extern uint32_t crc32_braid(uint32_t crc, const uint8_t *buf, uint64_t len); #ifdef ARM_ACLE_CRC_HASH -extern uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len); +extern uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len); #elif defined(POWER8_VSX_CRC32) -extern uint32_t crc32_power8(uint32_t crc, const unsigned char *buf, uint64_t len); +extern uint32_t crc32_power8(uint32_t crc, const uint8_t *buf, uint64_t len); #elif defined(S390_CRC32_VX) -extern uint32_t PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf, uint64_t len); +extern uint32_t PREFIX(s390_crc32_vx)(uint32_t crc, const uint8_t *buf, uint64_t len); #endif /* compare256 */ diff --git a/crc32_braid.c b/crc32_braid.c index f5b223eeab..07af068de1 100644 --- a/crc32_braid.c +++ b/crc32_braid.c @@ -111,7 +111,7 @@ static z_word_t crc_word(z_word_t data) { #endif /* W */ /* ========================================================================= */ -Z_INTERNAL uint32_t crc32_braid(uint32_t crc, const unsigned char *buf, uint64_t len) { +Z_INTERNAL uint32_t crc32_braid(uint32_t crc, const uint8_t *buf, uint64_t len) { Z_REGISTER uint32_t c; /* Pre-condition the CRC */ diff --git a/crc32_braid_p.h b/crc32_braid_p.h index 80c0f14b9c..53b7f53a66 100644 --- a/crc32_braid_p.h +++ b/crc32_braid_p.h @@ -45,6 +45,6 @@ /* CRC polynomial. */ #define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ -extern uint32_t crc32_braid(uint32_t crc, const unsigned char *buf, uint64_t len); +extern uint32_t crc32_braid(uint32_t crc, const uint8_t *buf, uint64_t len); #endif /* CRC32_BRAID_P_H_ */ diff --git a/functable.c b/functable.c index 4c9bc2d425..a96caafc5f 100644 --- a/functable.c +++ b/functable.c @@ -162,7 +162,7 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc return functable.longest_match_slow(s, cur_match); } -Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, uint64_t len) { +Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const uint8_t *buf, uint64_t len) { // Initialize default functable.adler32 = &adler32_c; cpu_check_features(); @@ -403,7 +403,7 @@ Z_INTERNAL uint8_t* chunkmemset_safe_stub(uint8_t *out, unsigned dist, unsigned return functable.chunkmemset_safe(out, dist, len, left); } -Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t len) { +Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const uint8_t *buf, uint64_t len) { Assert(sizeof(uint64_t) >= sizeof(size_t), "crc32_z takes size_t but internally we have a uint64_t len"); diff --git a/functable.h b/functable.h index 932ddcc898..838af2fd95 100644 --- a/functable.h +++ b/functable.h @@ -11,9 +11,9 @@ #include "adler32_fold.h" struct functable_s { - uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, uint64_t len); + uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, uint64_t len); uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); - uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); + uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, uint64_t len); uint32_t (* crc32_fold_reset) (crc32_fold *crc); void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); void (* crc32_fold) (crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index acc3fe5c11..81fdc4a0c6 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -18,7 +18,7 @@ extern "C" { #define MAX_RANDOM_INTS (1024 * 1024) #define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t)) -typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const unsigned char *buf, uint64_t len); +typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const uint8_t *buf, uint64_t len); class adler32_copy: public benchmark::Fixture { private: @@ -75,7 +75,7 @@ class adler32_copy: public benchmark::Fixture { state.SkipWithError("CPU does not support " #name); \ } \ Bench(state, [](uint32_t init_sum, unsigned char *dst, \ - const unsigned char *buf, uint64_t len) -> uint32_t { \ + const uint8_t *buf, uint64_t len) -> uint32_t { \ memcpy(dst, buf, len); \ return fptr(init_sum, buf, len); \ }); \ From d47d1c5756235d4e953a5dcaed43a13fe25c3584 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Fri, 3 Jun 2022 15:38:19 +0200 Subject: [PATCH 436/798] Add a test for concurrently modifying deflate() input The test simulates what one of the QEMU live migration tests is doing: increments each buffer byte by 1 while deflate()ing it. The test tries to produce a race condition and therefore is probabilistic. The longer it runs, the better are the chances to catch an issue. The scenario in question is known to be broken on IBM Z with DFLTCC, and there it is caught in 100ms most of the time. The run time is therefore set to 1 second in order to balance usability and reliability. --- test/CMakeLists.txt | 13 ++- test/test_deflate_concurrency.cc | 170 +++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 test/test_deflate_concurrency.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fc06ce7ba0..3a47e8b275 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,9 +22,6 @@ if(NOT TARGET GTest::GTest) # Prevent overriding the parent project's compiler/linker settings for Windows set(gtest_force_shared_crt ON CACHE BOOL "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) - # Disable pthreads for simplicity - set(gtest_disable_pthreads ON CACHE BOOL - "Disable uses of pthreads in gtest." FORCE) # Allow specifying alternative Google test repository if(NOT DEFINED GTEST_REPOSITORY) @@ -100,6 +97,16 @@ endif() target_link_libraries(gtest_zlib zlibstatic GTest::GTest) +find_package(Threads) +if(Threads_FOUND) + target_sources(gtest_zlib PRIVATE test_deflate_concurrency.cc) + if(UNIX AND NOT APPLE) + # On Linux, use a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590 + target_link_libraries(gtest_zlib -Wl,--whole-archive -lpthread -Wl,--no-whole-archive) + endif() + target_link_libraries(gtest_zlib Threads::Threads) +endif() + if(ZLIB_ENABLE_TESTS) add_test(NAME gtest_zlib COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) diff --git a/test/test_deflate_concurrency.cc b/test/test_deflate_concurrency.cc new file mode 100644 index 0000000000..1297aee644 --- /dev/null +++ b/test/test_deflate_concurrency.cc @@ -0,0 +1,170 @@ +/* Test deflate() on concurrently modified next_in. + * + * Plain zlib does not document that this is supported, but in practice it tolerates this, and QEMU live migration is + * known to rely on this. Make sure zlib-ng tolerates this as well. + */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +#include "zlib.h" +#else +#include "zlib-ng.h" +#endif + +#include + +#include +#include +#include +#include + +static uint8_t buf[8 * 1024]; +static uint8_t zbuf[4 * 1024]; +static uint8_t tmp[8 * 1024]; + +/* Thread that increments all bytes in buf by 1. */ +class Mutator { + enum class State { + PAUSED, + RUNNING, + STOPPED, + }; + +public: + Mutator() + : m_state(State::PAUSED), m_target_state(State::PAUSED), + m_thread(&Mutator::run, this) {} + ~Mutator() { + transition(State::STOPPED); + m_thread.join(); + } + + void pause() { + transition(State::PAUSED); + } + + void resume() { + transition(State::RUNNING); + } + +private: + void run() { + while (true) { + m_state.store(m_target_state); + if (m_state == State::PAUSED) + continue; + if (m_state == State::STOPPED) + break; + for (uint8_t & i: buf) + i++; + } + } + + void transition(State target_state) { + m_target_state = target_state; + while (m_state != target_state) { + } + } + + std::atomic m_state, m_target_state; + std::thread m_thread; +}; + +TEST(deflate, concurrency) { +#ifdef S390_DFLTCC_DEFLATE + GTEST_SKIP() << "Known to be broken with S390_DFLTCC_DEFLATE"; +#endif + + /* Create reusable mutator and streams. */ + Mutator mutator; + + PREFIX3(stream) dstrm; + memset(&dstrm, 0, sizeof(dstrm)); + int err = PREFIX(deflateInit2)(&dstrm, Z_BEST_SPEED, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + ASSERT_EQ(Z_OK, err) << dstrm.msg; + + PREFIX3(stream) istrm; + memset(&istrm, 0, sizeof(istrm)); + err = PREFIX(inflateInit2)(&istrm, -15); + ASSERT_EQ(Z_OK, err) << istrm.msg; + + /* Iterate for a certain amount of time. */ + auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(1); + while (std::chrono::steady_clock::now() < deadline) { + /* Start each iteration with a fresh stream state. */ + err = PREFIX(deflateReset)(&dstrm); + ASSERT_EQ(Z_OK, err) << dstrm.msg; + + err = PREFIX(inflateReset)(&istrm); + ASSERT_EQ(Z_OK, err) << istrm.msg; + + /* Mutate and compress the first half of buf concurrently. + * Decompress and throw away the results, which are unpredictable. + */ + mutator.resume(); + dstrm.next_in = buf; + dstrm.avail_in = sizeof(buf) / 2; + while (dstrm.avail_in > 0) { + dstrm.next_out = zbuf; + dstrm.avail_out = sizeof(zbuf); + err = PREFIX(deflate)(&dstrm, Z_NO_FLUSH); + ASSERT_EQ(Z_OK, err) << dstrm.msg; + istrm.next_in = zbuf; + istrm.avail_in = sizeof(zbuf) - dstrm.avail_out; + while (istrm.avail_in > 0) { + istrm.next_out = tmp; + istrm.avail_out = sizeof(tmp); + err = PREFIX(inflate)(&istrm, Z_NO_FLUSH); + ASSERT_EQ(Z_OK, err) << istrm.msg; + } + } + + /* Stop mutation and compress the second half of buf. + * Decompress and check that the result matches. + */ + mutator.pause(); + dstrm.next_in = buf + sizeof(buf) / 2; + dstrm.avail_in = sizeof(buf) - sizeof(buf) / 2; + while (dstrm.avail_in > 0) { + dstrm.next_out = zbuf; + dstrm.avail_out = sizeof(zbuf); + err = PREFIX(deflate)(&dstrm, Z_FINISH); + if (err == Z_STREAM_END) + ASSERT_EQ(0u, dstrm.avail_in); + else + ASSERT_EQ(Z_OK, err) << dstrm.msg; + istrm.next_in = zbuf; + istrm.avail_in = sizeof(zbuf) - dstrm.avail_out; + while (istrm.avail_in > 0) { + size_t orig_total_out = istrm.total_out; + istrm.next_out = tmp; + istrm.avail_out = sizeof(tmp); + err = PREFIX(inflate)(&istrm, Z_NO_FLUSH); + if (err == Z_STREAM_END) + ASSERT_EQ(0u, istrm.avail_in); + else + ASSERT_EQ(Z_OK, err) << istrm.msg; + size_t concurrent_size = sizeof(buf) - sizeof(buf) / 2; + if (istrm.total_out > concurrent_size) { + size_t tmp_offset, buf_offset, size; + if (orig_total_out >= concurrent_size) { + tmp_offset = 0; + buf_offset = orig_total_out - concurrent_size; + size = istrm.total_out - orig_total_out; + } else { + tmp_offset = concurrent_size - orig_total_out; + buf_offset = 0; + size = istrm.total_out - concurrent_size; + } + ASSERT_EQ(0, memcmp(tmp + tmp_offset, buf + sizeof(buf) / 2 + buf_offset, size)); + } + } + } + } + + err = PREFIX(inflateEnd)(&istrm); + ASSERT_EQ(Z_OK, err) << istrm.msg; + + err = PREFIX(deflateEnd)(&dstrm); + ASSERT_EQ(Z_OK, err) << istrm.msg; +} From 1f5ddcc009ac3511e99fc88736a9e1a6381168c5 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 14 Jun 2022 11:19:29 +0200 Subject: [PATCH 437/798] IBM Z DFLTCC: Test with MSan * Add a CI job. * Do not collect coverage: LLVM's gcov support (part of compiler-rt) cannot be built with the MSan instrumentation, which means that whenever it's called (in particular, in order to write the results to a file at the end), there is a risk of false positives. * Add __msan_unpoison() calls to DFLTCC inline assembly. * Make parameter block sizes symbolic constants. * Move dfltcc() definition after struct dfltcc_param_v0 definition. --- .github/workflows/cmake.yml | 6 + arch/s390/dfltcc_detail.h | 176 ++++++++++-------- .../actions-runner.Dockerfile | 2 + 3 files changed, 111 insertions(+), 73 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 43eb8d5c34..9158ce7b7f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -255,6 +255,12 @@ jobs: ldflags: -static codecov: ubuntu_gcc_s390x_dfltcc_compat + - name: Ubuntu Clang S390X DFLTCC MSAN + os: z15 + compiler: clang-11 + cxx-compiler: clang++-11 + cmake-args: -GNinja -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Memory + - name: Ubuntu MinGW i686 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake diff --git a/arch/s390/dfltcc_detail.h b/arch/s390/dfltcc_detail.h index 82924231ea..37e23bc122 100644 --- a/arch/s390/dfltcc_detail.h +++ b/arch/s390/dfltcc_detail.h @@ -26,74 +26,6 @@ #define DFLTCC_RIBM 0 #endif -/* - C wrapper for the DEFLATE CONVERSION CALL instruction. - */ -typedef enum { - DFLTCC_CC_OK = 0, - DFLTCC_CC_OP1_TOO_SHORT = 1, - DFLTCC_CC_OP2_TOO_SHORT = 2, - DFLTCC_CC_OP2_CORRUPT = 2, - DFLTCC_CC_AGAIN = 3, -} dfltcc_cc; - -#define DFLTCC_QAF 0 -#define DFLTCC_GDHT 1 -#define DFLTCC_CMPR 2 -#define DFLTCC_XPND 4 -#define HBT_CIRCULAR (1 << 7) -#define HB_BITS 15 -#define HB_SIZE (1 << HB_BITS) -#define DFLTCC_FACILITY 151 - -static inline dfltcc_cc dfltcc(int fn, void *param, - unsigned char **op1, size_t *len1, z_const unsigned char **op2, size_t *len2, void *hist) { - unsigned char *t2 = op1 ? *op1 : NULL; - size_t t3 = len1 ? *len1 : 0; - z_const unsigned char *t4 = op2 ? *op2 : NULL; - size_t t5 = len2 ? *len2 : 0; - Z_REGISTER int r0 __asm__("r0") = fn; - Z_REGISTER void *r1 __asm__("r1") = param; - Z_REGISTER unsigned char *r2 __asm__("r2") = t2; - Z_REGISTER size_t r3 __asm__("r3") = t3; - Z_REGISTER z_const unsigned char *r4 __asm__("r4") = t4; - Z_REGISTER size_t r5 __asm__("r5") = t5; - int cc; - - __asm__ volatile( -#ifdef HAVE_SYS_SDT_H - STAP_PROBE_ASM(zlib, dfltcc_entry, STAP_PROBE_ASM_TEMPLATE(5)) -#endif - ".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n" -#ifdef HAVE_SYS_SDT_H - STAP_PROBE_ASM(zlib, dfltcc_exit, STAP_PROBE_ASM_TEMPLATE(5)) -#endif - "ipm %[cc]\n" - : [r2] "+r" (r2) - , [r3] "+r" (r3) - , [r4] "+r" (r4) - , [r5] "+r" (r5) - , [cc] "=r" (cc) - : [r0] "r" (r0) - , [r1] "r" (r1) - , [hist] "r" (hist) -#ifdef HAVE_SYS_SDT_H - , STAP_PROBE_ASM_OPERANDS(5, r2, r3, r4, r5, hist) -#endif - : "cc", "memory"); - t2 = r2; t3 = r3; t4 = r4; t5 = r5; - - if (op1) - *op1 = t2; - if (len1) - *len1 = t3; - if (op2) - *op2 = t4; - if (len2) - *len2 = t5; - return (cc >> 28) & 3; -} - /* Parameter Block for Query Available Functions. */ @@ -106,7 +38,8 @@ struct dfltcc_qaf_param { char reserved2[6]; }; -static_assert(sizeof(struct dfltcc_qaf_param) == 32, sizeof_struct_dfltcc_qaf_param_is_32); +#define DFLTCC_SIZEOF_QAF 32 +static_assert(sizeof(struct dfltcc_qaf_param) == DFLTCC_SIZEOF_QAF, qaf); static inline int is_bit_set(const char *bits, int n) { return bits[n / 8] & (1 << (7 - (n % 8))); @@ -116,6 +49,8 @@ static inline void clear_bit(char *bits, int n) { bits[n / 8] &= ~(1 << (7 - (n % 8))); } +#define DFLTCC_FACILITY 151 + static inline int is_dfltcc_enabled(void) { uint64_t facilities[(DFLTCC_FACILITY / 64) + 1]; Z_REGISTER uint8_t r0 __asm__("r0"); @@ -189,12 +124,16 @@ struct dfltcc_param_v0 { uint16_t cdhtl : 12; /* Compressed-Dynamic-Huffman Table Length */ uint8_t reserved464[6]; - uint8_t cdht[288]; - uint8_t reserved[32]; - uint8_t csb[1152]; + uint8_t cdht[288]; /* Compressed-Dynamic-Huffman Table */ + uint8_t reserved[24]; + uint8_t ribm2[8]; /* Reserved for IBM use */ + uint8_t csb[1152]; /* Continuation-State Buffer */ }; -static_assert(sizeof(struct dfltcc_param_v0) == 1536, sizeof_struct_dfltcc_param_v0_is_1536); +#define DFLTCC_SIZEOF_GDHT_V0 384 +#define DFLTCC_SIZEOF_CMPR_XPND_V0 1536 +static_assert(offsetof(struct dfltcc_param_v0, csb) == DFLTCC_SIZEOF_GDHT_V0, gdht_v0); +static_assert(sizeof(struct dfltcc_param_v0) == DFLTCC_SIZEOF_CMPR_XPND_V0, cmpr_xpnd_v0); static inline z_const char *oesc_msg(char *buf, int oesc) { if (oesc == 0x00) @@ -205,6 +144,97 @@ static inline z_const char *oesc_msg(char *buf, int oesc) { } } +/* + C wrapper for the DEFLATE CONVERSION CALL instruction. + */ +typedef enum { + DFLTCC_CC_OK = 0, + DFLTCC_CC_OP1_TOO_SHORT = 1, + DFLTCC_CC_OP2_TOO_SHORT = 2, + DFLTCC_CC_OP2_CORRUPT = 2, + DFLTCC_CC_AGAIN = 3, +} dfltcc_cc; + +#define DFLTCC_QAF 0 +#define DFLTCC_GDHT 1 +#define DFLTCC_CMPR 2 +#define DFLTCC_XPND 4 +#define HBT_CIRCULAR (1 << 7) +#define DFLTCC_FN_MASK ((1 << 7) - 1) +#define HB_BITS 15 +#define HB_SIZE (1 << HB_BITS) + +static inline dfltcc_cc dfltcc(int fn, void *param, + unsigned char **op1, size_t *len1, + z_const unsigned char **op2, size_t *len2, void *hist) { + unsigned char *t2 = op1 ? *op1 : NULL; +#ifdef Z_MEMORY_SANITIZER + unsigned char *orig_t2 = t2; +#endif + size_t t3 = len1 ? *len1 : 0; + z_const unsigned char *t4 = op2 ? *op2 : NULL; + size_t t5 = len2 ? *len2 : 0; + Z_REGISTER int r0 __asm__("r0") = fn; + Z_REGISTER void *r1 __asm__("r1") = param; + Z_REGISTER unsigned char *r2 __asm__("r2") = t2; + Z_REGISTER size_t r3 __asm__("r3") = t3; + Z_REGISTER z_const unsigned char *r4 __asm__("r4") = t4; + Z_REGISTER size_t r5 __asm__("r5") = t5; + int cc; + + __asm__ volatile( +#ifdef HAVE_SYS_SDT_H + STAP_PROBE_ASM(zlib, dfltcc_entry, STAP_PROBE_ASM_TEMPLATE(5)) +#endif + ".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n" +#ifdef HAVE_SYS_SDT_H + STAP_PROBE_ASM(zlib, dfltcc_exit, STAP_PROBE_ASM_TEMPLATE(5)) +#endif + "ipm %[cc]\n" + : [r2] "+r" (r2) + , [r3] "+r" (r3) + , [r4] "+r" (r4) + , [r5] "+r" (r5) + , [cc] "=r" (cc) + : [r0] "r" (r0) + , [r1] "r" (r1) + , [hist] "r" (hist) +#ifdef HAVE_SYS_SDT_H + , STAP_PROBE_ASM_OPERANDS(5, r2, r3, r4, r5, hist) +#endif + : "cc", "memory"); + t2 = r2; t3 = r3; t4 = r4; t5 = r5; + +#ifdef Z_MEMORY_SANITIZER + switch (fn & DFLTCC_FN_MASK) { + case DFLTCC_QAF: + __msan_unpoison(param, DFLTCC_SIZEOF_QAF); + break; + case DFLTCC_GDHT: + __msan_unpoison(param, DFLTCC_SIZEOF_GDHT_V0); + break; + case DFLTCC_CMPR: + __msan_unpoison(param, DFLTCC_SIZEOF_CMPR_XPND_V0); + __msan_unpoison(orig_t2, t2 - orig_t2 + (((struct dfltcc_param_v0 *)param)->sbb == 0 ? 0 : 1)); + break; + case DFLTCC_XPND: + __msan_unpoison(param, DFLTCC_SIZEOF_CMPR_XPND_V0); + __msan_unpoison(orig_t2, t2 - orig_t2); + break; + } +#endif + + if (op1) + *op1 = t2; + if (len1) + *len1 = t3; + if (op2) + *op2 = t4; + if (len2) + *len2 = t5; + return (cc >> 28) & 3; +} + /* Extension of inflate_state and deflate_state. Must be doubleword-aligned. */ diff --git a/arch/s390/self-hosted-builder/actions-runner.Dockerfile b/arch/s390/self-hosted-builder/actions-runner.Dockerfile index 5e247fd9d3..136eec77a5 100644 --- a/arch/s390/self-hosted-builder/actions-runner.Dockerfile +++ b/arch/s390/self-hosted-builder/actions-runner.Dockerfile @@ -11,6 +11,7 @@ FROM s390x/ubuntu:20.04 # Packages for zlib-ng testing. ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get -y install \ + clang-11 \ cmake \ curl \ gcc \ @@ -18,6 +19,7 @@ RUN apt-get update && apt-get -y install \ jq \ libxml2-dev \ libxslt-dev \ + llvm-11-tools \ ninja-build \ python-is-python3 \ python3 \ From 428aa9ab4239d5fa7c760360fc5e07f64abb0b66 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 15 Jun 2022 19:10:43 +0200 Subject: [PATCH 438/798] IBM Z DFLTCC: Simplify includes in dfltcc_detail.h Include zbuild.h instead of the standard headers. Keep stdio.h, since it's provided only conditionally. Suggested-by: Nathan Moinvaziri --- arch/s390/dfltcc_detail.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/s390/dfltcc_detail.h b/arch/s390/dfltcc_detail.h index 37e23bc122..e1d625b84a 100644 --- a/arch/s390/dfltcc_detail.h +++ b/arch/s390/dfltcc_detail.h @@ -1,7 +1,5 @@ -#include -#include +#include "../../zbuild.h" #include -#include #ifdef HAVE_SYS_SDT_H #include From dda87d2b181aae0d9e00f8b0312d8615e1e10310 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 09:02:27 -0700 Subject: [PATCH 439/798] Improve dual link test to compile against zlib. Previously we were only linking against it. --- .github/workflows/cmake.yml | 6 ------ CMakeLists.txt | 6 ------ test/CMakeLists.txt | 15 +++++++++++++++ test/test_compress_dual.cc | 28 ++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 test/test_compress_dual.cc diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9158ce7b7f..9667d5f79b 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -83,12 +83,6 @@ jobs: cmake-args: -DWITH_OPTIM=OFF -DHAVE_BUILTIN_CTZLL=OFF -DHAVE_BUILTIN_CTZ=OFF codecov: ubuntu_gcc_no_ctz - - name: Ubuntu GCC Link Zlib - os: ubuntu-latest - compiler: gcc - cxx-compiler: g++ - cmake-args: -DZLIB_DUAL_LINK=ON - - name: Ubuntu GCC No AVX2 UBSAN os: ubuntu-latest compiler: gcc diff --git a/CMakeLists.txt b/CMakeLists.txt index 07c7753776..fae09c7c70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1191,12 +1191,6 @@ if(ZLIB_ENABLE_TESTS) target_compile_definitions(${target} PUBLIC -DWITH_GZFILEOP) target_sources(${target} PRIVATE ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) endif() - if(ZLIB_DUAL_LINK) - find_package(ZLIB) - if(ZLIB_FOUND) - target_link_libraries(${target} ${ZLIB_LIBRARIES}) - endif() - endif() endmacro() macro(add_simple_test_executable target) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3a47e8b275..f30f9ac3a0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -95,6 +95,21 @@ if(WITH_SANITIZER STREQUAL "Memory") -fsanitize-memory-track-origins) endif() +if(ZLIB_DUAL_LINK AND NOT ZLIB_COMPAT) + find_package(ZLIB) + if(ZLIB_FOUND) + message(STATUS "Added dual linking tests against zlib") + message(STATUS " Zlib include dir: ${ZLIB_INCLUDE_DIR}") + message(STATUS " Zlib libraries: ${ZLIB_LIBRARIES}") + + target_sources(gtest_zlib PRIVATE test_compress_dual.cc) + target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIR}) + target_link_libraries(gtest_zlib ${ZLIB_LIBRARIES}) + else() + message(WARNING "Zlib not found, skipping dual linking tests") + endif() +endif() + target_link_libraries(gtest_zlib zlibstatic GTest::GTest) find_package(Threads) diff --git a/test/test_compress_dual.cc b/test/test_compress_dual.cc new file mode 100644 index 0000000000..a92ab4be39 --- /dev/null +++ b/test/test_compress_dual.cc @@ -0,0 +1,28 @@ +/* test_compress_dual.cc - Test linking against both zlib and zlib-ng */ + +#include "zlib.h" + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(compress, basic_zlib) { + Byte compr[128], uncompr[128]; + uLong compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); + int err; + + err = compress(compr, &compr_len, (const unsigned char *)hello, hello_len); + EXPECT_EQ(err, Z_OK); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncompr_len, compr, compr_len); + EXPECT_EQ(err, Z_OK); + + EXPECT_STREQ((char *)uncompr, (char *)hello); +} From 88be8b7917536768af87c0cc717558e94f37f00e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 08:52:38 -0700 Subject: [PATCH 440/798] Added workflow to test linking zlib and zlib-ng compat against native zlib-ng. --- .github/workflows/link.yml | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/link.yml diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml new file mode 100644 index 0000000000..892f1afcd0 --- /dev/null +++ b/.github/workflows/link.yml @@ -0,0 +1,66 @@ +name: CI Link +on: [push, pull_request] +jobs: + zlib: + name: Link zlib + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Checkout zlib repository + uses: actions/checkout@v3 + with: + repository: madler/zlib + path: zlib + + - name: Generate project files (zlib) + run: cmake -S zlib -B zlib/build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF + + - name: Compile source code (zlib) + run: cmake --build zlib/build --config Release + + - name: Generate project files (native) + run: cmake -S . -B native -DZLIB_COMPAT=OFF -DZLIB_DUAL_LINK=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_ROOT=../zlib/build -DZLIB_LIBRARIES=../zlib/build/libz.a -DZLIB_INCLUDE_DIR=../zlib/build + + - name: Compile source code (native) + run: cmake --build native --config Release + + - name: Upload build errors + uses: actions/upload-artifact@v2 + if: failure() + with: + name: Link zlib (CMake Logs) + path: | + **/CMakeFiles/CMakeOutput.log + **/CMakeFiles/CMakeError.log + retention-days: 30 + + zlib-ng-compat: + name: Link zlib-ng compat + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Generate project files (compat) + run: cmake -S . -B compat -DZLIB_COMPAT=ON -DZLIB_ENABLE_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWITH_MAINTAINER_WARNINGS=ON + + - name: Compile source code (compat) + run: cmake --build compat --config Release + + - name: Generate project files (native) + run: cmake -S . -B native -DZLIB_COMPAT=OFF -DZLIB_DUAL_LINK=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_ROOT=../compat -DZLIB_LIBRARIES=../compat/libz.a -DZLIB_INCLUDE_DIR=../compat + + - name: Compile source code (native) + run: cmake --build native --config Release + + - name: Upload build errors + uses: actions/upload-artifact@v2 + if: failure() + with: + name: Link zlib-ng compat (CMake Logs) + path: | + **/CMakeFiles/CMakeOutput.log + **/CMakeFiles/CMakeError.log + retention-days: 30 From 1bcd15eaf32dbfcd834f1b21f5894edd6b466095 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Thu, 2 Jun 2022 18:46:56 -0400 Subject: [PATCH 441/798] Improve the swizzle of the memory magazine fed in a chunk copy for neon Like the x86 variant, we can leverage the same tables to load a vector register worth of values. This shows a vast improvement in places where very large run length encodes can be found in the lz runs. --- arch/arm/chunkset_neon.c | 46 +++++++++++++++++++++ arch/{x86 => generic}/chunk_permute_table.h | 0 arch/x86/chunkset_avx.c | 2 +- arch/x86/chunkset_sse41.c | 2 +- 4 files changed, 48 insertions(+), 2 deletions(-) rename arch/{x86 => generic}/chunk_permute_table.h (100%) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index ca8420d345..29065f77c4 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -9,6 +9,7 @@ # include #endif #include "../../zbuild.h" +#include "../generic/chunk_permute_table.h" typedef uint8x16_t chunk_t; @@ -17,6 +18,23 @@ typedef uint8x16_t chunk_t; #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 #define HAVE_CHUNKMEMSET_8 +#define HAVE_CHUNK_MAG + +static const lut_rem_pair perm_idx_lut[13] = { + {0, 1}, /* 3 */ + {0, 0}, /* don't care */ + {1 * 32, 1}, /* 5 */ + {2 * 32, 4}, /* 6 */ + {3 * 32, 2}, /* 7 */ + {0 * 32, 0}, /* don't care */ + {4 * 32, 7}, /* 9 */ + {5 * 32, 6}, /* 10 */ + {6 * 32, 5}, /* 11 */ + {7 * 32, 4}, /* 12 */ + {8 * 32, 3}, /* 13 */ + {9 * 32, 2}, /* 14 */ + {10 * 32, 1},/* 15 */ +}; static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { uint16_t tmp; @@ -50,6 +68,34 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { vst1q_u8(out, *chunk); } +static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { + lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; + *chunk_rem = lut_rem.remval; + +#ifdef Z_MEMORY_SANITIZER + /* See note in chunkset_sse41.c for why this is ok */ + __msan_unpoison(buf + dist, 16 - dist); +#endif + + /* This version of table is only available on aarch64 */ +#if defined(_M_ARM64) || defined(__aarch64__) + uint8x16_t ret_vec = vld1q_u8(buf); + + uint8x16_t perm_vec = vld1q_u8(permute_table + lut_rem.idx); + return vqtbl1q_u8(ret_vec, perm_vec); +#else + uint8x8_t ret0, ret1, a, b, perm_vec0, perm_vec1; + perm_vec0 = vld1_u8(permute_table + lut_rem.idx); + perm_vec1 = vld1_u8(permute_table + lut_rem.idx + 8); + a = vld1_u8(buf); + b = vld1_u8(buf + 8); + ret0 = vtbl1_u8(a, perm_vec0); + uint8x8x2_t ab = {{a, b}}; + ret1 = vtbl2_u8(ab, perm_vec1); + return vcombine_u8(ret0, ret1); +#endif +} + #include "chunkset_tpl.h" #endif diff --git a/arch/x86/chunk_permute_table.h b/arch/generic/chunk_permute_table.h similarity index 100% rename from arch/x86/chunk_permute_table.h rename to arch/generic/chunk_permute_table.h diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index bf49c712d0..024b37c304 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -5,7 +5,7 @@ #ifdef X86_AVX_CHUNKSET #include -#include "chunk_permute_table.h" +#include "../generic/chunk_permute_table.h" typedef __m256i chunk_t; diff --git a/arch/x86/chunkset_sse41.c b/arch/x86/chunkset_sse41.c index 9789df76a7..42b44d0512 100644 --- a/arch/x86/chunkset_sse41.c +++ b/arch/x86/chunkset_sse41.c @@ -9,7 +9,7 @@ * to identical machine code */ #if defined(X86_SSE41) && defined(X86_SSE2) #include -#include "chunk_permute_table.h" +#include "../generic/chunk_permute_table.h" typedef __m128i chunk_t; From bdcae54e5ab3803e1129bb65b3cfacc1a735e8a4 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 28 Jun 2022 10:51:39 +0200 Subject: [PATCH 442/798] Bump _POSIX_C_SOURCE to 200809 for strdup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Google Test uses strdup(), which makes building tests fail on a fresh MSYS2 setup: In file included from zlib-ng/_deps/googletest-src/googletest/include/gtest/internal/gtest-internal.h:40, from zlib-ng/_deps/googletest-src/googletest/include/gtest/gtest.h:62, from zlib-ng/test/test_compress.cc:17: zlib-ng/_deps/googletest-src/googletest/include/gtest/internal/gtest-port.h: In function ‘char* testing::internal::posix::StrDup(const char*)’: zlib-ng/_deps/googletest-src/googletest/include/gtest/internal/gtest-port.h:2046:47: error: ‘strdup’ was not declared in this scope; did you mean ‘StrDup’? 2046 | inline char* StrDup(const char* src) { return strdup(src); } | ^~~~~~ | StrDup Bump _POSIX_C_SOURCE to enable this function. An alternative solution would be to define _POSIX_C_SOURCE in test/CMakeLists.txt, but having a bigger value for zlib-ng itself should not hurt. Include zbuild.h earlier in minideflate.c in order to make the new setting take effect for this file. --- test/minideflate.c | 3 ++- zbuild.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index 148a277692..987e6121ba 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -3,10 +3,11 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ +#include "zbuild.h" + #include #include -#include "zbuild.h" #include "zutil.h" #if defined(_WIN32) || defined(__CYGWIN__) diff --git a/zbuild.h b/zbuild.h index 82374b1f14..d82c1c388e 100644 --- a/zbuild.h +++ b/zbuild.h @@ -3,7 +3,7 @@ #define _POSIX_SOURCE 1 /* fileno */ #ifndef _POSIX_C_SOURCE -# define _POSIX_C_SOURCE 200112L /* snprintf, posix_memalign */ +# define _POSIX_C_SOURCE 200809L /* snprintf, posix_memalign, strdup */ #endif #include From 1fac5a348402c2bd7fc273dda7613a94c1e469eb Mon Sep 17 00:00:00 2001 From: Lucinda May Phipps Date: Fri, 13 May 2022 08:48:17 +0100 Subject: [PATCH 443/798] crc32_acle.c: make logic more consistent --- arch/arm/crc32_acle.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index 68cdafa314..db730e2460 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -22,7 +22,7 @@ uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { len--; } - if ((len > sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) { + if ((len >= sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) { buf2 = (const uint16_t *) buf; c = __crc32h(c, *buf2++); len -= sizeof(uint16_t); @@ -32,7 +32,7 @@ uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { } #if defined(__aarch64__) - if ((len > sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { + if ((len >= sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { c = __crc32w(c, *buf4++); len -= sizeof(uint32_t); } From 4d9e40aa94f81a78ec70abac1f17e00b817821a1 Mon Sep 17 00:00:00 2001 From: Lucinda May Phipps Date: Tue, 7 Jun 2022 14:59:39 +0100 Subject: [PATCH 444/798] remove UNROLL_MORE as suggested --- arch/arm/crc32_acle.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index db730e2460..0133e88fb0 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -39,16 +39,6 @@ uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { const uint64_t *buf8 = (const uint64_t *) buf4; -#ifdef UNROLL_MORE - while (len >= 4 * sizeof(uint64_t)) { - c = __crc32d(c, *buf8++); - c = __crc32d(c, *buf8++); - c = __crc32d(c, *buf8++); - c = __crc32d(c, *buf8++); - len -= 4 * sizeof(uint64_t); - } -#endif - while (len >= sizeof(uint64_t)) { c = __crc32d(c, *buf8++); len -= sizeof(uint64_t); @@ -71,20 +61,6 @@ uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { buf = (const unsigned char *) buf2; #else /* __aarch64__ */ -# ifdef UNROLL_MORE - while (len >= 8 * sizeof(uint32_t)) { - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - c = __crc32w(c, *buf4++); - len -= 8 * sizeof(uint32_t); - } -# endif - while (len >= sizeof(uint32_t)) { c = __crc32w(c, *buf4++); len -= sizeof(uint32_t); From 9c17bd0a5f3af4f52851e24beebfee2f0d5fc907 Mon Sep 17 00:00:00 2001 From: Lucy Phipps Date: Wed, 8 Jun 2022 18:48:19 +0100 Subject: [PATCH 445/798] early return as requested --- arch/arm/crc32_acle.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index 0133e88fb0..ce75c343e5 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -37,6 +37,11 @@ uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { len -= sizeof(uint32_t); } + if (len == 0) { + c = ~c; + return c; + } + const uint64_t *buf8 = (const uint64_t *) buf4; while (len >= sizeof(uint64_t)) { @@ -61,6 +66,11 @@ uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { buf = (const unsigned char *) buf2; #else /* __aarch64__ */ + if (len == 0) { + c = ~c; + return c; + } + while (len >= sizeof(uint32_t)) { c = __crc32w(c, *buf4++); len -= sizeof(uint32_t); From 217420197228489e45dc2677f25f94479dc1df5e Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 27 Jun 2022 20:16:54 +0200 Subject: [PATCH 446/798] Uninstall strawberryperl strawberryperl installs /c/Strawberry/c/bin/libstdc++-6.dll, which is incompatible with the mingw64 one. zlib-ng does not need perl, so simply remove it. --- .github/workflows/cmake.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9667d5f79b..ddafa77f73 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -425,6 +425,9 @@ jobs: - name: Install packages (Windows) if: runner.os == 'Windows' run: | + # strawberryperl installs /c/Strawberry/c/bin/libstdc++-6.dll, which is incompatible with the mingw64 one. + # zlib-ng does not need perl, so simply remove it. + choco uninstall strawberryperl --no-progress choco install ninja ${{ matrix.packages }} --no-progress - name: Install packages (macOS) From a406284705a462939c7a634119884a31b87d6af9 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 29 Jun 2022 09:00:53 -0700 Subject: [PATCH 447/798] Fixed conversion warning with level in compress_bound unit tests. test_compress_bound.cc(43,1): warning C4267: 'argument': conversion from 'size_t' to 'int32_t', possible loss of data --- test/test_compress_bound.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_compress_bound.cc b/test/test_compress_bound.cc index 2757fb2cf2..cd5f6e5b95 100644 --- a/test/test_compress_bound.cc +++ b/test/test_compress_bound.cc @@ -18,9 +18,9 @@ #define MAX_LENGTH (32) -class compress_bound_variant : public testing::TestWithParam { +class compress_bound_variant : public testing::TestWithParam { public: - void estimate(z_size_t level) { + void estimate(int32_t level) { z_size_t estimate_len = 0; uint8_t *uncompressed = NULL; uint8_t dest[128]; From 3390eb0545808c35e6ab53a1127a7fa29db24b21 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 12:44:47 -0700 Subject: [PATCH 448/798] Upgrade to actions/checkout@v3. --- .github/workflows/analyze.yml | 4 ++-- .github/workflows/cmake.yml | 4 ++-- .github/workflows/configure.yml | 2 +- .github/workflows/libpng.yml | 4 ++-- .github/workflows/nmake.yml | 2 +- .github/workflows/pigz.yml | 4 ++-- .github/workflows/pkgcheck.yml | 2 +- .github/workflows/release.yml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index d9d2555b85..4c4f45e8ea 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install packages (Ubuntu) run: | @@ -27,7 +27,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install packages (Ubuntu) run: | diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ddafa77f73..17d5f39800 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -400,10 +400,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Checkout test corpora - uses: actions/checkout@v2 + uses: actions/checkout@v3 # Don't test against all corpora with MinGW due to Wine being unable to run parallel jobs # without connection timeout. Without parallel jobs test runs using Wine take close to an hour. if: contains(matrix.name, 'MinGW') == false diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 25d9b875c6..4091b0c1ca 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -193,7 +193,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index a519460cce..262b7c329b 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -7,7 +7,7 @@ jobs: steps: - name: Checkout repository (zlib-ng) - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Generate project files (zlib-ng) run: | @@ -22,7 +22,7 @@ jobs: cmake --build . --config Release - name: Checkout repository (libpng) - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: glennrp/libpng path: libpng diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index dcc1e736db..bd8567f7a1 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -48,7 +48,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Compile source code shell: cmd diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index e7193ee668..ee369400fb 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -51,10 +51,10 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Checkout test corpora - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: zlib-ng/corpora path: test/data/corpora diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 7b8a5df595..a953ea9229 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -76,7 +76,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install packages (Ubuntu) if: runner.os == 'Linux' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e52d6a6d8c..7f68074cf3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,7 +61,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set environment variables shell: bash From 5c95ff6019e597f67089d6d1f745bf604fb829c6 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 24 Jun 2022 07:38:40 -0700 Subject: [PATCH 449/798] Clean up workflow and job names. Remove CI prefix because it is redundant. --- .github/workflows/analyze.yml | 5 +++-- .github/workflows/cmake.yml | 4 ++-- .github/workflows/configure.yml | 4 ++-- .github/workflows/fuzz.yml | 5 +++-- .github/workflows/libpng.yml | 5 ++--- .github/workflows/link.yml | 2 +- .github/workflows/nmake.yml | 4 ++-- .github/workflows/pigz.yml | 4 ++-- .github/workflows/pkgcheck.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- 10 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 4c4f45e8ea..31d9ff9912 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -1,7 +1,8 @@ -name: CI Static Analysis +name: Static Analysis on: [push, pull_request] jobs: - GCC: + static-analysis: + name: GCC runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 17d5f39800..c97fd0deb2 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,10 +1,10 @@ -name: CI CMake +name: CMake on: [push, pull_request] env: TERM: xterm-256color GTEST_COLOR: 1 jobs: - ci-cmake: + cmake: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 4091b0c1ca..420172efd9 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -1,7 +1,7 @@ -name: CI Configure +name: Configure on: [push, pull_request] jobs: - ci-configure: + configure: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index cd647086ff..9814b9f390 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -1,4 +1,4 @@ -name: CI Fuzz +name: OSS-Fuzz on: pull_request: push: @@ -11,7 +11,8 @@ on: - '*' jobs: - Fuzzing: + fuzzing: + name: Fuzzing runs-on: ubuntu-latest steps: - name: Build Fuzzers diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index 262b7c329b..6af5ed00e4 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -1,10 +1,9 @@ -name: CI Libpng +name: Libpng on: [push, pull_request] jobs: - pngtest: + libpng: name: Ubuntu Clang runs-on: ubuntu-latest - steps: - name: Checkout repository (zlib-ng) uses: actions/checkout@v3 diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml index 892f1afcd0..2b9000cd5c 100644 --- a/.github/workflows/link.yml +++ b/.github/workflows/link.yml @@ -1,4 +1,4 @@ -name: CI Link +name: Link on: [push, pull_request] jobs: zlib: diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index bd8567f7a1..759bcce17e 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -1,7 +1,7 @@ -name: CI NMake +name: NMake on: [push, pull_request] jobs: - ci-cmake: + nmake: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index ee369400fb..82dc7c6769 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -1,7 +1,7 @@ -name: CI Pigz +name: Pigz on: [push, pull_request] jobs: - ci-cmake: + pigz: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index a953ea9229..9511af9952 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -1,7 +1,7 @@ -name: CI Pkgcheck +name: Package Check on: [push, pull_request] jobs: - ci-pkgcheck: + pkgcheck: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f68074cf3..a84051c1cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,10 +1,10 @@ -name: CI Release +name: Release on: push: tags: - '*' jobs: - ci-cmake: + release: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} strategy: From c4047895706e5fc08cba3c5985c4593de6ee69e5 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 13:17:02 -0700 Subject: [PATCH 450/798] Collapse workflow multiline run actions into single line. --- .github/workflows/analyze.yml | 9 +++------ .github/workflows/cmake.yml | 13 +++++-------- .github/workflows/libpng.yml | 3 +-- .github/workflows/pkgcheck.yml | 15 +++++---------- .github/workflows/release.yml | 3 +-- 5 files changed, 15 insertions(+), 28 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 31d9ff9912..b52c8490df 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -9,8 +9,7 @@ jobs: uses: actions/checkout@v3 - name: Install packages (Ubuntu) - run: | - sudo apt-get install -y gcc-10 + run: sudo apt-get install -y gcc-10 - name: Generate project files run: | @@ -21,8 +20,7 @@ jobs: CI: true - name: Compile source code - run: | - cmake --build . --config Release > /dev/null + run: cmake --build . --config Release > /dev/null Clang: runs-on: ubuntu-latest @@ -31,8 +29,7 @@ jobs: uses: actions/checkout@v3 - name: Install packages (Ubuntu) - run: | - sudo apt-get install clang-tools -y + run: sudo apt-get install clang-tools -y - name: Generate project files run: | diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index c97fd0deb2..dcdfee240b 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -413,8 +413,7 @@ jobs: - name: Add repositories (Wine) if: contains(matrix.packages, 'wine') - run: | - sudo dpkg --add-architecture i386 + run: sudo dpkg --add-architecture i386 - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages @@ -427,21 +426,19 @@ jobs: run: | # strawberryperl installs /c/Strawberry/c/bin/libstdc++-6.dll, which is incompatible with the mingw64 one. # zlib-ng does not need perl, so simply remove it. - choco uninstall strawberryperl --no-progress - choco install ninja ${{ matrix.packages }} --no-progress + choco uninstall --no-progress strawberryperl + choco install --no-progress ninja ${{ matrix.packages }} - name: Install packages (macOS) if: runner.os == 'macOS' - run: | - brew install ninja ${{ matrix.packages }} + run: brew install ninja ${{ matrix.packages }} env: HOMEBREW_NO_INSTALL_CLEANUP: 1 - name: Initialize Wine # Prevent parallel test jobs from initializing Wine at the same time if: contains(matrix.packages, 'wine') - run: | - wineboot --init + run: wineboot --init - name: Compile LLVM C++ libraries (MSAN) if: contains(matrix.name, 'MSAN') diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index 6af5ed00e4..f25f16865d 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -17,8 +17,7 @@ jobs: CI: true - name: Compile source code (zlib-ng) - run: | - cmake --build . --config Release + run: cmake --build . --config Release - name: Checkout repository (libpng) uses: actions/checkout@v3 diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 9511af9952..105f50a663 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -86,8 +86,7 @@ jobs: - name: Install packages (macOS) if: runner.os == 'macOS' - run: | - brew install ninja diffoscope ${{ matrix.packages }} + run: brew install ninja diffoscope ${{ matrix.packages }} env: HOMEBREW_NO_INSTALL_CLEANUP: 1 @@ -101,8 +100,7 @@ jobs: xcode-version: '11.7.0' - name: Compare builds - run: | - sh test/pkgcheck.sh + run: sh test/pkgcheck.sh env: CC: ${{ matrix.compiler }} CXX: ${{ matrix.cxx-compiler }} @@ -114,8 +112,7 @@ jobs: LDFLAGS: ${{ matrix.ldflags }} - name: Compare builds (compat) - run: | - sh test/pkgcheck.sh --zlib-compat + run: sh test/pkgcheck.sh --zlib-compat env: CC: ${{ matrix.compiler }} CFLAGS: ${{ matrix.cflags }} @@ -127,8 +124,7 @@ jobs: - name: Check ABI # macOS runner does not contain abigail if: runner.os != 'macOS' - run: | - sh test/abicheck.sh --refresh-if + run: sh test/abicheck.sh --refresh-if env: CC: ${{ matrix.compiler }} CXX: ${{ matrix.cxx-compiler }} @@ -142,8 +138,7 @@ jobs: - name: Check ABI (compat) # macOS runner does not contain abigail if: runner.os != 'macOS' - run: | - sh test/abicheck.sh --zlib-compat --refresh-if + run: sh test/abicheck.sh --zlib-compat --refresh-if env: CC: ${{ matrix.compiler }} CXX: ${{ matrix.cxx-compiler }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a84051c1cf..63649fda4b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -75,8 +75,7 @@ jobs: CI: true - name: Compile source code - run: | - cmake --build . --config Release --target install + run: cmake --build . --config Release --target install - name: Package release (Windows) if: runner.os == 'Windows' From 1a0b3bf09bfa66f94fcc49c8f4f90ad9cff2fd21 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 13:19:53 -0700 Subject: [PATCH 451/798] Use working-directory property for run actions instead of changing directory. --- .github/workflows/cmake.yml | 9 +++------ .github/workflows/configure.yml | 10 ++++------ .github/workflows/libpng.yml | 15 ++++++--------- .github/workflows/pigz.yml | 15 ++++++--------- .github/workflows/release.yml | 5 ++--- 5 files changed, 21 insertions(+), 33 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index dcdfee240b..b10a5911e3 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -468,16 +468,13 @@ jobs: CI: true - name: Compile source code - run: | - cd ${{ matrix.build-dir || '.' }} - cmake --build . --config ${{ matrix.build-config || 'Release' }} + run: cmake --build ${{ matrix.build-dir || '.' }} --config ${{ matrix.build-config || 'Release' }} - name: Run test cases # Don't run tests on Windows ARM if: runner.os != 'Windows' || contains(matrix.name, 'ARM') == false - run: | - cd ${{ matrix.build-dir || '.' }} - ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '6' }} + run: ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '6' }} + working-directory: ${{ matrix.build-dir || '.' }} env: ASAN_OPTIONS: ${{ matrix.asan-options || 'verbosity=0' }}:abort_on_error=1:halt_on_error=1 MSAN_OPTIONS: ${{ matrix.msan-options || 'verbosity=0' }}:abort_on_error=1:halt_on_error=1 diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 420172efd9..2071618fd6 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -214,14 +214,12 @@ jobs: CI: true - name: Compile source code - run: | - cd ${{ matrix.build-dir || '.' }} - make -j2 + run: make -j2 + working-directory: ${{ matrix.build-dir }} - name: Run test cases - run: | - cd ${{ matrix.build-dir || '.' }} - make test + run: make test + working-directory: ${{ matrix.build-dir }} env: QEMU_RUN: ${{ matrix.qemu-run }} ASAN_OPTIONS: abort_on_error=1:halt_on_error=1 diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index f25f16865d..13326b3953 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -26,19 +26,16 @@ jobs: path: libpng - name: Generate project files (libpng) - run: | - cd libpng - cmake . -DCMAKE_BUILD_TYPE=Release -DPNG_TESTS=ON -DPNG_STATIC=OFF -DZLIB_INCLUDE_DIR=.. -DZLIB_LIBRARY=$PWD/../libz.a + run: cmake . -DCMAKE_BUILD_TYPE=Release -DPNG_TESTS=ON -DPNG_STATIC=OFF -DZLIB_INCLUDE_DIR=.. -DZLIB_LIBRARY=$PWD/../libz.a + working-directory: libpng env: CC: clang CI: true - name: Compile source code (libpng) - run: | - cd libpng - cmake --build . --config Release + run: cmake --build . --config Release + working-directory: libpng - name: Run test cases (libpng) - run: | - cd libpng - ctest -C Release --output-on-failure --max-width 120 + run: ctest -C Release --output-on-failure --max-width 120 + working-directory: libpng diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 82dc7c6769..afec6e3eed 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -66,9 +66,8 @@ jobs: sudo apt-get install -y ${{ matrix.packages }} - name: Generate project files - run: | - cd test/pigz - cmake ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DZLIB_ROOT=../.. -DWITH_CODE_COVERAGE=ON -DWITH_MAINTAINER_WARNINGS=ON + run: cmake ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DZLIB_ROOT=../.. -DWITH_CODE_COVERAGE=ON -DWITH_MAINTAINER_WARNINGS=ON + working-directory: test/pigz env: CC: ${{ matrix.compiler }} CFLAGS: ${{ matrix.cflags }} @@ -76,14 +75,12 @@ jobs: CI: true - name: Compile source code - run: | - cd test/pigz - cmake --build . --config ${{ matrix.build-config || 'Release' }} + run: cmake --build . --config ${{ matrix.build-config || 'Release' }} + working-directory: test/pigz - name: Run test cases - run: | - cd test/pigz - ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '2' }} + run: ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '2' }} + working-directory: test/pigz - name: Generate coverage report if: matrix.codecov diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 63649fda4b..163caa08e2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,9 +79,8 @@ jobs: - name: Package release (Windows) if: runner.os == 'Windows' - run: | - cd out - 7z a -tzip ../zlib-ng-${{ matrix.deploy-name }}.zip bin include lib ../LICENSE.md ../PORTING.md ../README.md + run: 7z a -tzip ../zlib-ng-${{ matrix.deploy-name }}.zip bin include lib ../LICENSE.md ../PORTING.md ../README.md + working-directory: out - name: Upload release (Windows) uses: svenstaro/upload-release-action@v1-release From 040e55d3221808b4d8d2e3357e296ae8d6aa02c8 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 13:19:11 -0700 Subject: [PATCH 452/798] Remove unused sanitizer options in configure workflow. --- .github/workflows/configure.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 2071618fd6..975af222b2 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -222,9 +222,6 @@ jobs: working-directory: ${{ matrix.build-dir }} env: QEMU_RUN: ${{ matrix.qemu-run }} - ASAN_OPTIONS: abort_on_error=1:halt_on_error=1 - MSAN_OPTIONS: abort_on_error=1:halt_on_error=1 - UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1:halt_on_error=1 - name: Upload build errors uses: actions/upload-artifact@v2 From 9545d711f4f459cb1a0b21434811f19c73d48f7b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 13:19:29 -0700 Subject: [PATCH 453/798] Added whitespace separation between steps in fuzzer workflow. --- .github/workflows/fuzz.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 9814b9f390..b108461033 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -20,12 +20,14 @@ jobs: with: oss-fuzz-project-name: 'zlib-ng' dry-run: false + - name: Run Fuzzers uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master with: oss-fuzz-project-name: 'zlib-ng' fuzz-seconds: 600 dry-run: false + - name: Upload Crash uses: actions/upload-artifact@v1 if: failure() From 6c895ebffc27be1da13953bd49dbb690bce8ee2b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 24 Jun 2022 11:22:41 -0700 Subject: [PATCH 454/798] Split long workflow commands into separate lines for easier readability. --- .github/workflows/analyze.yml | 39 +++++++++++++++++++++++++++++----- .github/workflows/cmake.yml | 29 ++++++++++++++++--------- .github/workflows/libpng.yml | 14 ++++++++++-- .github/workflows/pigz.yml | 14 ++++++++++-- .github/workflows/pkgcheck.yml | 5 ++++- .github/workflows/release.yml | 7 +++++- 6 files changed, 87 insertions(+), 21 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index b52c8490df..3a38edd93f 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -13,10 +13,32 @@ jobs: - name: Generate project files run: | - cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=OFF -DWITH_CODE_COVERAGE=OFF -DWITH_MAINTAINER_WARNINGS=OFF + cmake . \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=OFF \ + -DWITH_FUZZERS=OFF \ + -DWITH_CODE_COVERAGE=OFF \ + -DWITH_MAINTAINER_WARNINGS=OFF env: CC: gcc-10 - CFLAGS: "-fanalyzer -Werror -Wanalyzer-double-fclose -Wanalyzer-double-free -Wanalyzer-exposure-through-output-file -Wanalyzer-file-leak -Wanalyzer-free-of-non-heap -Wanalyzer-malloc-leak -Wanalyzer-null-argument -Wanalyzer-null-dereference -Wanalyzer-possible-null-argument -Wanalyzer-possible-null-dereference -Wanalyzer-stale-setjmp-buffer -Wanalyzer-tainted-array-index -Wanalyzer-unsafe-call-within-signal-handler -Wanalyzer-use-after-free -Wanalyzer-use-of-pointer-in-stale-stack-frame" + CFLAGS: + -fanalyzer + -Werror + -Wanalyzer-double-fclose + -Wanalyzer-double-free + -Wanalyzer-exposure-through-output-file + -Wanalyzer-file-leak + -Wanalyzer-free-of-non-heap + -Wanalyzer-malloc-leak + -Wanalyzer-null-argument + -Wanalyzer-null-dereference + -Wanalyzer-possible-null-argument + -Wanalyzer-possible-null-dereference + -Wanalyzer-stale-setjmp-buffer + -Wanalyzer-tainted-array-index + -Wanalyzer-unsafe-call-within-signal-handler + -Wanalyzer-use-after-free + -Wanalyzer-use-of-pointer-in-stale-stack-frame CI: true - name: Compile source code @@ -29,14 +51,21 @@ jobs: uses: actions/checkout@v3 - name: Install packages (Ubuntu) - run: sudo apt-get install clang-tools -y + run: sudo apt-get install -y clang-tools - name: Generate project files run: | - scan-build --status-bugs cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=OFF -DWITH_CODE_COVERAGE=OFF -DWITH_MAINTAINER_WARNINGS=OFF + scan-build --status-bugs \ + cmake . \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=OFF \ + -DWITH_FUZZERS=OFF \ + -DWITH_CODE_COVERAGE=OFF \ + -DWITH_MAINTAINER_WARNINGS=OFF env: CI: true - name: Compile source code run: | - scan-build --status-bugs cmake --build . --config Release > /dev/null + scan-build --status-bugs \ + cmake --build . --config Release > /dev/null diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index b10a5911e3..7b537f06c6 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -444,22 +444,27 @@ jobs: if: contains(matrix.name, 'MSAN') run: | git clone --depth=1 https://github.com/llvm/llvm-project --single-branch --branch llvmorg-11.0.0 - cd llvm-project - mkdir build - cd build - cmake -G Ninja ../llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" -DLLVM_USE_SANITIZER=MemoryWithOrigins -DLLVM_LIBC_ENABLE_LINTING=OFF - cmake --build . -- cxx cxxabi - echo "LLVM_BUILD_DIR=`pwd`" >> $GITHUB_ENV + cmake -S llvm-project/llvm -B llvm-project/build -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" \ + -DLLVM_USE_SANITIZER=MemoryWithOrigins \ + -DLLVM_LIBC_ENABLE_LINTING=OFF + cmake --build llvm-project/build -- cxx cxxabi + echo "LLVM_BUILD_DIR=`pwd`/llvm-project/build" >> $GITHUB_ENV env: CC: ${{ matrix.compiler }} CXX: ${{ matrix.cxx-compiler }} - name: Generate project files + shell: bash # Shared libraries turned off for qemu ppc* and sparc & reduce code coverage sources run: | - mkdir ${{ matrix.build-dir || '.not-used' }} - cd ${{ matrix.build-dir || '.' }} - cmake ${{ matrix.build-src-dir || '.' }} ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=ON ${{ matrix.codecov && '-DWITH_CODE_COVERAGE=ON' }} -DWITH_MAINTAINER_WARNINGS=ON + cmake -S ${{ matrix.build-src-dir || '.' }} -B ${{ matrix.build-dir || '.' }} ${{ matrix.cmake-args }} \ + -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} \ + -DBUILD_SHARED_LIBS=OFF \ + -DWITH_FUZZERS=ON \ + -DWITH_MAINTAINER_WARNINGS=ON \ + ${{ matrix.codecov && '-DWITH_CODE_COVERAGE=ON' }} env: CC: ${{ matrix.compiler }} CXX: ${{ matrix.cxx-compiler }} @@ -487,7 +492,11 @@ jobs: shell: bash run: | python3 -u -m pip install --user gcovr==5.0 - python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root ${{ matrix.build-src-dir || '.' }} --xml --output coverage.xml -j 3 --verbose + python3 -m gcovr -j 3 --verbose \ + --exclude-unreachable-branches \ + --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" \ + --root ${{ matrix.build-src-dir || '.' }} \ + --xml --output coverage.xml - name: Upload coverage report uses: codecov/codecov-action@v2 diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index 13326b3953..9118a96c81 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -10,7 +10,11 @@ jobs: - name: Generate project files (zlib-ng) run: | - cmake . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_COMPAT=ON -DZLIB_ENABLE_TESTS=OFF + cmake . \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_SHARED_LIBS=OFF \ + -DZLIB_COMPAT=ON \ + -DZLIB_ENABLE_TESTS=OFF env: CC: clang CFLAGS: -fPIC @@ -26,7 +30,13 @@ jobs: path: libpng - name: Generate project files (libpng) - run: cmake . -DCMAKE_BUILD_TYPE=Release -DPNG_TESTS=ON -DPNG_STATIC=OFF -DZLIB_INCLUDE_DIR=.. -DZLIB_LIBRARY=$PWD/../libz.a + run: | + cmake . \ + -DCMAKE_BUILD_TYPE=Release \ + -DPNG_TESTS=ON \ + -DPNG_STATIC=OFF \ + -DZLIB_INCLUDE_DIR=.. \ + -DZLIB_LIBRARY=$PWD/../libz.a working-directory: libpng env: CC: clang diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index afec6e3eed..fc604200b4 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -66,7 +66,13 @@ jobs: sudo apt-get install -y ${{ matrix.packages }} - name: Generate project files - run: cmake ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DZLIB_ROOT=../.. -DWITH_CODE_COVERAGE=ON -DWITH_MAINTAINER_WARNINGS=ON + run: | + cmake ${{ matrix.cmake-args }} \ + -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} \ + -DBUILD_SHARED_LIBS=OFF \ + -DZLIB_ROOT=../.. \ + -DWITH_CODE_COVERAGE=ON \ + -DWITH_MAINTAINER_WARNINGS=ON working-directory: test/pigz env: CC: ${{ matrix.compiler }} @@ -86,7 +92,11 @@ jobs: if: matrix.codecov run: | python3 -u -m pip install --user gcovr==5.0 - python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root . --xml --output coverage.xml -j 3 --verbose + python3 -m gcovr -j 3 --verbose \ + --exclude-unreachable-branches \ + --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" \ + --root . \ + --xml --output coverage.xml - name: Upload coverage report uses: codecov/codecov-action@v2 diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 105f50a663..3b8c712c22 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -82,7 +82,10 @@ jobs: if: runner.os == 'Linux' run: | sudo apt-get update - sudo apt-get install -y --no-install-recommends abigail-tools ninja-build diffoscope ${{ matrix.packages }} + sudo apt-get install -y --no-install-recommends ${{ matrix.packages }} \ + abigail-tools \ + diffoscope \ + ninja-build - name: Install packages (macOS) if: runner.os == 'macOS' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 163caa08e2..2a3327b479 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -68,8 +68,13 @@ jobs: run: echo "tag=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV - name: Generate project files + shell: bash run: | - cmake . ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=Release -DZLIB_ENABLE_TESTS=ON -DCMAKE_INSTALL_PREFIX=out -DINSTALL_UTILS=ON + cmake . ${{ matrix.cmake-args }} \ + -DCMAKE_BUILD_TYPE=Release \ + -DZLIB_ENABLE_TESTS=ON \ + -DCMAKE_INSTALL_PREFIX=out \ + -DINSTALL_UTILS=ON env: CC: ${{ matrix.compiler }} CI: true From 0ef83443ca0fe082b2c60d66747441694b4b2120 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 13:33:56 -0700 Subject: [PATCH 455/798] Use msvc-dev-cmd to set the development environment. --- .github/workflows/nmake.yml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index 759bcce17e..f8c61af009 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -11,56 +11,58 @@ jobs: - name: Windows NMake x86 os: windows-2022 makefile: win32/Makefile.msc - vc-vars: x86 + arch: x86 - name: Windows NMake x64 compat os: windows-2022 makefile: win32/Makefile.msc - vc-vars: x86_amd64 + arch: x86_amd64 additional-args: ZLIB_COMPAT=yes - name: Windows NMake x64 Symbol Prefix os: windows-2022 makefile: win32/Makefile.msc - vc-vars: x86_amd64 + arch: x86_amd64 additional-args: SYMBOL_PREFIX=zTest_ - name: Windows NMake x64 Symbol Prefix Compat os: windows-2022 makefile: win32/Makefile.msc - vc-vars: x86_amd64 + arch: x86_amd64 additional-args: ZLIB_COMPAT=yes SYMBOL_PREFIX=zTest_ - name: Windows NMake x64 os: windows-2022 makefile: win32/Makefile.msc - vc-vars: x86_amd64 + arch: x86_amd64 - name: Windows NMake ARM No Test os: windows-2022 makefile: win32/Makefile.arm - vc-vars: x86_arm + arch: x86_arm - name: Windows NMake ARM64 No Test os: windows-2022 makefile: win32/Makefile.a64 - vc-vars: x86_arm64 + arch: x86_arm64 steps: - name: Checkout repository uses: actions/checkout@v3 + - name: Setup development environment + uses: ilammy/msvc-dev-cmd@v1.10.0 + with: + arch: ${{ matrix.arch }} + - name: Compile source code shell: cmd - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} - nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} + run: nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} - name: Run test cases shell: cmd # Don't run tests on Windows ARM - if: contains(matrix.vc-vars, 'arm') == false + if: contains(matrix.arch, 'arm') == false run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} test nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} testdll From 9a14b932d6ba2923feaa6d1aa3317330c31aef38 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 19 Jun 2022 14:42:57 -0700 Subject: [PATCH 456/798] Set max time for job to complete to 60 minutes. --- .github/workflows/cmake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 7b537f06c6..d9af5d4a95 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -7,6 +7,7 @@ jobs: cmake: name: ${{ matrix.name }} runs-on: ${{ matrix.os }} + timeout-minutes: 60 strategy: fail-fast: false matrix: From 91976e465fc6e4b775051a122aa6c018a3061019 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 30 Jun 2022 11:23:37 -0700 Subject: [PATCH 457/798] Use 15 (0xf) for ZLIB_VER_SUBREVISION to indicate zlib fork. --- zlib.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zlib.h.in b/zlib.h.in index 09ea336ff3..96f76b2f9a 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -62,7 +62,7 @@ extern "C" { #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 #define ZLIB_VER_REVISION 12 -#define ZLIB_VER_SUBREVISION 0 +#define ZLIB_VER_SUBREVISION 15 /* 15=fork (0xf) */ /* The 'zlib' compression library provides in-memory compression and From 1532af4d85734563d5cd3b276df808fd67b88489 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 30 Jun 2022 11:23:23 -0700 Subject: [PATCH 458/798] Don't use zlib fork identifier in copyright statement. --- deflate.c | 2 +- inftrees.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deflate.c b/deflate.c index 2970aa4e08..e17f791717 100644 --- a/deflate.c +++ b/deflate.c @@ -59,7 +59,7 @@ # undef deflateInit2 #endif -const char PREFIX(deflate_copyright)[] = " deflate 1.2.12.f Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; +const char PREFIX(deflate_copyright)[] = " deflate 1.2.12 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot diff --git a/inftrees.c b/inftrees.c index 369fd09dfe..7a215bd657 100644 --- a/inftrees.c +++ b/inftrees.c @@ -9,7 +9,7 @@ #define MAXBITS 15 -const char PREFIX(inflate_copyright)[] = " inflate 1.2.12.f Copyright 1995-2022 Mark Adler "; +const char PREFIX(inflate_copyright)[] = " inflate 1.2.12 Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot From 370d08fc1f8421322e6aadcc29ce81efe3854d3d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 2 Jul 2022 13:59:19 -0700 Subject: [PATCH 459/798] Fixed functions declared without a prototype warning in tools. tools/maketrees.c:101:29: warning: a function declaration without a prototype is deprecated in all versions of C [-Wstrict-prototypes] static void gen_trees_header() tools/makecrct.c:65:27: warning: a function declaration without a prototype is deprecated in all versions of C [-Wstrict-prototypes] static void make_crc_table() --- tools/makecrct.c | 2 +- tools/maketrees.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/makecrct.c b/tools/makecrct.c index 8ed0cf5cfd..b5469b7d39 100644 --- a/tools/makecrct.c +++ b/tools/makecrct.c @@ -62,7 +62,7 @@ static void write_table64(const z_word_t *table, int k); information needed to generate CRCs on data a byte at a time for all combinations of CRC register values and incoming bytes. */ -static void make_crc_table() { +static void make_crc_table(void) { unsigned i, j, n; uint32_t p; diff --git a/tools/maketrees.c b/tools/maketrees.c index 97688c7aae..2c32ccae08 100644 --- a/tools/maketrees.c +++ b/tools/maketrees.c @@ -98,7 +98,7 @@ static void tr_static_init(void) { ((i) == (last)? "\n};\n\n" : \ ((i) % (width) == (width)-1 ? ",\n" : ", ")) -static void gen_trees_header() { +static void gen_trees_header(void) { int i; printf("#ifndef TREES_TBL_H_\n"); From b18c815056e9b20175d44732bd7416f1fe6a931e Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sat, 9 Jul 2022 12:33:02 +0300 Subject: [PATCH 460/798] Treat arm64 as aarch64 for Apple M1. --- cmake/detect-arch.c | 2 +- configure | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/detect-arch.c b/cmake/detect-arch.c index 84e6a84100..43ddb126ae 100644 --- a/cmake/detect-arch.c +++ b/cmake/detect-arch.c @@ -12,7 +12,7 @@ #error archfound i686 // ARM -#elif defined(__aarch64__) || defined(_M_ARM64) +#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) #error archfound aarch64 #elif defined(__arm__) || defined(__arm) || defined(_M_ARM) || defined(__TARGET_ARCH_ARM) #if defined(__ARM64_ARCH_8__) || defined(__ARMv8__) || defined(__ARMv8_A__) diff --git a/configure b/configure index ffee400548..f28f1dba2f 100755 --- a/configure +++ b/configure @@ -359,7 +359,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then else ARCH=native fi ;; - aarch64 | aarch64_be) + aarch64 | aarch64_be | arm64) if test "${uname}" = "elf"; then uname=aarch64 fi @@ -1125,7 +1125,7 @@ EOF check_neon_ld4_intrinsics() { if test $buildneon -eq 1 && test $native -eq 0; then - if test "$CC_ARCH" = "aarch64" || test "$CC_ARCH" = "aarch64_be"; then + if test "$CC_ARCH" = "aarch64" || test "$CC_ARCH" = "aarch64_be" || test "$CC_ARCH" = "arm64"; then neonflag="-march=armv8-a+simd" elif test $MFPU_NEON_AVAILABLE -eq 1; then neonflag="-mfpu=neon" From e22195e5bcb10851f96e0b56e396696b152e81af Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 29 Jun 2022 08:57:11 -0700 Subject: [PATCH 461/798] Don't use unaligned access for memcpy instructions due to GCC 11 assuming it is aligned in certain instances. --- arch/arm/chunkset_neon.c | 8 ++++---- arch/power/chunkset_power8.c | 6 +++--- arch/x86/chunkset_avx.c | 6 +++--- arch/x86/chunkset_sse2.c | 6 +++--- arch/x86/chunkset_sse41.c | 8 ++++---- chunkset.c | 10 +++++----- compare256.c | 8 ++++---- deflate.h | 10 +++++----- inffast.c | 2 +- inflate_p.h | 6 +++--- insert_string_tpl.h | 2 +- match_tpl.h | 12 ++++++------ zbuild.h | 15 +++------------ 13 files changed, 45 insertions(+), 54 deletions(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 29065f77c4..3b8d2c0010 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -38,19 +38,19 @@ static const lut_rem_pair perm_idx_lut[13] = { static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { uint16_t tmp; - zmemcpy_2(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = vreinterpretq_u8_u16(vdupq_n_u16(tmp)); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { uint32_t tmp; - zmemcpy_4(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = vreinterpretq_u8_u32(vdupq_n_u32(tmp)); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { uint64_t tmp; - zmemcpy_8(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = vreinterpretq_u8_u64(vdupq_n_u64(tmp)); } @@ -76,7 +76,7 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t /* See note in chunkset_sse41.c for why this is ok */ __msan_unpoison(buf + dist, 16 - dist); #endif - + /* This version of table is only available on aarch64 */ #if defined(_M_ARM64) || defined(__aarch64__) uint8x16_t ret_vec = vld1q_u8(buf); diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index 47e5485262..83928308d6 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -16,19 +16,19 @@ typedef vector unsigned char chunk_t; static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { uint16_t tmp; - zmemcpy_2(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = (vector unsigned char)vec_splats(tmp); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { uint32_t tmp; - zmemcpy_4(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = (vector unsigned char)vec_splats(tmp); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { uint64_t tmp; - zmemcpy_8(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = (vector unsigned char)vec_splats(tmp); } diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index 024b37c304..c4a4d9b052 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -52,19 +52,19 @@ static const lut_rem_pair perm_idx_lut[29] = { static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { int16_t tmp; - zmemcpy_2(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm256_set1_epi16(tmp); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { int32_t tmp; - zmemcpy_4(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm256_set1_epi32(tmp); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { int64_t tmp; - zmemcpy_8(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm256_set1_epi64x(tmp); } diff --git a/arch/x86/chunkset_sse2.c b/arch/x86/chunkset_sse2.c index 8e3166f70e..eddf5d9895 100644 --- a/arch/x86/chunkset_sse2.c +++ b/arch/x86/chunkset_sse2.c @@ -17,19 +17,19 @@ typedef __m128i chunk_t; static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { int16_t tmp; - zmemcpy_2(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm_set1_epi16(tmp); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { int32_t tmp; - zmemcpy_4(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm_set1_epi32(tmp); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { int64_t tmp; - zmemcpy_8(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm_set1_epi64x(tmp); } diff --git a/arch/x86/chunkset_sse41.c b/arch/x86/chunkset_sse41.c index 42b44d0512..c148db0924 100644 --- a/arch/x86/chunkset_sse41.c +++ b/arch/x86/chunkset_sse41.c @@ -41,19 +41,19 @@ static const lut_rem_pair perm_idx_lut[13] = { static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { int16_t tmp; - zmemcpy_2(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm_set1_epi16(tmp); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { int32_t tmp; - zmemcpy_4(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm_set1_epi32(tmp); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { int64_t tmp; - zmemcpy_8(&tmp, from); + memcpy(&tmp, from, sizeof(tmp)); *chunk = _mm_set1_epi64x(tmp); } @@ -69,7 +69,7 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; __m128i perm_vec, ret_vec; #ifdef Z_MEMORY_SANITIZER - /* Important to note: + /* Important to note: * This is _not_ to subvert the memory sanitizer but to instead unpoison some * bytes we willingly and purposefully load uninitialized that we swizzle over * in a vector register, anyway. If what we assume is wrong about what is used, diff --git a/chunkset.c b/chunkset.c index ca35929f3a..169e411233 100644 --- a/chunkset.c +++ b/chunkset.c @@ -13,20 +13,20 @@ typedef uint64_t chunk_t; static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { uint8_t *dest = (uint8_t *)chunk; - zmemcpy_4(dest, from); - zmemcpy_4(dest+4, from); + memcpy(dest, from, sizeof(uint32_t)); + memcpy(dest+4, from, sizeof(uint32_t)); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { - zmemcpy_8(chunk, from); + memcpy(chunk, from, sizeof(uint64_t)); } static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { - zmemcpy_8(chunk, (uint8_t *)s); + memcpy(chunk, (uint8_t *)s, sizeof(uint64_t)); } static inline void storechunk(uint8_t *out, chunk_t *chunk) { - zmemcpy_8(out, chunk); + memcpy(out, chunk, sizeof(uint64_t)); } #define CHUNKSIZE chunksize_c diff --git a/compare256.c b/compare256.c index 3c05969f9f..b11ac24ee0 100644 --- a/compare256.c +++ b/compare256.c @@ -101,8 +101,8 @@ static inline uint32_t compare256_unaligned_32_static(const uint8_t *src0, const do { uint32_t sv, mv, diff; - zmemcpy_4(&sv, src0); - zmemcpy_4(&mv, src1); + memcpy(&sv, src0, sizeof(sv)); + memcpy(&mv, src1, sizeof(mv)); diff = sv ^ mv; if (diff) { @@ -141,8 +141,8 @@ static inline uint32_t compare256_unaligned_64_static(const uint8_t *src0, const do { uint64_t sv, mv, diff; - zmemcpy_8(&sv, src0); - zmemcpy_8(&mv, src1); + memcpy(&sv, src0, sizeof(sv)); + memcpy(&mv, src1, sizeof(mv)); diff = sv ^ mv; if (diff) { diff --git a/deflate.h b/deflate.h index f8920df59c..ccb246a818 100644 --- a/deflate.h +++ b/deflate.h @@ -306,7 +306,7 @@ static inline void put_short(deflate_state *s, uint16_t w) { #if BYTE_ORDER == BIG_ENDIAN w = ZSWAP16(w); #endif - zmemcpy_2(&s->pending_buf[s->pending], &w); + memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); s->pending += 2; } @@ -318,7 +318,7 @@ static inline void put_short_msb(deflate_state *s, uint16_t w) { #if BYTE_ORDER == LITTLE_ENDIAN w = ZSWAP16(w); #endif - zmemcpy_2(&s->pending_buf[s->pending], &w); + memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); s->pending += 2; } @@ -330,7 +330,7 @@ static inline void put_uint32(deflate_state *s, uint32_t dw) { #if BYTE_ORDER == BIG_ENDIAN dw = ZSWAP32(dw); #endif - zmemcpy_4(&s->pending_buf[s->pending], &dw); + memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); s->pending += 4; } @@ -342,7 +342,7 @@ static inline void put_uint32_msb(deflate_state *s, uint32_t dw) { #if BYTE_ORDER == LITTLE_ENDIAN dw = ZSWAP32(dw); #endif - zmemcpy_4(&s->pending_buf[s->pending], &dw); + memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); s->pending += 4; } @@ -354,7 +354,7 @@ static inline void put_uint64(deflate_state *s, uint64_t lld) { #if BYTE_ORDER == BIG_ENDIAN lld = ZSWAP64(lld); #endif - zmemcpy_8(&s->pending_buf[s->pending], &lld); + memcpy(&s->pending_buf[s->pending], &lld, sizeof(lld)); s->pending += 8; } diff --git a/inffast.c b/inffast.c index 36923317de..bfb1c83134 100644 --- a/inffast.c +++ b/inffast.c @@ -14,7 +14,7 @@ /* Load 64 bits from IN and place the bytes at offset BITS in the result. */ static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { uint64_t chunk; - zmemcpy_8(&chunk, in); + memcpy(&chunk, in, sizeof(chunk)); #if BYTE_ORDER == LITTLE_ENDIAN return chunk << bits; diff --git a/inflate_p.h b/inflate_p.h index 20f6b1a8c3..7122d7ce65 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -176,21 +176,21 @@ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, uint64_t len, } if (tocopy >= 8) { - zmemcpy_8(out, from); + memcpy(out, from, 8); out += 8; from += 8; tocopy -= 8; } if (tocopy >= 4) { - zmemcpy_4(out, from); + memcpy(out, from, 4); out += 4; from += 4; tocopy -= 4; } if (tocopy >= 2) { - zmemcpy_2(out, from); + memcpy(out, from, 2); out += 2; from += 2; tocopy -= 2; diff --git a/insert_string_tpl.h b/insert_string_tpl.h index 643a5e0e31..4acd67fd62 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -31,7 +31,7 @@ #ifndef HASH_CALC_READ # if BYTE_ORDER == LITTLE_ENDIAN # define HASH_CALC_READ \ - zmemcpy_4(&val, strstart); + memcpy(&val, strstart, sizeof(val)); # else # define HASH_CALC_READ \ val = ((uint32_t)(strstart[0])); \ diff --git a/match_tpl.h b/match_tpl.h index 3fc71c15a0..fbd34e58a5 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -74,11 +74,11 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif #ifdef UNALIGNED64_OK - zmemcpy_8(scan_start, scan); - zmemcpy_8(scan_end, scan+offset); + memcpy(scan_start, scan, sizeof(uint64_t)); + memcpy(scan_end, scan+offset, sizeof(uint64_t)); #elif defined(UNALIGNED_OK) - zmemcpy_4(scan_start, scan); - zmemcpy_4(scan_end, scan+offset); + memcpy(scan_start, scan, sizeof(uint32_t)); + memcpy(scan_end, scan+offset, sizeof(uint32_t)); #else scan_end[0] = *(scan+offset); scan_end[1] = *(scan+offset+1); @@ -201,9 +201,9 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif #ifdef UNALIGNED64_OK - zmemcpy_8(scan_end, scan+offset); + memcpy(scan_end, scan+offset, sizeof(uint64_t)); #elif defined(UNALIGNED_OK) - zmemcpy_4(scan_end, scan+offset); + memcpy(scan_end, scan+offset, sizeof(uint32_t)); #else scan_end[0] = *(scan+offset); scan_end[1] = *(scan+offset+1); diff --git a/zbuild.h b/zbuild.h index d82c1c388e..10a7fd6b3d 100644 --- a/zbuild.h +++ b/zbuild.h @@ -218,31 +218,22 @@ # endif #endif -/* Force compiler to emit unaligned memory accesses if unaligned access is supported +/* Force compiler to emit unaligned memory comparisons if unaligned access is supported on the architecture, otherwise don't assume unaligned access is supported. Older - compilers don't optimize memcpy and memcmp calls to unaligned access instructions - when it is supported on the architecture resulting in significant performance impact. - Newer compilers might optimize memcpy but not all optimize memcmp for all integer types. */ + compilers don't optimize memcmp calls for all integer types to unaligned access instructions + when it is supported on the architecture resulting in significant performance impact. */ #ifdef UNALIGNED_OK -# define zmemcpy_2(dest, src) (*((uint16_t *)(dest)) = *((uint16_t *)(src))) # define zmemcmp_2(str1, str2) (*((uint16_t *)(str1)) != *((uint16_t *)(str2))) -# define zmemcpy_4(dest, src) (*((uint32_t *)(dest)) = *((uint32_t *)(src))) # define zmemcmp_4(str1, str2) (*((uint32_t *)(str1)) != *((uint32_t *)(str2))) # if defined(UNALIGNED64_OK) && (UINTPTR_MAX == UINT64_MAX) -# define zmemcpy_8(dest, src) (*((uint64_t *)(dest)) = *((uint64_t *)(src))) # define zmemcmp_8(str1, str2) (*((uint64_t *)(str1)) != *((uint64_t *)(str2))) # else -# define zmemcpy_8(dest, src) (((uint32_t *)(dest))[0] = ((uint32_t *)(src))[0], \ - ((uint32_t *)(dest))[1] = ((uint32_t *)(src))[1]) # define zmemcmp_8(str1, str2) (((uint32_t *)(str1))[0] != ((uint32_t *)(str2))[0] || \ ((uint32_t *)(str1))[1] != ((uint32_t *)(str2))[1]) # endif #else -# define zmemcpy_2(dest, src) memcpy(dest, src, 2) # define zmemcmp_2(str1, str2) memcmp(str1, str2, 2) -# define zmemcpy_4(dest, src) memcpy(dest, src, 4) # define zmemcmp_4(str1, str2) memcmp(str1, str2, 4) -# define zmemcpy_8(dest, src) memcpy(dest, src, 8) # define zmemcmp_8(str1, str2) memcmp(str1, str2, 8) #endif From 998fc886d63e3a2950cb8a857cc51c72610b29cc Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Thu, 30 Jun 2022 12:04:27 -0700 Subject: [PATCH 462/798] Fix inflateBack to detect invalid input with distances too far. --- infback.c | 1 + 1 file changed, 1 insertion(+) diff --git a/infback.c b/infback.c index 95798511f7..200997c467 100644 --- a/infback.c +++ b/infback.c @@ -55,6 +55,7 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateBackInit)(PREFIX3(stream) *strm, int32_t wi state->window = window; state->wnext = 0; state->whave = 0; + state->sane = 1; state->chunksize = functable.chunksize(); return Z_OK; } From 1943c9721b61ebceaeeba4c299c461479101b773 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 4 Jul 2022 11:53:46 -0700 Subject: [PATCH 463/798] Reorganize cmake scripts for tests. * Moves cmake scripts for testing into test/cmake. * Separates out related add_tests into separate cmake scripts. * Moves building test binaries into CMakeLists.txt in test directory. --- CMakeLists.txt | 273 +---------------- test/CMakeLists.txt | 286 +++++++++++------- .../cmake/compress-and-verify.cmake | 4 +- {cmake => test/cmake}/run-and-compare.cmake | 0 {cmake => test/cmake}/run-and-redirect.cmake | 0 test/cmake/test-cves.cmake | 33 ++ test/cmake/test-data.cmake | 67 ++++ test/cmake/test-issues.cmake | 68 +++++ {cmake => test/cmake}/test-tools.cmake | 27 ++ test/pigz/CMakeLists.txt | 2 +- 10 files changed, 384 insertions(+), 376 deletions(-) rename cmake/test-compress.cmake => test/cmake/compress-and-verify.cmake (97%) rename {cmake => test/cmake}/run-and-compare.cmake (100%) rename {cmake => test/cmake}/run-and-redirect.cmake (100%) create mode 100644 test/cmake/test-cves.cmake create mode 100644 test/cmake/test-data.cmake create mode 100644 test/cmake/test-issues.cmake rename {cmake => test/cmake}/test-tools.cmake (52%) diff --git a/CMakeLists.txt b/CMakeLists.txt index fae09c7c70..d8f45b743d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1174,278 +1174,7 @@ option(ZLIB_ENABLE_TESTS "Build test binaries" ON) if(ZLIB_ENABLE_TESTS) enable_testing() - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) - add_subdirectory(test) - if(WITH_BENCHMARKS) - add_subdirectory(test/benchmarks) - endif() - else() - message(WARNING "Minimum cmake version of 3.12 not met for GoogleTest or benchmarks!") - endif() - - macro(configure_test_executable target) - target_include_directories(${target} PUBLIC - "$" - "$") - if(NOT WITH_GZFILEOP) - target_compile_definitions(${target} PUBLIC -DWITH_GZFILEOP) - target_sources(${target} PRIVATE ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) - endif() - endmacro() - - macro(add_simple_test_executable target) - add_executable(${target} test/${target}.c) - configure_test_executable(${target}) - target_link_libraries(${target} zlib) - add_test(NAME ${target} COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - endmacro() - - add_simple_test_executable(example) - - set(MINIGZIP_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_executable(minigzip test/minigzip.c) - configure_test_executable(minigzip) - if(NOT DEFINED BUILD_SHARED_LIBS) - target_link_libraries(minigzip zlibstatic) - else() - target_link_libraries(minigzip zlib) - endif() - if(BASEARCH_S360_FOUND) - if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) - set_source_files_properties(test/minigzip.c PROPERTIES COMPILE_DEFINITIONS BUFLEN=262144) - endif() - endif() - - set(MINIDEFLATE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_executable(minideflate test/minideflate.c) - configure_test_executable(minideflate) - target_link_libraries(minideflate zlib) - - if(INSTALL_UTILS) - install(TARGETS minigzip minideflate - RUNTIME DESTINATION "${BIN_INSTALL_DIR}" - ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" - LIBRARY DESTINATION "${LIB_INSTALL_DIR}") - endif() - - set(SWITCHLEVELS_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_executable(switchlevels test/switchlevels.c) - configure_test_executable(switchlevels) - target_link_libraries(switchlevels zlib) - - add_simple_test_executable(infcover) - if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) - target_sources(infcover PRIVATE inftrees.c) - endif() - - add_executable(makefixed tools/makefixed.c inftrees.c) - target_include_directories(makefixed PUBLIC - "$" - "$") - - set(MAKEFIXED_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME makefixed - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${MAKEFIXED_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/inffixed_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/inffixed_tbl.h - -DIGNORE_LINE_ENDINGS=ON - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) - - add_executable(maketrees tools/maketrees.c trees.c zutil.c) - target_include_directories(maketrees PUBLIC - "$" - "$") - - set(MAKETREES_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME maketrees - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${MAKETREES_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/trees_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/trees_tbl.h - -DIGNORE_LINE_ENDINGS=ON - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) - - add_executable(makecrct tools/makecrct.c) - target_include_directories(makecrct PUBLIC - "$" - "$") - - set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME makecrct - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/crc32_braid_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_braid_tbl.h - -DIGNORE_LINE_ENDINGS=ON - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) - - if(WITH_FUZZERS) - add_subdirectory(test/fuzz) - endif() - - macro(test_minigzip name path) - # Construct compression arguments for minigzip - set(compress_args -k -c) - foreach(extra_arg IN ITEMS "${ARGN}") - list(APPEND compress_args ${extra_arg}) - endforeach() - - # Create unique friendly string for test - string(REPLACE ";" "" arg_list "${ARGN}") - string(REPLACE " " "" arg_list "${arg_list}") - string(REPLACE "-" "" arg_list "${arg_list}") - - set(test_id minigzip-${name}-${arg_list}) - - if(NOT TEST ${test_id}) - add_test(NAME ${test_id} - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIGZIP_COMMAND}" - "-DCOMPRESS_ARGS=${compress_args}" - "-DDECOMPRESS_ARGS=-d;-c" - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${path} - -DTEST_NAME=${test_id} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - endif() - endmacro() - - set(TEST_CONFIGS - -R # Z_RLE - -h # Z_HUFFMAN_ONLY - -T # Direct store - -0 # No compression - -1 # Deflate quick - -4 # Deflate medium (lazy matches) - "-5;-F" # Deflate medium (Z_FIXED) - -6 # Deflate medium - -9 # Deflate slow - "-9;-f" # Deflate slow (Z_FILTERED) - ) - - file(GLOB_RECURSE TEST_FILE_PATHS - LIST_DIRECTORIES false - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/test/data/*) - - foreach(TEST_FILE_PATH ${TEST_FILE_PATHS}) - if("${TEST_FILE_PATH}" MATCHES ".gz$" OR "${TEST_FILE_PATH}" MATCHES ".out$" OR - "${TEST_FILE_PATH}" MATCHES "/.git/" OR "${TEST_FILE_PATH}" MATCHES ".md$") - continue() - endif() - foreach(TEST_CONFIG ${TEST_CONFIGS}) - get_filename_component(TEST_NAME ${TEST_FILE_PATH} NAME) - if (TEST_NAME STREQUAL "") - continue() - endif() - test_minigzip(${TEST_NAME} ${TEST_FILE_PATH} ${TEST_CONFIG}) - endforeach() - endforeach() - - test_minigzip("detect-text" "test/data/lcet10.txt" -A) - test_minigzip("detect-binary" "test/data/paper-100k.pdf" -A) - - set(CVES CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096) - foreach(CVE ${CVES}) - set(CVE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ -d) - add_test(NAME ${CVE} - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${CVE_COMMAND}" - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/${CVE}/test.gz - "-DSUCCESS_EXIT=0;1" - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake) - endforeach() - - set(TEST_LEVELS 6 1 2) - foreach(TEST_LEVEL ${TEST_LEVELS}) - add_test(NAME CVE-2018-25032-fixed-level-${TEST_LEVEL} - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIDEFLATE_COMMAND}" - "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-F;-${TEST_LEVEL}" - "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15;-${TEST_LEVEL}" - -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/fixed.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME CVE-2018-25032-default-level-${TEST_LEVEL} - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIDEFLATE_COMMAND}" - "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-${TEST_LEVEL}" - "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15;-${TEST_LEVEL}" - -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/default.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - endforeach() - - # Run tests targeting tools - include(cmake/test-tools.cmake) - - add_test(NAME GH-361 - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIGZIP_COMMAND}" - "-DCOMPRESS_ARGS=-c;-k;-4" - -DTEST_NAME=GH-361-test-txt - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-361/test.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-364 - COMMAND ${CMAKE_COMMAND} - "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" - "-DCOMPRESS_ARGS=1;5;9;3" - "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" - -DTEST_NAME=GH-364-test-bin - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-364/test.bin - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-382 - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIDEFLATE_COMMAND}" - "-DCOMPRESS_ARGS=-c;-m;1;-w;-15;-1;-s;4" - "-DDECOMPRESS_ARGS=-c;-d;-m;1;-w;-15" - -DGZIP_VERIFY=OFF - -DTEST_NAME=GH-382-defneg3-dat - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-382/defneg3.dat - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-536-segfault - COMMAND ${CMAKE_COMMAND} - "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" - "-DCOMPRESS_ARGS=6;9744;1;91207" - "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" - -DCOMPARE=OFF - -DGZIP_VERIFY=OFF - -DTEST_NAME=GH-536-segfault-lcet10-txt - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-536-incomplete-read - COMMAND ${CMAKE_COMMAND} - "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" - "-DCOMPRESS_ARGS=6;88933;1;195840;2;45761" - "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" - -DCOMPARE=OFF - -DGZIP_VERIFY=OFF - -DTEST_NAME=GH-536-incomplete-read-lcet10-txt - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-536-zero-stored-block - COMMAND ${CMAKE_COMMAND} - "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" - "-DCOMPRESS_ARGS=6;15248;1;1050;2;25217" - "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" - -DCOMPARE=OFF - -DGZIP_VERIFY=OFF - -DTEST_NAME=GH-536-zero-stored-block-lcet10-txt - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/data/lcet10.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME GH-751 - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIGZIP_COMMAND}" - -DTEST_NAME=GH-751-test-txt - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-751/test.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) + add_subdirectory(test) endif() add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile related functions") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f30f9ac3a0..be508f61d6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,128 +1,212 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.5.1) + +macro(configure_test_executable target) + target_include_directories(${target} PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + if(NOT WITH_GZFILEOP) + target_compile_definitions(${target} PRIVATE -DWITH_GZFILEOP) + target_sources(${target} PRIVATE ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) + endif() +endmacro() + +add_executable(example example.c) +configure_test_executable(example) +target_link_libraries(example zlib) +add_test(NAME example COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) + +add_executable(minigzip minigzip.c) +configure_test_executable(minigzip) +if(NOT DEFINED BUILD_SHARED_LIBS) + target_link_libraries(minigzip zlibstatic) +else() + target_link_libraries(minigzip zlib) +endif() +if(BASEARCH_S360_FOUND) + if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) + set_source_files_properties(minigzip.c PROPERTIES COMPILE_DEFINITIONS BUFLEN=262144) + endif() +endif() +set(MINIGZIP_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) + +add_executable(minideflate minideflate.c) +configure_test_executable(minideflate) +target_link_libraries(minideflate zlib) +set(MINIDEFLATE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) + +if(INSTALL_UTILS) + install(TARGETS minigzip minideflate + RUNTIME DESTINATION "${BIN_INSTALL_DIR}" + ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" + LIBRARY DESTINATION "${LIB_INSTALL_DIR}") +endif() + +add_executable(switchlevels switchlevels.c) +configure_test_executable(switchlevels) +target_link_libraries(switchlevels zlib) +set(SWITCHLEVELS_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -include(FetchContent) +add_executable(infcover infcover.c) +configure_test_executable(infcover) +target_link_libraries(infcover zlib) +if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) + target_sources(infcover PRIVATE ${CMAKE_SOURCE_DIR}/inftrees.c) +endif() +add_test(NAME infcover COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -enable_language(CXX) +add_executable(makefixed ${CMAKE_SOURCE_DIR}/tools/makefixed.c ${CMAKE_SOURCE_DIR}/inftrees.c) +configure_test_executable(makefixed) +set(MAKEFIXED_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -# Google test requires at least C++11 -set(CMAKE_CXX_STANDARD 11) +add_executable(maketrees ${CMAKE_SOURCE_DIR}/tools/maketrees.c ${CMAKE_SOURCE_DIR}/trees.c ${CMAKE_SOURCE_DIR}/zutil.c) +configure_test_executable(maketrees) +set(MAKETREES_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -# Google test requires MSAN instrumented LLVM C++ libraries -if(WITH_SANITIZER STREQUAL "Memory") - if(NOT DEFINED ENV{LLVM_BUILD_DIR}) - message(FATAL_ERROR "MSAN instrumented C++ libraries required!") - endif() +add_executable(makecrct ${CMAKE_SOURCE_DIR}/tools/makecrct.c) +configure_test_executable(makecrct) +set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - # Must set include and compile options before fetching googletest - include_directories($ENV{LLVM_BUILD_DIR}/include $ENV{LLVM_BUILD_DIR}/include/c++/v1) - add_compile_options(-stdlib=libc++ -g) +# Runs tests targeting CVEs +include(cmake/test-cves.cmake) + +# Run tests with data files +include(cmake/test-data.cmake) + +# Run tests targeting GitHub issues +include(cmake/test-issues.cmake) + +# Run tests targeting tools +include(cmake/test-tools.cmake) + +if(WITH_FUZZERS) + add_subdirectory(fuzz) endif() -if(NOT TARGET GTest::GTest) - # Prevent overriding the parent project's compiler/linker settings for Windows - set(gtest_force_shared_crt ON CACHE BOOL - "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) +if(CMAKE_VERSION VERSION_LESS 3.12) + message(WARNING "Minimum cmake version of 3.12 not met for GoogleTest or benchmarks!") +else() + enable_language(CXX) - # Allow specifying alternative Google test repository - if(NOT DEFINED GTEST_REPOSITORY) - set(GTEST_REPOSITORY https://github.com/google/googletest.git) + include(FetchContent) + + if(WITH_BENCHMARKS) + add_subdirectory(benchmarks) endif() - if(NOT DEFINED GTEST_TAG) - # Use older version of Google test to support older versions of GCC - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3) - set(GTEST_TAG release-1.10.0) - else() - set(GTEST_TAG release-1.11.0) + + # Google test requires at least C++11 + set(CMAKE_CXX_STANDARD 11) + + # Google test requires MSAN instrumented LLVM C++ libraries + if(WITH_SANITIZER STREQUAL "Memory") + if(NOT DEFINED ENV{LLVM_BUILD_DIR}) + message(FATAL_ERROR "MSAN instrumented C++ libraries required!") endif() + + # Must set include and compile options before fetching googletest + include_directories($ENV{LLVM_BUILD_DIR}/include $ENV{LLVM_BUILD_DIR}/include/c++/v1) + add_compile_options(-stdlib=libc++ -g) endif() - # Fetch Google test source code from official repository - FetchContent_Declare(googletest - GIT_REPOSITORY ${GTEST_REPOSITORY} - GIT_TAG ${GTEST_TAG}) + if(NOT TARGET GTest::GTest) + # Prevent overriding the parent project's compiler/linker settings for Windows + set(gtest_force_shared_crt ON CACHE BOOL + "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) + + # Allow specifying alternative Google test repository + if(NOT DEFINED GTEST_REPOSITORY) + set(GTEST_REPOSITORY https://github.com/google/googletest.git) + endif() + if(NOT DEFINED GTEST_TAG) + # Use older version of Google test to support older versions of GCC + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3) + set(GTEST_TAG release-1.10.0) + else() + set(GTEST_TAG release-1.11.0) + endif() + endif() + + # Fetch Google test source code from official repository + FetchContent_Declare(googletest + GIT_REPOSITORY ${GTEST_REPOSITORY} + GIT_TAG ${GTEST_TAG}) - FetchContent_GetProperties(googletest) - if(NOT googletest_POPULATED) - FetchContent_Populate(googletest) - add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) + FetchContent_GetProperties(googletest) + if(NOT googletest_POPULATED) + FetchContent_Populate(googletest) + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() + add_library(GTest::GTest ALIAS gtest) endif() - add_library(GTest::GTest ALIAS gtest) -endif() -set(TEST_SRCS - test_adler32.cc - test_aligned_alloc.cc - test_compare256.cc - test_compress.cc - test_compress_bound.cc - test_crc32.cc - test_cve-2003-0107.cc - test_deflate_bound.cc - test_deflate_copy.cc - test_deflate_dict.cc - test_deflate_hash_head_0.cc - test_deflate_header.cc - test_deflate_params.cc - test_deflate_pending.cc - test_deflate_prime.cc - test_deflate_quick_bi_valid.cc - test_deflate_quick_block_open.cc - test_deflate_tune.cc - test_dict.cc - test_inflate_adler32.cc - test_inflate_sync.cc - test_large_buffers.cc - test_small_buffers.cc - test_version.cc - ) - -if(WITH_GZFILEOP) - list(APPEND TEST_SRCS test_gzio.cc) -endif() + set(TEST_SRCS + test_adler32.cc + test_aligned_alloc.cc + test_compare256.cc + test_compress.cc + test_compress_bound.cc + test_crc32.cc + test_cve-2003-0107.cc + test_deflate_bound.cc + test_deflate_copy.cc + test_deflate_dict.cc + test_deflate_hash_head_0.cc + test_deflate_header.cc + test_deflate_params.cc + test_deflate_pending.cc + test_deflate_prime.cc + test_deflate_quick_bi_valid.cc + test_deflate_quick_block_open.cc + test_deflate_tune.cc + test_dict.cc + test_inflate_adler32.cc + test_inflate_sync.cc + test_large_buffers.cc + test_small_buffers.cc + test_version.cc + ) + + if(WITH_GZFILEOP) + list(APPEND TEST_SRCS test_gzio.cc) + endif() -add_executable(gtest_zlib test_main.cc ${TEST_SRCS}) + add_executable(gtest_zlib test_main.cc ${TEST_SRCS}) + configure_test_executable(gtest_zlib) -target_include_directories(gtest_zlib PRIVATE - ${CMAKE_SOURCE_DIR} - ${CMAKE_BINARY_DIR}) + if(WITH_SANITIZER STREQUAL "Memory") + target_link_directories(gtest_zlib PRIVATE $ENV{LLVM_BUILD_DIR}/lib) + target_link_options(gtest_zlib PRIVATE + -stdlib=libc++ + -lc++abi + -fsanitize=memory + -fsanitize-memory-track-origins) + endif() -if(WITH_SANITIZER STREQUAL "Memory") - target_link_directories(gtest_zlib PRIVATE $ENV{LLVM_BUILD_DIR}/lib) - target_link_options(gtest_zlib PRIVATE - -stdlib=libc++ - -lc++abi - -fsanitize=memory - -fsanitize-memory-track-origins) -endif() + if(ZLIB_DUAL_LINK AND NOT ZLIB_COMPAT) + find_package(ZLIB) + if(ZLIB_FOUND) + message(STATUS "Added dual linking tests against zlib") + message(STATUS " Zlib include dir: ${ZLIB_INCLUDE_DIR}") + message(STATUS " Zlib libraries: ${ZLIB_LIBRARIES}") -if(ZLIB_DUAL_LINK AND NOT ZLIB_COMPAT) - find_package(ZLIB) - if(ZLIB_FOUND) - message(STATUS "Added dual linking tests against zlib") - message(STATUS " Zlib include dir: ${ZLIB_INCLUDE_DIR}") - message(STATUS " Zlib libraries: ${ZLIB_LIBRARIES}") - - target_sources(gtest_zlib PRIVATE test_compress_dual.cc) - target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIR}) - target_link_libraries(gtest_zlib ${ZLIB_LIBRARIES}) - else() - message(WARNING "Zlib not found, skipping dual linking tests") + target_sources(gtest_zlib PRIVATE test_compress_dual.cc) + target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIR}) + target_link_libraries(gtest_zlib ${ZLIB_LIBRARIES}) + else() + message(WARNING "Zlib not found, skipping dual linking tests") + endif() endif() -endif() -target_link_libraries(gtest_zlib zlibstatic GTest::GTest) + target_link_libraries(gtest_zlib zlibstatic GTest::GTest) -find_package(Threads) -if(Threads_FOUND) - target_sources(gtest_zlib PRIVATE test_deflate_concurrency.cc) - if(UNIX AND NOT APPLE) - # On Linux, use a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590 - target_link_libraries(gtest_zlib -Wl,--whole-archive -lpthread -Wl,--no-whole-archive) + find_package(Threads) + if(Threads_FOUND) + target_sources(gtest_zlib PRIVATE test_deflate_concurrency.cc) + if(UNIX AND NOT APPLE) + # On Linux, use a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590 + target_link_libraries(gtest_zlib -Wl,--whole-archive -lpthread -Wl,--no-whole-archive) + endif() + target_link_libraries(gtest_zlib Threads::Threads) endif() - target_link_libraries(gtest_zlib Threads::Threads) -endif() -if(ZLIB_ENABLE_TESTS) add_test(NAME gtest_zlib COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) endif() diff --git a/cmake/test-compress.cmake b/test/cmake/compress-and-verify.cmake similarity index 97% rename from cmake/test-compress.cmake rename to test/cmake/compress-and-verify.cmake index cfc7613ab2..856f2cb353 100644 --- a/cmake/test-compress.cmake +++ b/test/cmake/compress-and-verify.cmake @@ -1,5 +1,5 @@ -# test-compress.cmake -- Runs a test against an input file to make sure that the specified -# targets are able to to compress and then decompress it successfully. Optionally verify +# compress-and-verify.cmake -- Runs a test against an input file to make sure that the specified +# targets are able to to compress and then decompress successfully. Optionally verify # the results with gzip. Output files are generated with unique names to prevent parallel # tests from corrupting one another. Default target arguments are compatible with minigzip. diff --git a/cmake/run-and-compare.cmake b/test/cmake/run-and-compare.cmake similarity index 100% rename from cmake/run-and-compare.cmake rename to test/cmake/run-and-compare.cmake diff --git a/cmake/run-and-redirect.cmake b/test/cmake/run-and-redirect.cmake similarity index 100% rename from cmake/run-and-redirect.cmake rename to test/cmake/run-and-redirect.cmake diff --git a/test/cmake/test-cves.cmake b/test/cmake/test-cves.cmake new file mode 100644 index 0000000000..4a08604034 --- /dev/null +++ b/test/cmake/test-cves.cmake @@ -0,0 +1,33 @@ +# test-cves.cmake -- Tests targeting common vulnerabilities and exposures + +set(CVES CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096) +foreach(cve ${CVES}) + set(CVE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ -d) + add_test(NAME ${cve} + COMMAND ${CMAKE_COMMAND} + "-DCOMMAND=${CVE_COMMAND}" + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${cve}/test.gz + "-DSUCCESS_EXIT=0;1" + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake) +endforeach() + +set(CVE_COMPRESS_LEVELS 6 1 2) +foreach(cve_compress_level ${CVE_COMPRESS_LEVELS}) + add_test(NAME CVE-2018-25032-fixed-level-${cve_compress_level} + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIDEFLATE_COMMAND}" + "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-F;-${cve_compress_level}" + "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15;-${cve_compress_level}" + -DGZIP_VERIFY=OFF + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/CVE-2018-25032/fixed.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + + add_test(NAME CVE-2018-25032-default-level-${cve_compress_level} + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIDEFLATE_COMMAND}" + "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-${cve_compress_level}" + "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15;-${cve_compress_level}" + -DGZIP_VERIFY=OFF + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/CVE-2018-25032/default.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) +endforeach() diff --git a/test/cmake/test-data.cmake b/test/cmake/test-data.cmake new file mode 100644 index 0000000000..07013355a3 --- /dev/null +++ b/test/cmake/test-data.cmake @@ -0,0 +1,67 @@ +# test-data.cmake - Tests targeting data files in the data directory + +# Test compress and verify test against data file using extra args +macro(test_minigzip name path) + # Construct compression arguments for minigzip + set(compress_args -k -c) + foreach(extra_arg IN ITEMS "${ARGN}") + list(APPEND compress_args ${extra_arg}) + endforeach() + + # Create unique friendly string for test + string(REPLACE ";" "" arg_list "${ARGN}") + string(REPLACE " " "" arg_list "${arg_list}") + string(REPLACE "-" "" arg_list "${arg_list}") + + set(test_id minigzip-${name}-${arg_list}) + + if(NOT TEST ${test_id}) + add_test(NAME ${test_id} + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIGZIP_COMMAND}" + "-DCOMPRESS_ARGS=${compress_args}" + "-DDECOMPRESS_ARGS=-d;-c" + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${path} + -DTEST_NAME=${test_id} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + endif() +endmacro() + +# List of arg combinations to use during compression +set(TEST_CONFIGS + -R # Z_RLE + -h # Z_HUFFMAN_ONLY + -T # Direct store + -0 # No compression + -1 # Deflate quick + -4 # Deflate medium (lazy matches) + "-5;-F" # Deflate medium (Z_FIXED) + -6 # Deflate medium + -9 # Deflate slow + "-9;-f" # Deflate slow (Z_FILTERED) +) + +# Enumerate all files in data directory to run tests against +file(GLOB_RECURSE TEST_FILE_PATHS + LIST_DIRECTORIES false + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/data/*) + +# For all files in the data directory, run tests against them +foreach(test_file_path ${TEST_FILE_PATHS}) + if("${test_file_path}" MATCHES ".gz$" OR "${test_file_path}" MATCHES ".out$" OR + "${test_file_path}" MATCHES "/.git/" OR "${test_file_path}" MATCHES ".md$") + continue() + endif() + foreach(test_config ${TEST_CONFIGS}) + get_filename_component(test_name ${test_file_path} NAME) + if (test_name STREQUAL "") + continue() + endif() + test_minigzip(${test_name} ${test_file_path} ${test_config}) + endforeach() +endforeach() + +# Additional tests to verify with automatic data type detection arg +test_minigzip("detect-text" "data/lcet10.txt" -A) +test_minigzip("detect-binary" "data/paper-100k.pdf" -A) diff --git a/test/cmake/test-issues.cmake b/test/cmake/test-issues.cmake new file mode 100644 index 0000000000..1ffb3abda4 --- /dev/null +++ b/test/cmake/test-issues.cmake @@ -0,0 +1,68 @@ +# test-issues.cmake -- Tests targeting specific GitHub issues + +add_test(NAME GH-361 + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIGZIP_COMMAND}" + "-DCOMPRESS_ARGS=-c;-k;-4" + -DTEST_NAME=GH-361-test-txt + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/GH-361/test.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + +add_test(NAME GH-364 + COMMAND ${CMAKE_COMMAND} + "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" + "-DCOMPRESS_ARGS=1;5;9;3" + "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" + -DTEST_NAME=GH-364-test-bin + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/GH-364/test.bin + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + +add_test(NAME GH-382 + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIDEFLATE_COMMAND}" + "-DCOMPRESS_ARGS=-c;-m;1;-w;-15;-1;-s;4" + "-DDECOMPRESS_ARGS=-c;-d;-m;1;-w;-15" + -DGZIP_VERIFY=OFF + -DTEST_NAME=GH-382-defneg3-dat + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/GH-382/defneg3.dat + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + +add_test(NAME GH-536-segfault + COMMAND ${CMAKE_COMMAND} + "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" + "-DCOMPRESS_ARGS=6;9744;1;91207" + "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" + -DCOMPARE=OFF + -DGZIP_VERIFY=OFF + -DTEST_NAME=GH-536-segfault-lcet10-txt + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/data/lcet10.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + +add_test(NAME GH-536-incomplete-read + COMMAND ${CMAKE_COMMAND} + "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" + "-DCOMPRESS_ARGS=6;88933;1;195840;2;45761" + "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" + -DCOMPARE=OFF + -DGZIP_VERIFY=OFF + -DTEST_NAME=GH-536-incomplete-read-lcet10-txt + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/data/lcet10.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + +add_test(NAME GH-536-zero-stored-block + COMMAND ${CMAKE_COMMAND} + "-DCOMPRESS_TARGET=${SWITCHLEVELS_COMMAND}" + "-DCOMPRESS_ARGS=6;15248;1;1050;2;25217" + "-DDECOMPRESS_TARGET=${MINIGZIP_COMMAND}" + -DCOMPARE=OFF + -DGZIP_VERIFY=OFF + -DTEST_NAME=GH-536-zero-stored-block-lcet10-txt + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/data/lcet10.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + +add_test(NAME GH-751 + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIGZIP_COMMAND}" + -DTEST_NAME=GH-751-test-txt + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/GH-751/test.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) diff --git a/cmake/test-tools.cmake b/test/cmake/test-tools.cmake similarity index 52% rename from cmake/test-tools.cmake rename to test/cmake/test-tools.cmake index 4afe07c2c1..ce9a3ff2c7 100644 --- a/cmake/test-tools.cmake +++ b/test/cmake/test-tools.cmake @@ -32,3 +32,30 @@ add_test(NAME switchlevels-help COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${TEST_COMMAND}" -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake) + +# Test generated crc32 tables match tables in source directory +add_test(NAME makecrct + COMMAND ${CMAKE_COMMAND} + "-DCOMMAND=${MAKECRCT_COMMAND}" + -DOUTPUT=${CMAKE_BINARY_DIR}/Testing/Temporary/crc32_braid_tbl._h + -DCOMPARE=${CMAKE_SOURCE_DIR}/crc32_braid_tbl.h + -DIGNORE_LINE_ENDINGS=ON + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) + +# Test generated inflate tables match tables in source directory +add_test(NAME makefixed + COMMAND ${CMAKE_COMMAND} + "-DCOMMAND=${MAKEFIXED_COMMAND}" + -DOUTPUT=${CMAKE_BINARY_DIR}/Testing/Temporary/inffixed_tbl._h + -DCOMPARE=${CMAKE_SOURCE_DIR}/inffixed_tbl.h + -DIGNORE_LINE_ENDINGS=ON + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) + +# Test generated tree tables match tables in source directory +add_test(NAME maketrees + COMMAND ${CMAKE_COMMAND} + "-DCOMMAND=${MAKETREES_COMMAND}" + -DOUTPUT=${CMAKE_BINARY_DIR}/Testing/Temporary/trees_tbl._h + -DCOMPARE=${CMAKE_SOURCE_DIR}/trees_tbl.h + -DIGNORE_LINE_ENDINGS=ON + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) diff --git a/test/pigz/CMakeLists.txt b/test/pigz/CMakeLists.txt index 0d5bc86430..d1f5b22d23 100644 --- a/test/pigz/CMakeLists.txt +++ b/test/pigz/CMakeLists.txt @@ -167,7 +167,7 @@ if(PIGZ_ENABLE_TESTS) "-DDECOMPRESS_ARGS=-d;-c" -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/${path} -DTEST_NAME=${test_id} - -P ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/test-compress.cmake) + -P ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/compress-and-verify.cmake) endif() endmacro() From 89763032d57e3da5301f4cd6e1f363e7a1f85f02 Mon Sep 17 00:00:00 2001 From: Viktor Szakats Date: Sun, 17 Jul 2022 19:33:01 +0000 Subject: [PATCH 464/798] cmake: respect custom `RC` flags and delete `GCC_WINDRES` Before this patch, `zlib.rc` was compiled using a manual command [1] when using the MinGW (and MSYS/Cygwin) toolchains. This method ignores `CMAKE_RC_FLAGS` and offers no other way to pass a custom flag, breaking the build in cases where a custom `windres` option is required. E.g. `--target=` or `-I` on some platforms and configuration, in particular with `llvm-windres`. This patch deletes the special case for these toolchains and lets CMake compile the `.rc` file the default way used for all Windows targets. I'm not entirely sure why this special case was added back in 2011. The need to pass `-DGCC_WINDRES` is my suspect. We can resolve this much simpler by adding this line for the targets that require it: set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS} -DGCC_WINDRES") But, the `.rc` line protected by `GCC_WINDRES`, these days work just fine with `windres`. Moreover, that protected line are oboslete flags from the 16-bit era, which for a long time have no effect, as documented here: So, this patch deletes `GCC_WINDRES` from the project entirely. [1] dc5a43e --- CMakeLists.txt | 21 +-------------------- configure | 3 --- win32/zlib-ng1.rc | 4 ---- win32/zlib1.rc | 4 ---- 4 files changed, 1 insertion(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8f45b743d..fafedb9ce2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -997,26 +997,7 @@ if(WITH_GZFILEOP) endif() if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) - if(NOT MINGW AND NOT MSYS AND NOT CYGWIN) - # If present will override custom build rule below. - set(ZLIB_DLL_SRCS win32/zlib${SUFFIX}1.rc) - endif() - - if(MINGW OR MSYS OR CYGWIN) - # This gets us DLL resource information when compiling on MinGW. - if(NOT CMAKE_RC_COMPILER) - set(CMAKE_RC_COMPILER windres.exe) - endif() - - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND ${CMAKE_RC_COMPILER} - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib${SUFFIX}1.rc) - set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) - endif() + set(ZLIB_DLL_SRCS win32/zlib${SUFFIX}1.rc) endif() if(NOT DEFINED BUILD_SHARED_LIBS) diff --git a/configure b/configure index f28f1dba2f..4e73a22dcc 100755 --- a/configure +++ b/configure @@ -432,7 +432,6 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then LDSHAREDLIBC="" DEFFILE='win32/${LIBNAME2}.def' RC="${CROSS_PREFIX}windres" - RCFLAGS='--define GCC_WINDRES' RCOBJS='zlibrc.o' STRIP="${CROSS_PREFIX}strip" EXE='.exe' ;; @@ -455,7 +454,6 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then LDSHAREDLIBC="" DEFFILE='win32/${LIBNAME2}.def' RC="${CROSS_PREFIX}windres" - RCFLAGS='--define GCC_WINDRES' RCOBJS='zlibrc.o' STRIP="${CROSS_PREFIX}strip" EXE='.exe' ;; @@ -475,7 +473,6 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then LDSHAREDLIBC="" DEFFILE='win32/${LIBNAME2}.def' RC="${CROSS_PREFIX}windres" - RCFLAGS='--define GCC_WINDRES' if [ "$CC" == "mingw32-gcc" ]; then case $ARCH in i386 | i486 | i586 | i686) RCFLAGS="${RCFLAGS} -F pe-i386";; diff --git a/win32/zlib-ng1.rc b/win32/zlib-ng1.rc index f524131462..327f17fd8b 100644 --- a/win32/zlib-ng1.rc +++ b/win32/zlib-ng1.rc @@ -1,11 +1,7 @@ #include #include "zlib-ng.h" -#ifdef GCC_WINDRES VS_VERSION_INFO VERSIONINFO -#else -VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE -#endif FILEVERSION ZLIBNG_VER_MAJOR,ZLIBNG_VER_MINOR,ZLIBNG_VER_REVISION,0 PRODUCTVERSION ZLIBNG_VER_MAJOR,ZLIBNG_VER_MINOR,ZLIBNG_VER_REVISION,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK diff --git a/win32/zlib1.rc b/win32/zlib1.rc index ee0b287953..82e5934c2b 100644 --- a/win32/zlib1.rc +++ b/win32/zlib1.rc @@ -1,11 +1,7 @@ #include #include "zlib.h" -#ifdef GCC_WINDRES VS_VERSION_INFO VERSIONINFO -#else -VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE -#endif FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK From ab47c738037dc51d0d44de7e64661648c24c9fb4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 21 Aug 2022 10:03:32 -0700 Subject: [PATCH 465/798] Fixed content already populated error in CMake scripts. #1327 Should only need to use either FetchContent_MakeAvailable or FetchContent_GetProperties and FetchContent_Populate but not both methods. We use the later for CMake compatibility with lower versions. --- test/benchmarks/CMakeLists.txt | 10 +++++----- test/pigz/CMakeLists.txt | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index 19762fc738..e6eaa352b0 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -14,11 +14,11 @@ if(NOT benchmark_FOUND) set(BENCHMARK_ENABLE_TESTING OFF) FetchContent_Declare(benchmark GIT_REPOSITORY https://github.com/google/benchmark.git) - FetchContent_MakeAvailable(benchmark) - FetchContent_GetProperties(benchmark) + FetchContent_GetProperties(benchmark) if(NOT benchmark_POPULATED) FetchContent_Populate(benchmark) + add_subdirectory(${benchmark_SOURCE_DIR} ${benchmark_BINARY_DIR}) endif() endif() @@ -55,15 +55,15 @@ if(WITH_BENCHMARK_APPS) if(NOT PNG_FOUND) FetchContent_Declare(PNG GIT_REPOSITORY https://github.com/glennrp/libpng.git) - FetchContent_MakeAvailable(PNG) - FetchContent_GetProperties(PNG) + FetchContent_GetProperties(PNG) if(NOT PNG_POPULATED) FetchContent_Populate(PNG) + add_subdirectory(${PNG_SOURCE_DIR} ${PNG_BINARY_DIR}) endif() endif() - set(BENCH_APP_SRCS + set(BENCH_APP_SRCS benchmark_png_encode.cc benchmark_png_decode.cc benchmark_main.cc diff --git a/test/pigz/CMakeLists.txt b/test/pigz/CMakeLists.txt index d1f5b22d23..bc6830ae24 100644 --- a/test/pigz/CMakeLists.txt +++ b/test/pigz/CMakeLists.txt @@ -64,9 +64,8 @@ endif() FetchContent_Declare(pigz GIT_REPOSITORY https://github.com/madler/pigz.git GIT_TAG ${PIGZ_TAG}) -FetchContent_MakeAvailable(pigz) -FetchContent_GetProperties(pigz) +FetchContent_GetProperties(pigz) if(NOT pigz_POPULATED) FetchContent_Populate(pigz) endif() From 28d1e534308bb3c3bccf61581229429f39e8d315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Wed, 24 Aug 2022 20:39:03 +0100 Subject: [PATCH 466/798] Actually run `configure` CI on macOS with GCC `gcc` is an alias for Apple Clang on macOS. See for example https://github.com/zlib-ng/zlib-ng/runs/7963904948?check_suite_focus=true ``` gcc -O2 -std=c11 -Wall -fPIC -DNDEBUG -DHAVE_POSIX_MEMALIGN -DWITH_GZFILEOP -fno-semantic-interposition -DHAVE_VISIBILITY_HIDDEN -DHAVE_VISIBILITY_INTERNAL -DHAVE_BUILTIN_CTZ -DHAVE_BUILTIN_CTZLL -DX86_FEATURES -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET -DX86_AVX512 -DX86_AVX512_ADLER32 -DX86_MASK_INTRIN -DX86_AVX512VNNI -DX86_AVX512VNNI_ADLER32 -DX86_SSE41 -DX86_SSE42_CRC_HASH -DX86_SSE42_ADLER32 -DX86_SSE42_CRC_INTRIN -DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSSE3 -DX86_SSSE3_ADLER32 -DX86_PCLMULQDQ_CRC -DPIC -I/Users/runner/work/zlib-ng/zlib-ng -c -o adler32.lo /Users/runner/work/zlib-ng/zlib-ng/adler32.c clang: warning: argument unused during compilation: '-fno-semantic-interposition' [-Wunused-command-line-argument] ``` In order to use the real GCC you have to call `gcc-9`, `gcc-10`, or `gcc-11`: https://github.com/actions/runner-images/blob/06dd4c14e4aa8c14febdd8d6cf123b8d770b4e4a/images/macos/macos-11-Readme.md#language-and-runtime. --- .github/workflows/configure.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 975af222b2..4c0d395d7d 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -178,17 +178,17 @@ jobs: - name: macOS GCC Symbol Prefix os: macOS-latest - compiler: gcc + compiler: gcc-9 configure-args: --sprefix=zTest_ - name: macOS GCC Symbol Prefix & Compat os: macOS-latest - compiler: gcc + compiler: gcc-9 configure-args: --zlib-compat --sprefix=zTest_ - name: macOS GCC os: macOS-latest - compiler: gcc + compiler: gcc-9 configure-args: --warn steps: From 8df665005952cdbe7dc995d409ffe4f861e7a83e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 20 Aug 2022 09:55:49 -0700 Subject: [PATCH 467/798] Remove ZLIB_DUAL_LINK option to simplify dual link tests. --- .github/workflows/link.yml | 4 ++-- CMakeLists.txt | 3 --- README.md | 1 - test/CMakeLists.txt | 21 ++++++++------------- 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml index 2b9000cd5c..806a934112 100644 --- a/.github/workflows/link.yml +++ b/.github/workflows/link.yml @@ -21,7 +21,7 @@ jobs: run: cmake --build zlib/build --config Release - name: Generate project files (native) - run: cmake -S . -B native -DZLIB_COMPAT=OFF -DZLIB_DUAL_LINK=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_ROOT=../zlib/build -DZLIB_LIBRARIES=../zlib/build/libz.a -DZLIB_INCLUDE_DIR=../zlib/build + run: cmake -S . -B native -DZLIB_COMPAT=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_LIBRARIES=../zlib/build/libz.a -DZLIB_INCLUDE_DIR=../zlib/build - name: Compile source code (native) run: cmake --build native --config Release @@ -50,7 +50,7 @@ jobs: run: cmake --build compat --config Release - name: Generate project files (native) - run: cmake -S . -B native -DZLIB_COMPAT=OFF -DZLIB_DUAL_LINK=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_ROOT=../compat -DZLIB_LIBRARIES=../compat/libz.a -DZLIB_INCLUDE_DIR=../compat + run: cmake -S . -B native -DZLIB_COMPAT=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_LIBRARIES=../compat/libz.a -DZLIB_INCLUDE_DIR=../compat - name: Compile source code (native) run: cmake --build native --config Release diff --git a/CMakeLists.txt b/CMakeLists.txt index fafedb9ce2..c403e5b0fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,6 @@ endif() option(WITH_GZFILEOP "Compile with support for gzFile related functions" ON) option(ZLIB_COMPAT "Compile with zlib compatible API" OFF) option(ZLIB_ENABLE_TESTS "Build test binaries" ON) -option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) option(WITH_FUZZERS "Build test/fuzz" OFF) option(WITH_BENCHMARKS "Build test/benchmarks" OFF) option(WITH_BENCHMARK_APPS "Build application benchmarks" OFF) @@ -127,7 +126,6 @@ option(INSTALL_UTILS "Copy minigzip and minideflate during install" OFF) mark_as_advanced(FORCE ZLIB_SYMBOL_PREFIX - ZLIB_DUAL_LINK WITH_REDUCED_MEM WITH_ACLE WITH_NEON WITH_DFLTCC_DEFLATE @@ -1161,7 +1159,6 @@ endif() add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile related functions") add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Compile with zlib compatible API") add_feature_info(ZLIB_ENABLE_TESTS ZLIB_ENABLE_TESTS "Build test binaries") -add_feature_info(ZLIB_DUAL_LINK ZLIB_DUAL_LINK "Dual link tests against system zlib") add_feature_info(WITH_SANITIZER WITH_SANITIZER "Enable sanitizer support") add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz") add_feature_info(WITH_BENCHMARKS WITH_BENCHMARKS "Build test/benchmarks") diff --git a/README.md b/README.md index 1efe7f2f47..ab12fa3431 100644 --- a/README.md +++ b/README.md @@ -193,7 +193,6 @@ Advanced Build Options | CMake | configure | Description | Default | |:--------------------------------|:----------------------|:--------------------------------------------------------------------|------------------------| -| ZLIB_DUAL_LINK | | Dual link tests with system zlib | OFF | | FORCE_SSE2 | --force-sse2 | Skip runtime check for SSE2 instructions (Always on for x86_64) | OFF (x86) | | FORCE_TZCNT | --force-tzcnt | Skip runtime check for TZCNT instructions | OFF | | WITH_AVX2 | | Build with AVX2 intrinsics | ON | diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index be508f61d6..29658422a1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -180,19 +180,14 @@ else() -fsanitize-memory-track-origins) endif() - if(ZLIB_DUAL_LINK AND NOT ZLIB_COMPAT) - find_package(ZLIB) - if(ZLIB_FOUND) - message(STATUS "Added dual linking tests against zlib") - message(STATUS " Zlib include dir: ${ZLIB_INCLUDE_DIR}") - message(STATUS " Zlib libraries: ${ZLIB_LIBRARIES}") - - target_sources(gtest_zlib PRIVATE test_compress_dual.cc) - target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIR}) - target_link_libraries(gtest_zlib ${ZLIB_LIBRARIES}) - else() - message(WARNING "Zlib not found, skipping dual linking tests") - endif() + if(NOT ZLIB_COMPAT AND DEFINED ZLIB_INCLUDE_DIR AND DEFINED ZLIB_LIBRARIES) + message(STATUS "Added dual linking tests against zlib") + message(STATUS " Zlib include dir: ${ZLIB_INCLUDE_DIR}") + message(STATUS " Zlib libraries: ${ZLIB_LIBRARIES}") + + target_sources(gtest_zlib PRIVATE test_compress_dual.cc) + target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIR}) + target_link_libraries(gtest_zlib ${ZLIB_LIBRARIES}) endif() target_link_libraries(gtest_zlib zlibstatic GTest::GTest) From e2b2f1fa2983d9b4d3e5bd2cc821940a0715aac8 Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Tue, 12 Jul 2022 16:27:52 +0700 Subject: [PATCH 468/798] Set `CMAKE_*_COMPILER_TARGET` to full triplet for mingw toolchains --- cmake/toolchain-mingw-i686.cmake | 16 ++++++++-------- cmake/toolchain-mingw-x86_64.cmake | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cmake/toolchain-mingw-i686.cmake b/cmake/toolchain-mingw-i686.cmake index 4b1264cb5b..cc2da2ff56 100644 --- a/cmake/toolchain-mingw-i686.cmake +++ b/cmake/toolchain-mingw-i686.cmake @@ -1,8 +1,8 @@ set(CMAKE_SYSTEM_NAME Windows) -set(CMAKE_C_COMPILER_TARGET i686) -set(CMAKE_CXX_COMPILER_TARGET i686) -set(CMAKE_RC_COMPILER_TARGET i686) +set(CMAKE_C_COMPILER_TARGET i686-w64-mingw32) +set(CMAKE_CXX_COMPILER_TARGET i686-w64-mingw32) +set(CMAKE_RC_COMPILER_TARGET i686-w64-mingw32) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR wine) @@ -14,8 +14,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Prefer posix gcc variant for gtest pthread support find_program(C_COMPILER_FULL_PATH NAMES - ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc-posix - ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc + ${CMAKE_C_COMPILER_TARGET}-gcc-posix + ${CMAKE_C_COMPILER_TARGET}-gcc gcc-mingw32-w64-${CMAKE_C_COMPILER_TARGET}) if(NOT C_COMPILER_FULL_PATH) message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") @@ -24,14 +24,14 @@ set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) find_program(CXX_COMPILER_FULL_PATH NAMES g++-mingw-w64-${CMAKE_CXX_COMPILER_TARGET} - ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++-posix - ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) + ${CMAKE_CXX_COMPILER_TARGET}-g++-posix + ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() find_program(RC_COMPILER_FULL_PATH NAMES - ${CMAKE_RC_COMPILER_TARGET}-w64-mingw32-windres) + ${CMAKE_RC_COMPILER_TARGET}-windres) if(RC_COMPILER_FULL_PATH) set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) endif() diff --git a/cmake/toolchain-mingw-x86_64.cmake b/cmake/toolchain-mingw-x86_64.cmake index 7ae8140422..8c660b0b1e 100644 --- a/cmake/toolchain-mingw-x86_64.cmake +++ b/cmake/toolchain-mingw-x86_64.cmake @@ -1,8 +1,8 @@ set(CMAKE_SYSTEM_NAME Windows) -set(CMAKE_C_COMPILER_TARGET x86_64) -set(CMAKE_CXX_COMPILER_TARGET x86_64) -set(CMAKE_RC_COMPILER_TARGET x86_64) +set(CMAKE_C_COMPILER_TARGET x86_64-w64-mingw32) +set(CMAKE_CXX_COMPILER_TARGET x86_64-w64-mingw32) +set(CMAKE_RC_COMPILER_TARGET x86_64-w64-mingw32) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR wine) @@ -14,21 +14,21 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Prefer posix gcc variant for gtest pthread support find_program(C_COMPILER_FULL_PATH NAMES - ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc-posix - ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc) + ${CMAKE_C_COMPILER_TARGET}-gcc-posix + ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) find_program(CXX_COMPILER_FULL_PATH NAMES - ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-g++-posix - ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) + ${CMAKE_CXX_COMPILER_TARGET}-g++-posix + ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() -find_program(RC_COMPILER_FULL_PATH NAMES ${CMAKE_RC_COMPILER_TARGET}-w64-mingw32-windres) +find_program(RC_COMPILER_FULL_PATH NAMES ${CMAKE_RC_COMPILER_TARGET}-windres) if(RC_COMPILER_FULL_PATH) set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) endif() From 20b93ca688ff959b7e5afc87172772884a33cbbd Mon Sep 17 00:00:00 2001 From: Long Nguyen Date: Sat, 13 Aug 2022 10:38:02 +0700 Subject: [PATCH 469/798] Remove extra compiler names --- cmake/toolchain-mingw-i686.cmake | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmake/toolchain-mingw-i686.cmake b/cmake/toolchain-mingw-i686.cmake index cc2da2ff56..b95e63f50c 100644 --- a/cmake/toolchain-mingw-i686.cmake +++ b/cmake/toolchain-mingw-i686.cmake @@ -15,15 +15,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Prefer posix gcc variant for gtest pthread support find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc-posix - ${CMAKE_C_COMPILER_TARGET}-gcc - gcc-mingw32-w64-${CMAKE_C_COMPILER_TARGET}) + ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) find_program(CXX_COMPILER_FULL_PATH NAMES - g++-mingw-w64-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++-posix ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) From 970cdee1735a4faffff86113f4bb954aebf8e503 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Sat, 23 Jul 2022 21:01:47 -0700 Subject: [PATCH 470/798] msvc/arm64: fix narrowing/signed conversion warning in NEON_accum32 --- arch/arm/adler32_neon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index 0e2a1b4033..9b55ca0c08 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -44,10 +44,10 @@ static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { uint16x8_t s2_4, s2_5, s2_6, s2_7; s2_4 = s2_5 = s2_6 = s2_7 = vdupq_n_u16(0); - int num_iter = len >> 2; + uint64_t num_iter = len >> 2; int rem = len & 3; - for (int i = 0; i < num_iter; ++i) { + for (uint64_t i = 0; i < num_iter; ++i) { uint8x16x4_t d0_d3 = vld1q_u8_x4(buf); /* Unfortunately it doesn't look like there's a direct sum 8 bit to 32 From 8098fde200388c8ef99984fbfa2cb39303ed42c8 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Sat, 23 Jul 2022 21:01:04 -0700 Subject: [PATCH 471/798] fix ACLE detection on msvc/arm64 --- CMakeLists.txt | 2 +- arch/arm/arm_features.c | 4 +++- arch/arm/crc32_acle.c | 6 ++++-- cmake/detect-intrinsics.cmake | 8 ++++++-- fallback_builtins.h | 2 +- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c403e5b0fb..8ca63a30f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -587,7 +587,7 @@ if(WITH_OPTIM) endif() list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm_features.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/arm_features.c) - if(WITH_ACLE AND NOT MSVC AND NOT "${ARCH}" MATCHES "armv[2-7]") + if(WITH_ACLE AND NOT "${ARCH}" MATCHES "armv[2-7]") check_acle_compiler_flag() if(HAVE_ACLE_FLAG) add_definitions(-DARM_ACLE_CRC_HASH) diff --git a/arch/arm/arm_features.c b/arch/arm/arm_features.c index 979204b83b..d41c13acb0 100644 --- a/arch/arm/arm_features.c +++ b/arch/arm/arm_features.c @@ -16,7 +16,7 @@ # endif # include #elif defined(_WIN32) -# include +# include #endif static int arm_has_crc32() { @@ -34,6 +34,8 @@ static int arm_has_crc32() { size_t size = sizeof(hascrc32); return sysctlbyname("hw.optional.armv8_crc32", &hascrc32, &size, NULL, 0) == 0 && hascrc32 == 1; +#elif defined(_WIN32) + return IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE); #elif defined(ARM_NOCHECK_ACLE) return 1; #else diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index ce75c343e5..ef18ae81ec 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -6,7 +6,9 @@ */ #ifdef ARM_ACLE_CRC_HASH -#ifndef _MSC_VER +#ifdef _MSC_VER +# include +#else # include #endif #include "../../zbuild.h" @@ -31,7 +33,7 @@ uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { buf4 = (const uint32_t *) buf; } -#if defined(__aarch64__) +#if defined(__aarch64__) || defined(_M_ARM64) if ((len >= sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { c = __crc32w(c, *buf4++); len -= sizeof(uint32_t); diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 1ddab22537..743af4e87c 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -2,8 +2,12 @@ # Licensed under the Zlib license, see LICENSE.md for details macro(check_acle_compiler_flag) - if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) - set(ACLEFLAG "-march=armv8-a+crc" CACHE INTERNAL "Compiler option to enable ACLE support") + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) + set(ACLEFLAG "-march=armv8-a+crc" CACHE INTERNAL "Compiler option to enable ACLE support") + endif() + elseif(MSVC) + set(HAVE_ACLE_FLAG TRUE) endif() # Check whether compiler supports ACLE flag set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG}") diff --git a/fallback_builtins.h b/fallback_builtins.h index 6ab89c20f8..3e58942078 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -71,7 +71,7 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { #endif // __AVX2__ -#if defined(ARM_NEON_ADLER32) && !defined(__aarch64__) +#if defined(ARM_NEON_ADLER32) && !defined(__aarch64__) && !defined(_M_ARM64) /* Compatibility shim for the _high family of functions */ #define vmull_high_u8(a, b) vmull_u8(vget_high_u8(a), vget_high_u8(b)) #define vmlal_high_u8(a, b, c) vmlal_u8(a, vget_high_u8(b), vget_high_u8(c)) From facce4981c60ef178cf0d718f7a606627eb4d2f3 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Wed, 17 Aug 2022 18:13:39 +0500 Subject: [PATCH 472/798] Fix build as subproject. Signed-off-by: Vladislav Shchapov --- test/CMakeLists.txt | 12 ++++++------ test/benchmarks/CMakeLists.txt | 12 ++++++------ test/cmake/test-tools.cmake | 12 ++++++------ test/fuzz/CMakeLists.txt | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 29658422a1..51d1cf0840 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required(VERSION 3.5.1) macro(configure_test_executable target) - target_include_directories(${target} PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}) - set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + target_include_directories(${target} PRIVATE ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}) + set_target_properties(${target} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) if(NOT WITH_GZFILEOP) target_compile_definitions(${target} PRIVATE -DWITH_GZFILEOP) target_sources(${target} PRIVATE ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) @@ -49,19 +49,19 @@ add_executable(infcover infcover.c) configure_test_executable(infcover) target_link_libraries(infcover zlib) if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) - target_sources(infcover PRIVATE ${CMAKE_SOURCE_DIR}/inftrees.c) + target_sources(infcover PRIVATE ${PROJECT_SOURCE_DIR}/inftrees.c) endif() add_test(NAME infcover COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -add_executable(makefixed ${CMAKE_SOURCE_DIR}/tools/makefixed.c ${CMAKE_SOURCE_DIR}/inftrees.c) +add_executable(makefixed ${PROJECT_SOURCE_DIR}/tools/makefixed.c ${PROJECT_SOURCE_DIR}/inftrees.c) configure_test_executable(makefixed) set(MAKEFIXED_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -add_executable(maketrees ${CMAKE_SOURCE_DIR}/tools/maketrees.c ${CMAKE_SOURCE_DIR}/trees.c ${CMAKE_SOURCE_DIR}/zutil.c) +add_executable(maketrees ${PROJECT_SOURCE_DIR}/tools/maketrees.c ${PROJECT_SOURCE_DIR}/trees.c ${PROJECT_SOURCE_DIR}/zutil.c) configure_test_executable(maketrees) set(MAKETREES_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -add_executable(makecrct ${CMAKE_SOURCE_DIR}/tools/makecrct.c) +add_executable(makecrct ${PROJECT_SOURCE_DIR}/tools/makecrct.c) configure_test_executable(makecrct) set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index e6eaa352b0..bfd4b081af 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -32,8 +32,8 @@ add_executable(benchmark_zlib ) target_include_directories(benchmark_zlib PRIVATE - ${CMAKE_SOURCE_DIR} - ${CMAKE_BINARY_DIR} + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} ${benchmark_SOURCE_DIR}/benchmark/include) target_link_libraries(benchmark_zlib zlibstatic benchmark::benchmark) @@ -77,15 +77,15 @@ if(WITH_BENCHMARK_APPS) target_link_libraries(benchmark_zlib_apps_alt libpng.a ${ZLIB_ALT_LIB} benchmark::benchmark) target_compile_definitions(benchmark_zlib_apps_alt PRIVATE BUILD_ALT=1) target_include_directories(benchmark_zlib_apps_alt PRIVATE - ${CMAKE_SOURCE_DIR} - ${CMAKE_BINARY_DIR} + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} ${PNG_INCLUDE_DIR} ${benchmark_SOURCE_DIR}/benchmark/include) endif() target_include_directories(benchmark_zlib_apps PRIVATE - ${CMAKE_SOURCE_DIR} - ${CMAKE_BINARY_DIR} + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} ${PNG_INCLUDE_DIR} ${benchmark_SOURCE_DIR}/benchmark/include) diff --git a/test/cmake/test-tools.cmake b/test/cmake/test-tools.cmake index ce9a3ff2c7..afe4835d89 100644 --- a/test/cmake/test-tools.cmake +++ b/test/cmake/test-tools.cmake @@ -37,8 +37,8 @@ add_test(NAME switchlevels-help add_test(NAME makecrct COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_BINARY_DIR}/Testing/Temporary/crc32_braid_tbl._h - -DCOMPARE=${CMAKE_SOURCE_DIR}/crc32_braid_tbl.h + -DOUTPUT=${PROJECT_BINARY_DIR}/Testing/Temporary/crc32_braid_tbl._h + -DCOMPARE=${PROJECT_SOURCE_DIR}/crc32_braid_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -46,8 +46,8 @@ add_test(NAME makecrct add_test(NAME makefixed COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKEFIXED_COMMAND}" - -DOUTPUT=${CMAKE_BINARY_DIR}/Testing/Temporary/inffixed_tbl._h - -DCOMPARE=${CMAKE_SOURCE_DIR}/inffixed_tbl.h + -DOUTPUT=${PROJECT_BINARY_DIR}/Testing/Temporary/inffixed_tbl._h + -DCOMPARE=${PROJECT_SOURCE_DIR}/inffixed_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -55,7 +55,7 @@ add_test(NAME makefixed add_test(NAME maketrees COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKETREES_COMMAND}" - -DOUTPUT=${CMAKE_BINARY_DIR}/Testing/Temporary/trees_tbl._h - -DCOMPARE=${CMAKE_SOURCE_DIR}/trees_tbl.h + -DOUTPUT=${PROJECT_BINARY_DIR}/Testing/Temporary/trees_tbl._h + -DCOMPARE=${PROJECT_SOURCE_DIR}/trees_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt index c21f9c1ca4..9f14637425 100644 --- a/test/fuzz/CMakeLists.txt +++ b/test/fuzz/CMakeLists.txt @@ -37,7 +37,7 @@ foreach(FUZZER ${FUZZERS}) endif() if(ZLIB_ENABLE_TESTS) - file(GLOB FUZZER_TEST_FILES ${CMAKE_SOURCE_DIR}/*) + file(GLOB FUZZER_TEST_FILES ${PROJECT_SOURCE_DIR}/*) set(FUZZER_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ ${FUZZER_TEST_FILES}) add_test(NAME ${FUZZER} COMMAND ${FUZZER_COMMAND}) endif() From fe1da0694c0cb1a9fd11801ad635c6375e84b552 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Wed, 17 Aug 2022 21:06:37 +0500 Subject: [PATCH 473/798] Add add_subdirectory test. Signed-off-by: Vladislav Shchapov --- .github/workflows/cmake.yml | 7 +++++++ test/add-subdirectory-project/CMakeLists.txt | 13 +++++++++++++ test/add-subdirectory-project/main.c | 7 +++++++ 3 files changed, 27 insertions(+) create mode 100644 test/add-subdirectory-project/CMakeLists.txt create mode 100644 test/add-subdirectory-project/main.c diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index d9af5d4a95..9958d9e72d 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -54,6 +54,13 @@ jobs: codecov: ubuntu_gcc_osb cflags: -O3 + - name: Ubuntu GCC -O3 OSB add_subdirectory + os: ubuntu-latest + compiler: gcc + cxx-compiler: g++ + build-dir: ../build + build-src-dir: ../zlib-ng/test/add-subdirectory-project + - name: Ubuntu GCC -O1 No Unaligned UBSAN os: ubuntu-latest compiler: gcc diff --git a/test/add-subdirectory-project/CMakeLists.txt b/test/add-subdirectory-project/CMakeLists.txt new file mode 100644 index 0000000000..1b87005f72 --- /dev/null +++ b/test/add-subdirectory-project/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.5.1) + +project(zlib-ng-add-subdirecory-test C) + +include(CTest) + +set(BUILD_SHARED_LIBS OFF) +set(ZLIB_ENABLE_TESTS ON CACHE BOOL "Build test binaries" FORCE) + +add_subdirectory(../.. zlib-ng) + +add_executable(app main.c) +target_link_libraries(app zlibstatic) diff --git a/test/add-subdirectory-project/main.c b/test/add-subdirectory-project/main.c new file mode 100644 index 0000000000..638a35b1d3 --- /dev/null +++ b/test/add-subdirectory-project/main.c @@ -0,0 +1,7 @@ +#include +#include "zlib-ng.h" + +int main(void) { + printf("zlib-ng: %s\n", ZLIBNG_VERSION); + return 0; +} From 03c989a1059413a82db20dbd262e48b19c302f28 Mon Sep 17 00:00:00 2001 From: FrankXie Date: Wed, 24 Aug 2022 20:02:12 -0700 Subject: [PATCH 474/798] Add vcpkg installation instructions --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index ab12fa3431..9c118d07c2 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,18 @@ To install zlib-ng system-wide using the configure script: make install ``` +Alternatively, you can build and install zlib-ng using [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: + +```sh or powershell + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh # "./bootstrap-vcpkg.bat" for powershell + ./vcpkg integrate install + ./vcpkg install zlib-ng +``` + +The zlib-ng port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + Contributing ------------ From 8b7a69b6413fcbfaccd1e0d2ca6236a1e4b5cf44 Mon Sep 17 00:00:00 2001 From: FrankXie Date: Thu, 25 Aug 2022 19:16:00 -0700 Subject: [PATCH 475/798] format and add vcpkg headings. --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9c118d07c2..56555cf48d 100644 --- a/README.md +++ b/README.md @@ -161,14 +161,16 @@ To install zlib-ng system-wide using the configure script: make install ``` -Alternatively, you can build and install zlib-ng using [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: +### vcpkg + +Alternatively, you can build and install zlib-ng using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: ```sh or powershell - git clone https://github.com/Microsoft/vcpkg.git - cd vcpkg - ./bootstrap-vcpkg.sh # "./bootstrap-vcpkg.bat" for powershell - ./vcpkg integrate install - ./vcpkg install zlib-ng +git clone https://github.com/Microsoft/vcpkg.git +cd vcpkg +./bootstrap-vcpkg.sh # "./bootstrap-vcpkg.bat" for powershell +./vcpkg integrate install +./vcpkg install zlib-ng ``` The zlib-ng port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. From ad444f4715242991cf6829083d291496bc176a2f Mon Sep 17 00:00:00 2001 From: FrankXie Date: Thu, 25 Aug 2022 19:19:03 -0700 Subject: [PATCH 476/798] format Vcpkg --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56555cf48d..932214a88f 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ To install zlib-ng system-wide using the configure script: make install ``` -### vcpkg +### Vcpkg Alternatively, you can build and install zlib-ng using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: From 9309904fe79cd60599259022bd2aab2a3e1fb0d8 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 19 Aug 2022 15:00:21 +0300 Subject: [PATCH 477/798] If the extra field was larger than the space the user provided with inflateGetHeader(), and if multiple calls of inflate() delivered the extra header data, then there could be a buffer overflow of the provided space. This commit assures that provided space is not exceeded. See #1323. --- inflate.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/inflate.c b/inflate.c index 4bd9b938a2..6085fffac9 100644 --- a/inflate.c +++ b/inflate.c @@ -552,9 +552,11 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { if (copy) { if (state->head != NULL && state->head->extra != NULL) { len = state->head->extra_len - state->length; - memcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); + if (len < state->head->extra_max) { + memcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } } if ((state->flags & 0x0200) && (state->wrap & 4)) { state->check = PREFIX(crc32)(state->check, next, copy); From 5d9c5a546a69f1c1d83635746274f94d5c4c6c70 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Fri, 19 Aug 2022 16:33:59 +0500 Subject: [PATCH 478/798] Add CVE-2022-37434 test. Signed-off-by: Vladislav Shchapov --- test/infcover.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/infcover.c b/test/infcover.c index 63f5b3a29a..6606d222a9 100644 --- a/test/infcover.c +++ b/test/infcover.c @@ -669,6 +669,10 @@ static void cover_fast(void) { Z_STREAM_END); } +static void cover_cve_2022_37434(void) { + inf("1f 8b 08 04 61 62 63 64 61 62 52 51 1f 8b 08 04 61 62 63 64 61 62 52 51 1f 8b 08 04 61 62 63 64 61 62 52 51 1f 8b 08 04 61 62 63 64 61 62 52 51", "wtf", 13, 47, 12, Z_OK); +} + int main(void) { fprintf(stderr, "%s\n", zVersion()); cover_support(); @@ -677,5 +681,6 @@ int main(void) { cover_inflate(); cover_trees(); cover_fast(); + cover_cve_2022_37434(); return 0; } From ce01b1e41da298334f8214389cc9369540a7560f Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Mon, 29 Aug 2022 10:50:05 +0300 Subject: [PATCH 479/798] Fix wine32 dependencies for MinGW i686. * Downgrade broken libgd3 --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9958d9e72d..c81f47a3df 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -266,7 +266,7 @@ jobs: - name: Ubuntu MinGW i686 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake - packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.34-7 libpcre2-8-0:i386=10.34-7 libodbc1=2.3.6-0.1build1 libodbc1:i386=2.3.6-0.1build1 + packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.34-7 libpcre2-8-0:i386=10.34-7 libodbc1=2.3.6-0.1build1 libodbc1:i386=2.3.6-0.1build1 libwine:i386=5.0-3ubuntu1 libgphoto2-6:i386=2.5.25-0ubuntu0.1 libsane:i386=1.0.29-0ubuntu5.2 libgd3=2.2.5-5.2ubuntu2.1 libgd3:i386=2.2.5-5.2ubuntu2.1 ldflags: -static codecov: ubuntu_gcc_mingw_i686 # Limit parallel test jobs to prevent wine errors From 8353094a7bde4b7f626d84aabf7a0149724e786d Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 11 Sep 2022 18:57:02 +0300 Subject: [PATCH 480/798] Fix build failure introduced by 8df665005952cdbe7dc995d409ffe4f861e7a83e * We need absolute path for libz.a --- .github/workflows/link.yml | 2 +- test/CMakeLists.txt | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml index 806a934112..0ac4f5cff4 100644 --- a/.github/workflows/link.yml +++ b/.github/workflows/link.yml @@ -21,7 +21,7 @@ jobs: run: cmake --build zlib/build --config Release - name: Generate project files (native) - run: cmake -S . -B native -DZLIB_COMPAT=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_LIBRARIES=../zlib/build/libz.a -DZLIB_INCLUDE_DIR=../zlib/build + run: cmake -S . -B native -DZLIB_COMPAT=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_LIBRARIES=../zlib/build/libz.a -DZLIB_INCLUDE_DIR="../zlib/build;../zlib" - name: Compile source code (native) run: cmake --build native --config Release diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 51d1cf0840..ad002d9cef 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -180,14 +180,24 @@ else() -fsanitize-memory-track-origins) endif() - if(NOT ZLIB_COMPAT AND DEFINED ZLIB_INCLUDE_DIR AND DEFINED ZLIB_LIBRARIES) + if(NOT ZLIB_COMPAT AND DEFINED ZLIB_LIBRARIES AND DEFINED ZLIB_INCLUDE_DIR) + if(NOT IS_ABSOLUTE ${ZLIB_LIBRARIES}) + get_filename_component(ZLIB_ABSOLUTE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/${ZLIB_LIBRARIES}" + ABSOLUTE) + else() + set(ZLIB_ABSOLUTE_PATH ${ZLIB_LIBRARIES}) + endif() + + add_library(external_zlib STATIC IMPORTED) + set_property(TARGET external_zlib PROPERTY IMPORTED_LOCATION ${ZLIB_ABSOLUTE_PATH}) message(STATUS "Added dual linking tests against zlib") message(STATUS " Zlib include dir: ${ZLIB_INCLUDE_DIR}") - message(STATUS " Zlib libraries: ${ZLIB_LIBRARIES}") + message(STATUS " Zlib libraries: ${ZLIB_ABSOLUTE_PATH}") target_sources(gtest_zlib PRIVATE test_compress_dual.cc) target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIR}) - target_link_libraries(gtest_zlib ${ZLIB_LIBRARIES}) + target_link_libraries(gtest_zlib external_zlib) endif() target_link_libraries(gtest_zlib zlibstatic GTest::GTest) From 2d110b17b815016b5419592b7484ae9affb6fe68 Mon Sep 17 00:00:00 2001 From: Dougall Johnson Date: Mon, 22 Aug 2022 10:57:39 +1000 Subject: [PATCH 481/798] Inflate: Increase max root table sizes to 10 and 9 This increases the size of the `codes` array by 1920 bytes (33%), but improves performance a little. Root table size is still limited by the maximum code length in use, so tiny files typically see no change to table-building time, as they don't use longer codes. --- infback.c | 6 +++--- inflate.c | 6 +++--- inftrees.h | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/infback.c b/infback.c index 200997c467..f56db8e86d 100644 --- a/infback.c +++ b/infback.c @@ -329,18 +329,18 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in } /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h + values here (10 and 9) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (const code *)(state->next); - state->lenbits = 9; + state->lenbits = 10; ret = zng_inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { SET_BAD("invalid literal/lengths set"); break; } state->distcode = (const code *)(state->next); - state->distbits = 6; + state->distbits = 9; ret = zng_inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { diff --git a/inflate.c b/inflate.c index 6085fffac9..e109182fd3 100644 --- a/inflate.c +++ b/inflate.c @@ -820,18 +820,18 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } /* build code tables -- note: do not change the lenbits or distbits - values here (9 and 6) without reading the comments in inftrees.h + values here (10 and 9) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; state->lencode = (const code *)(state->next); - state->lenbits = 9; + state->lenbits = 10; ret = zng_inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); if (ret) { SET_BAD("invalid literal/lengths set"); break; } state->distcode = (const code *)(state->next); - state->distbits = 6; + state->distbits = 9; ret = zng_inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); if (ret) { diff --git a/inftrees.h b/inftrees.h index bb6274a128..eeae9c6ac4 100644 --- a/inftrees.h +++ b/inftrees.h @@ -39,17 +39,17 @@ typedef struct { */ /* Maximum size of the dynamic table. The maximum number of code structures is - 1444, which is the sum of 852 for literal/length codes and 592 for distance + 1924, which is the sum of 1332 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distributions. The arguments to that program are the number of symbols, the initial root table size, and the - maximum bit length of a code. "enough 286 9 15" for literal/length codes - returns returns 852, and "enough 30 6 15" for distance codes returns 592. - The initial root table size (9 or 6) is found in the fifth argument of the + maximum bit length of a code. "enough 286 10 15" for literal/length codes + returns returns 1332, and "enough 30 9 15" for distance codes returns 592. + The initial root table size (10 or 9) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ -#define ENOUGH_LENS 852 +#define ENOUGH_LENS 1332 #define ENOUGH_DISTS 592 #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) From 1a96258117775492378a4e62d070ade203d2aa77 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 11 Sep 2022 15:35:24 -0400 Subject: [PATCH 482/798] Pin Google Benchmark to v1.7.0 since master tag has been removed. --- test/benchmarks/CMakeLists.txt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index bfd4b081af..cfcb360b5c 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -12,13 +12,23 @@ find_package(benchmark QUIET) if(NOT benchmark_FOUND) # Fetch google benchmark source code from official repository set(BENCHMARK_ENABLE_TESTING OFF) + + # Allow specifying alternative Google benchmark repository + if(NOT DEFINED GBENCHMARK_REPOSITORY) + set(GBENCHMARK_REPOSITORY https://github.com/google/benchmark.git) + endif() + if(NOT DEFINED GBENCHMARK_TAG) + set(GBENCHMARK_TAG v1.7.0) + endif() + FetchContent_Declare(benchmark - GIT_REPOSITORY https://github.com/google/benchmark.git) + GIT_REPOSITORY ${GBENCHMARK_REPOSITORY} + GIT_TAG ${GBENCHMARK_TAG}) FetchContent_GetProperties(benchmark) if(NOT benchmark_POPULATED) FetchContent_Populate(benchmark) - add_subdirectory(${benchmark_SOURCE_DIR} ${benchmark_BINARY_DIR}) + add_subdirectory(${benchmark_SOURCE_DIR} ${benchmark_BINARY_DIR} EXCLUDE_FROM_ALL) endif() endif() @@ -31,6 +41,7 @@ add_executable(benchmark_zlib benchmark_slidehash.cc ) +target_compile_definitions(benchmark_zlib PRIVATE -DBENCHMARK_STATIC_DEFINE) target_include_directories(benchmark_zlib PRIVATE ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR} From f01072809baf988c2492283350241f11344c970a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 11 Sep 2022 15:36:33 -0400 Subject: [PATCH 483/798] Fixed undefined variable random_ints in adler32_copy benchmarks. --- test/benchmarks/benchmark_adler32_copy.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index 81fdc4a0c6..2cc18015ce 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -36,7 +36,8 @@ class adler32_copy: public benchmark::Fixture { * control the _consistency_ of the results */ random_ints_src = (uint32_t *)zng_alloc(MAX_RANDOM_INTS_SIZE); random_ints_dst = (uint32_t *)zng_alloc(MAX_RANDOM_INTS_SIZE); - assert(random_ints != NULL); + assert(random_ints_src != NULL); + assert(random_ints_dst != NULL); for (int32_t i = 0; i < MAX_RANDOM_INTS; i++) { random_ints_src[i] = rand(); From 34220d6400548a336ecb0d0645dcf0e0082bbac4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 11 Sep 2022 15:36:59 -0400 Subject: [PATCH 484/798] Fixed casting warning from uint64_t to size_t in adler32_copy benchmarks --- test/benchmarks/benchmark_adler32_copy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index 2cc18015ce..71ac72f295 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -77,7 +77,7 @@ class adler32_copy: public benchmark::Fixture { } \ Bench(state, [](uint32_t init_sum, unsigned char *dst, \ const uint8_t *buf, uint64_t len) -> uint32_t { \ - memcpy(dst, buf, len); \ + memcpy(dst, buf, (size_t)len); \ return fptr(init_sum, buf, len); \ }); \ } \ From ece74eec32cbd1da4fddf772757ece3844b49c94 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Tue, 6 Sep 2022 13:11:16 -0700 Subject: [PATCH 485/798] msvc/armv7: disable crc32_acle msvc compiler targeting 32bit arm supports only armv7 and lacks these intrinsics --- cmake/detect-intrinsics.cmake | 42 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 743af4e87c..e1b410337f 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -2,29 +2,35 @@ # Licensed under the Zlib license, see LICENSE.md for details macro(check_acle_compiler_flag) - if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") - if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) - set(ACLEFLAG "-march=armv8-a+crc" CACHE INTERNAL "Compiler option to enable ACLE support") + if(MSVC) + # Both ARM and ARM64-targeting msvc support intrinsics, but + # ARM msvc is missing some intrinsics introduced with ARMv8, e.g. crc32 + if(MSVC_C_ARCHITECTURE_ID STREQUAL "ARM64") + set(HAVE_ACLE_FLAG TRUE) + endif() + else() + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) + set(ACLEFLAG "-march=armv8-a+crc" CACHE INTERNAL "Compiler option to enable ACLE support") + endif() endif() - elseif(MSVC) - set(HAVE_ACLE_FLAG TRUE) - endif() - # Check whether compiler supports ACLE flag - set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG}") - check_c_source_compiles( - "int main() { return 0; }" - HAVE_ACLE_FLAG FAIL_REGEX "not supported") - if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) - set(ACLEFLAG "-march=armv8-a+crc+simd" CACHE INTERNAL "Compiler option to enable ACLE support" FORCE) # Check whether compiler supports ACLE flag - set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG}") check_c_source_compiles( "int main() { return 0; }" - HAVE_ACLE_FLAG2 FAIL_REGEX "not supported") - set(HAVE_ACLE_FLAG ${HAVE_ACLE_FLAG2} CACHE INTERNAL "Have compiler option to enable ACLE intrinsics" FORCE) - unset(HAVE_ACLE_FLAG2 CACHE) # Don't cache this internal variable + HAVE_ACLE_FLAG FAIL_REGEX "not supported") + if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) + set(ACLEFLAG "-march=armv8-a+crc+simd" CACHE INTERNAL "Compiler option to enable ACLE support" FORCE) + # Check whether compiler supports ACLE flag + set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG}") + check_c_source_compiles( + "int main() { return 0; }" + HAVE_ACLE_FLAG2 FAIL_REGEX "not supported") + set(HAVE_ACLE_FLAG ${HAVE_ACLE_FLAG2} CACHE INTERNAL "Have compiler option to enable ACLE intrinsics" FORCE) + unset(HAVE_ACLE_FLAG2 CACHE) # Don't cache this internal variable + endif() + set(CMAKE_REQUIRED_FLAGS) endif() - set(CMAKE_REQUIRED_FLAGS) endmacro() macro(check_avx512_intrinsics) From 6057002d4832457b86eb38d7ae95d661aeeca464 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 11 Sep 2022 16:15:10 +0300 Subject: [PATCH 486/798] [Compat] Don't use uint32_t for z_crc_t * We don't include stdint.h as it must be included before stdarg.h and other headers might include stdarg.h before us See #1342 --- zconf.h.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zconf.h.in b/zconf.h.in index c82a8ad009..82ee080321 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -111,7 +111,7 @@ # define ZEXPORTVA Z_EXPORTVA #endif -/* Fallback for something that includes us. */ +/* Legacy zlib typedefs for backwards compatibility. Don't assume stdint.h is defined. */ typedef unsigned char Byte; typedef Byte Bytef; @@ -127,7 +127,7 @@ typedef void const *voidpc; typedef void *voidpf; typedef void *voidp; -typedef uint32_t z_crc_t; +typedef unsigned int z_crc_t; #ifdef HAVE_UNISTD_H /* may be set to #if 1 by configure/cmake/etc */ # define Z_HAVE_UNISTD_H From d38dd9240f2de436769c9ce9549e15cb0d0cfd32 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Sat, 17 Sep 2022 15:32:29 +0200 Subject: [PATCH 487/798] IBM Z DFLTCC: Fix updating strm.adler with inflate() inflate() does not update strm.adler with DFLTCC. Add a missing assignment to dfltcc_inflate() to fix this. Note that deflate() is not affected. Also add a test to prevent regressions. --- arch/s390/dfltcc_inflate.c | 2 +- test/test_inflate_adler32.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/s390/dfltcc_inflate.c b/arch/s390/dfltcc_inflate.c index 7a422d97e4..b7ecbe275c 100644 --- a/arch/s390/dfltcc_inflate.c +++ b/arch/s390/dfltcc_inflate.c @@ -115,7 +115,7 @@ dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, i state->bits = param->sbb; state->whave = param->hl; state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1); - state->check = state->flags ? ZSWAP32(param->cv) : param->cv; + strm->adler = state->check = state->flags ? ZSWAP32(param->cv) : param->cv; if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) { /* Report an error if stream is corrupted */ state->mode = BAD; diff --git a/test/test_inflate_adler32.cc b/test/test_inflate_adler32.cc index e17cf6b795..fb78bb1bfc 100644 --- a/test/test_inflate_adler32.cc +++ b/test/test_inflate_adler32.cc @@ -41,6 +41,8 @@ TEST(inflate, adler32) { err = PREFIX(inflate)(&strm, Z_NO_FLUSH); EXPECT_EQ(err, Z_STREAM_END); + EXPECT_EQ(strm.adler, 0x6b931030); + err = PREFIX(inflateEnd)(&strm); EXPECT_EQ(err, Z_OK); From fb8af972f3df20b3f1e2b00c9d2895cb1981abc5 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Wed, 14 Sep 2022 21:26:32 +0200 Subject: [PATCH 488/798] Remove errant space in cmake posix specifier --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ca63a30f4..65827c227b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -333,7 +333,7 @@ check_function_exists(strerror HAVE_STRERROR) if(NOT HAVE_STRERROR) add_definitions(-DNO_STRERROR) endif() -set(CMAKE_REQUIRED_DEFINITIONS -D _POSIX_C_SOURCE=200112L) +set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_C_SOURCE=200112L) check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN) if(HAVE_POSIX_MEMALIGN) add_definitions(-DHAVE_POSIX_MEMALIGN) From 7ef285b9b1ecf4f992c61392d37449543e43e58c Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Wed, 14 Sep 2022 21:27:48 +0200 Subject: [PATCH 489/798] Don't try to link gz* objects twice. --- Makefile.in | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Makefile.in b/Makefile.in index 4e25ef9962..f068184e3a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -254,45 +254,45 @@ ifneq ($(SHAREDLIB),$(SHAREDTARGET)) endif endif -example$(EXE): example.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) +example$(EXE): example.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -minigzip$(EXE): minigzip.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) +minigzip$(EXE): minigzip.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -minigzipsh$(EXE): minigzip.o $(OBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) +minigzipsh$(EXE): minigzip.o $(SHAREDTARGET) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(SHAREDLIB) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif examplesh$(EXE): example.o $(PIC_TESTOBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(PIC_TESTOBJG) $(SHAREDLIB) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -makefixed$(EXE): makefixed.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makefixed.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) +makefixed$(EXE): makefixed.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makefixed.o $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -maketrees$(EXE): maketrees.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ maketrees.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) +maketrees$(EXE): maketrees.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ maketrees.o $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -makecrct$(EXE): makecrct.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makecrct.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) +makecrct$(EXE): makecrct.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makecrct.o $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif From 962b3dd2ff809fbd9ceb20a919939937389faa0f Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Wed, 14 Sep 2022 21:29:41 +0200 Subject: [PATCH 490/798] Make visibility tests run the same way as the other tests. Fix indentation. --- configure | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 4e73a22dcc..2cd8186248 100755 --- a/configure +++ b/configure @@ -581,16 +581,16 @@ if ($CC -c $CFLAGS $test.c) 2>/dev/null; then } echo - using any output from compiler to indicate an error >> configure.log else -try() -{ - show $* - ( $* ) >> configure.log 2>&1 - ret=$? - if test $ret -ne 0; then - echo "(exit code $ret)" >> configure.log - fi - return $ret -} + try() + { + show $* + ( $* ) >> configure.log 2>&1 + ret=$? + if test $ret -ne 0; then + echo "(exit code $ret)" >> configure.log + fi + return $ret + } fi tryboth() @@ -924,7 +924,7 @@ if test "$gcc" -eq 1; then int Z_INTERNAL foo; int main() { return 0; } EOF - if tryboth $CC -c $CFLAGS $test.c; then + if try $CC $CFLAGS $test.c; then CFLAGS="$CFLAGS -DHAVE_VISIBILITY_HIDDEN" SFLAGS="$SFLAGS -DHAVE_VISIBILITY_HIDDEN" echo >> configure.log @@ -943,7 +943,7 @@ if test "$gcc" -eq 1; then int Z_INTERNAL foo; int main() { return 0; } EOF - if tryboth $CC -c $CFLAGS $test.c; then + if try $CC $CFLAGS $test.c; then CFLAGS="$CFLAGS -DHAVE_VISIBILITY_INTERNAL" SFLAGS="$SFLAGS -DHAVE_VISIBILITY_INTERNAL" echo >> configure.log From 6490b70c487dadb156f3622eb57785589fc218eb Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Wed, 14 Sep 2022 21:30:43 +0200 Subject: [PATCH 491/798] vpclmulqdq compilation fails without avx512f also enabled --- cmake/detect-intrinsics.cmake | 2 +- configure | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index e1b410337f..d2b42ca142 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -230,7 +230,7 @@ endmacro() macro(check_vpclmulqdq_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) - set(VPCLMULFLAG "-mvpclmulqdq") + set(VPCLMULFLAG "-mvpclmulqdq -mavx512f") endif() endif() # Check whether compiler supports VPCLMULQDQ intrinsics diff --git a/configure b/configure index 2cd8186248..c2196fccae 100755 --- a/configure +++ b/configure @@ -114,7 +114,7 @@ ssse3flag="-mssse3" sse41flag="-msse4.1" sse42flag="-msse4.2" pclmulflag="-mpclmul" -vpclmulflag="-mvpclmulqdq" +vpclmulflag="-mvpclmulqdq -mavx512f" acleflag= neonflag= noltoflag="-fno-lto" From 9b9be8b979e06418d32f9a04d2f0e0e8fc529409 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 25 Sep 2022 17:59:44 +0200 Subject: [PATCH 492/798] Remove unused tryboth() function --- configure | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/configure b/configure index c2196fccae..ea4ac3977c 100755 --- a/configure +++ b/configure @@ -593,18 +593,6 @@ else } fi -tryboth() -{ - show $* - got=$(( $* ) 2>&1) - ret=$? - printf %s "$got" >> configure.log - if test $ret -ne 0; then - return $ret - fi - test "$got" = "" -} - cat > $test.c << EOF int foo() { return 0; } EOF From 5b46217d458a144742937a370b2cd2dd0f2fd92e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 28 Sep 2022 09:38:06 -0700 Subject: [PATCH 493/798] Use short decompress option name for gzip compatibility. #1347 Long option names in BusyBoxy is an optional feature, so use short option names by default. --- test/cmake/compress-and-verify.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cmake/compress-and-verify.cmake b/test/cmake/compress-and-verify.cmake index 856f2cb353..e79c50c4f0 100644 --- a/test/cmake/compress-and-verify.cmake +++ b/test/cmake/compress-and-verify.cmake @@ -173,7 +173,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") endif() # Check gzip can decompress our compressed output - set(GZ_DECOMPRESS_COMMAND ${GZIP} --decompress) + set(GZ_DECOMPRESS_COMMAND ${GZIP} -d) message(STATUS "Gzip decompress ${GZ_DECOMPRESS_COMMAND}") message(STATUS " Input: ${OUTPUT_BASE}.gz") From 2fb28557351b3e394dce0be44b364ca95d7e47dc Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Sun, 25 Sep 2022 20:11:14 +0100 Subject: [PATCH 494/798] Check that the OS supports saving the YMM registers before enabling AVX2 --- arch/x86/x86_features.c | 44 +++++++++++++++++++++++++++++++++++++---- arch/x86/x86_features.h | 2 ++ 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index 72ef885e82..b8ab69cefe 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -28,6 +28,8 @@ Z_INTERNAL int x86_cpu_has_sse42; Z_INTERNAL int x86_cpu_has_pclmulqdq; Z_INTERNAL int x86_cpu_has_vpclmulqdq; Z_INTERNAL int x86_cpu_has_tzcnt; +Z_INTERNAL int x86_cpu_has_os_save_ymm; +Z_INTERNAL int x86_cpu_has_os_save_zmm; static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { #ifdef _MSC_VER @@ -57,6 +59,16 @@ static void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigne #endif } +static uint64_t xgetbv(unsigned int xcr) { +#ifdef _MSC_VER + return _xgetbv(xcr); +#else + uint32_t eax, edx; + __asm__ ( ".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(xcr)); + return (uint64_t)(edx) << 32 | eax; +#endif +} + void Z_INTERNAL x86_check_features(void) { unsigned eax, ebx, ecx, edx; unsigned maxbasic; @@ -70,20 +82,44 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_has_sse42 = ecx & 0x100000; x86_cpu_has_pclmulqdq = ecx & 0x2; + if (ecx & 0x08000000) { + uint64_t xfeature = xgetbv(0); + + x86_cpu_has_os_save_ymm = ((xfeature & 0x06) == 0x06); + x86_cpu_has_os_save_zmm = ((xfeature & 0xe6) == 0xe6); + } else { + x86_cpu_has_os_save_ymm = 0; + x86_cpu_has_os_save_zmm = 0; + } + if (maxbasic >= 7) { cpuidex(7, 0, &eax, &ebx, &ecx, &edx); // check BMI1 bit // Reference: https://software.intel.com/sites/default/files/article/405250/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf x86_cpu_has_tzcnt = ebx & 0x8; - // check AVX2 bit - x86_cpu_has_avx2 = ebx & 0x20; - x86_cpu_has_avx512 = ebx & 0x00010000; - x86_cpu_has_avx512vnni = ecx & 0x800; x86_cpu_has_vpclmulqdq = ecx & 0x400; + + // check AVX2 bit if the OS supports saving YMM registers + if (x86_cpu_has_os_save_ymm) { + x86_cpu_has_avx2 = ebx & 0x20; + } else { + x86_cpu_has_avx2 = 0; + } + + // check AVX512 bits if the OS supports saving ZMM registers + if (x86_cpu_has_os_save_zmm) { + x86_cpu_has_avx512 = ebx & 0x00010000; + x86_cpu_has_avx512vnni = ecx & 0x800; + } else { + x86_cpu_has_avx512 = 0; + x86_cpu_has_avx512vnni = 0; + } } else { x86_cpu_has_tzcnt = 0; x86_cpu_has_avx2 = 0; + x86_cpu_has_avx512 = 0; + x86_cpu_has_avx512vnni = 0; x86_cpu_has_vpclmulqdq = 0; } } diff --git a/arch/x86/x86_features.h b/arch/x86/x86_features.h index 97630ab6e6..3e0d17f063 100644 --- a/arch/x86/x86_features.h +++ b/arch/x86/x86_features.h @@ -16,6 +16,8 @@ extern int x86_cpu_has_sse42; extern int x86_cpu_has_pclmulqdq; extern int x86_cpu_has_vpclmulqdq; extern int x86_cpu_has_tzcnt; +extern int x86_cpu_has_os_save_ymm; +extern int x86_cpu_has_os_save_zmm; void Z_INTERNAL x86_check_features(void); From 582a2b5528ce8c259f77464b262e30a48ba1ed97 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Sun, 25 Sep 2022 21:42:36 +0100 Subject: [PATCH 495/798] Use static inline in x86_features.c --- arch/x86/x86_features.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index b8ab69cefe..0de8349941 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -31,7 +31,7 @@ Z_INTERNAL int x86_cpu_has_tzcnt; Z_INTERNAL int x86_cpu_has_os_save_ymm; Z_INTERNAL int x86_cpu_has_os_save_zmm; -static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { +static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { #ifdef _MSC_VER unsigned int registers[4]; __cpuid((int *)registers, info); @@ -45,7 +45,7 @@ static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigne #endif } -static void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { +static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { #ifdef _MSC_VER unsigned int registers[4]; __cpuidex((int *)registers, info, subinfo); @@ -59,7 +59,7 @@ static void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigne #endif } -static uint64_t xgetbv(unsigned int xcr) { +static inline uint64_t xgetbv(unsigned int xcr) { #ifdef _MSC_VER return _xgetbv(xcr); #else From 9c839540ed522d10a7519d78881ca7666b042db6 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Thu, 29 Sep 2022 19:55:34 +0100 Subject: [PATCH 496/798] Move the NEON compatibility defines into a separate file --- arch/arm/adler32_neon.c | 7 +---- arch/arm/chunkset_neon.c | 6 +--- arch/arm/compare256_neon.c | 11 ++++--- arch/arm/neon_intrins.h | 59 ++++++++++++++++++++++++++++++++++++++ arch/arm/slide_hash_neon.c | 7 +---- fallback_builtins.h | 55 ----------------------------------- 6 files changed, 67 insertions(+), 78 deletions(-) create mode 100644 arch/arm/neon_intrins.h diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index 9b55ca0c08..9b9d65ddd4 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -6,14 +6,9 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ #ifdef ARM_NEON_ADLER32 -#ifdef _M_ARM64 -# include -#else -# include -#endif +#include "neon_intrins.h" #include "../../zbuild.h" #include "../../adler32_p.h" -#include "../../fallback_builtins.h" static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { static const uint16_t ALIGNED_(16) taps[64] = { diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 3b8d2c0010..2c64ce59e3 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -3,11 +3,7 @@ */ #ifdef ARM_NEON_CHUNKSET -#ifdef _M_ARM64 -# include -#else -# include -#endif +#include "neon_intrins.h" #include "../../zbuild.h" #include "../generic/chunk_permute_table.h" diff --git a/arch/arm/compare256_neon.c b/arch/arm/compare256_neon.c index 53a088cc00..7daeba411e 100644 --- a/arch/arm/compare256_neon.c +++ b/arch/arm/compare256_neon.c @@ -3,14 +3,13 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) -#ifdef _M_ARM64 -# include -#else -# include -#endif #include "../../zbuild.h" +#include "fallback_builtins.h" + +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +#include "neon_intrins.h" + static inline uint32_t compare256_neon_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; diff --git a/arch/arm/neon_intrins.h b/arch/arm/neon_intrins.h new file mode 100644 index 0000000000..5885779ee4 --- /dev/null +++ b/arch/arm/neon_intrins.h @@ -0,0 +1,59 @@ +#ifndef ARM_NEON_INTRINS_H +#define ARM_NEON_INTRINS_H + +#ifdef _M_ARM64 +# include +#else +# include +#endif + +#if defined(ARM_NEON_ADLER32) && !defined(__aarch64__) && !defined(_M_ARM64) +/* Compatibility shim for the _high family of functions */ +#define vmull_high_u8(a, b) vmull_u8(vget_high_u8(a), vget_high_u8(b)) +#define vmlal_high_u8(a, b, c) vmlal_u8(a, vget_high_u8(b), vget_high_u8(c)) +#define vmlal_high_u16(a, b, c) vmlal_u16(a, vget_high_u16(b), vget_high_u16(c)) +#define vaddw_high_u8(a, b) vaddw_u8(a, vget_high_u8(b)) +#endif + +#ifdef ARM_NEON_SLIDEHASH + +#define vqsubq_u16_x4_x1(out, a, b) do { \ + out.val[0] = vqsubq_u16(a.val[0], b); \ + out.val[1] = vqsubq_u16(a.val[1], b); \ + out.val[2] = vqsubq_u16(a.val[2], b); \ + out.val[3] = vqsubq_u16(a.val[3], b); \ +} while (0) + +/* Have to check for hard float ABI on GCC/clang, but not + * on MSVC (we don't compile for the soft float ABI on windows) + */ +#if !defined(ARM_NEON_HASLD4) && (defined(__ARM_FP) || defined(_MSC_VER)) + +static inline uint16x8x4_t vld1q_u16_x4(uint16_t *a) { + uint16x8x4_t ret = (uint16x8x4_t) {{ + vld1q_u16(a), + vld1q_u16(a+8), + vld1q_u16(a+16), + vld1q_u16(a+24)}}; + return ret; +} + +static inline uint8x16x4_t vld1q_u8_x4(uint8_t *a) { + uint8x16x4_t ret = (uint8x16x4_t) {{ + vld1q_u8(a), + vld1q_u8(a+16), + vld1q_u8(a+32), + vld1q_u8(a+48)}}; + return ret; +} + +static inline void vst1q_u16_x4(uint16_t *p, uint16x8x4_t a) { + vst1q_u16(p, a.val[0]); + vst1q_u16(p + 8, a.val[1]); + vst1q_u16(p + 16, a.val[2]); + vst1q_u16(p + 24, a.val[3]); +} +#endif // HASLD4 check and hard float +#endif // ARM_NEON_SLIDEHASH + +#endif // include guard ARM_NEON_INTRINS_H diff --git a/arch/arm/slide_hash_neon.c b/arch/arm/slide_hash_neon.c index 8dc887379c..5bb4dc505c 100644 --- a/arch/arm/slide_hash_neon.c +++ b/arch/arm/slide_hash_neon.c @@ -9,14 +9,9 @@ */ #if defined(ARM_NEON_SLIDEHASH) -#ifdef _M_ARM64 -# include -#else -# include -#endif +#include "neon_intrins.h" #include "../../zbuild.h" #include "../../deflate.h" -#include "../../fallback_builtins.h" /* SIMD version of hash_chain rebase */ static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { diff --git a/fallback_builtins.h b/fallback_builtins.h index 3e58942078..32bb54dc6f 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -71,59 +71,4 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { #endif // __AVX2__ -#if defined(ARM_NEON_ADLER32) && !defined(__aarch64__) && !defined(_M_ARM64) -/* Compatibility shim for the _high family of functions */ -#define vmull_high_u8(a, b) vmull_u8(vget_high_u8(a), vget_high_u8(b)) -#define vmlal_high_u8(a, b, c) vmlal_u8(a, vget_high_u8(b), vget_high_u8(c)) -#define vmlal_high_u16(a, b, c) vmlal_u16(a, vget_high_u16(b), vget_high_u16(c)) -#define vaddw_high_u8(a, b) vaddw_u8(a, vget_high_u8(b)) -#endif - -#ifdef ARM_NEON_SLIDEHASH - -#define vqsubq_u16_x4_x1(out, a, b) do { \ - out.val[0] = vqsubq_u16(a.val[0], b); \ - out.val[1] = vqsubq_u16(a.val[1], b); \ - out.val[2] = vqsubq_u16(a.val[2], b); \ - out.val[3] = vqsubq_u16(a.val[3], b); \ -} while (0) - -/* Have to check for hard float ABI on GCC/clang, but not - * on MSVC (we don't compile for the soft float ABI on windows) - */ -#if !defined(ARM_NEON_HASLD4) && (defined(__ARM_FP) || defined(_MSC_VER)) - -#ifdef _M_ARM64 -# include -#else -# include -#endif - -static inline uint16x8x4_t vld1q_u16_x4(uint16_t *a) { - uint16x8x4_t ret = (uint16x8x4_t) {{ - vld1q_u16(a), - vld1q_u16(a+8), - vld1q_u16(a+16), - vld1q_u16(a+24)}}; - return ret; -} - -static inline uint8x16x4_t vld1q_u8_x4(uint8_t *a) { - uint8x16x4_t ret = (uint8x16x4_t) {{ - vld1q_u8(a), - vld1q_u8(a+16), - vld1q_u8(a+32), - vld1q_u8(a+48)}}; - return ret; -} - -static inline void vst1q_u16_x4(uint16_t *p, uint16x8x4_t a) { - vst1q_u16(p, a.val[0]); - vst1q_u16(p + 8, a.val[1]); - vst1q_u16(p + 16, a.val[2]); - vst1q_u16(p + 24, a.val[3]); -} -#endif // HASLD4 check and hard float -#endif // ARM_NEON_SLIDEHASH - #endif // include guard FALLBACK_BUILTINS_H From e8736aa54a8a5cc0150dae016985d2002080f51f Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Thu, 29 Sep 2022 21:45:39 +0100 Subject: [PATCH 497/798] Simplify feature checks in neon_intrins.h --- arch/arm/neon_intrins.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/arm/neon_intrins.h b/arch/arm/neon_intrins.h index 5885779ee4..be66800672 100644 --- a/arch/arm/neon_intrins.h +++ b/arch/arm/neon_intrins.h @@ -24,10 +24,9 @@ out.val[3] = vqsubq_u16(a.val[3], b); \ } while (0) -/* Have to check for hard float ABI on GCC/clang, but not - * on MSVC (we don't compile for the soft float ABI on windows) - */ -#if !defined(ARM_NEON_HASLD4) && (defined(__ARM_FP) || defined(_MSC_VER)) +#endif + +#if !defined(ARM_NEON_HASLD4) && (defined(ARM_NEON_ADLER32) || defined(ARM_NEON_SLIDEHASH)) static inline uint16x8x4_t vld1q_u16_x4(uint16_t *a) { uint16x8x4_t ret = (uint16x8x4_t) {{ @@ -53,7 +52,6 @@ static inline void vst1q_u16_x4(uint16_t *p, uint16x8x4_t a) { vst1q_u16(p + 16, a.val[2]); vst1q_u16(p + 24, a.val[3]); } -#endif // HASLD4 check and hard float -#endif // ARM_NEON_SLIDEHASH +#endif // HASLD4 check #endif // include guard ARM_NEON_INTRINS_H From d053b6f37c2f75bab5f7bc33411fd5f09444f8bb Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Sat, 1 Oct 2022 16:01:52 +0100 Subject: [PATCH 498/798] Fix compiler warnings when ARM_NEON_HASLD4 is undefined --- arch/arm/neon_intrins.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/neon_intrins.h b/arch/arm/neon_intrins.h index be66800672..06e310c9f9 100644 --- a/arch/arm/neon_intrins.h +++ b/arch/arm/neon_intrins.h @@ -28,7 +28,7 @@ #if !defined(ARM_NEON_HASLD4) && (defined(ARM_NEON_ADLER32) || defined(ARM_NEON_SLIDEHASH)) -static inline uint16x8x4_t vld1q_u16_x4(uint16_t *a) { +static inline uint16x8x4_t vld1q_u16_x4(uint16_t const *a) { uint16x8x4_t ret = (uint16x8x4_t) {{ vld1q_u16(a), vld1q_u16(a+8), @@ -37,7 +37,7 @@ static inline uint16x8x4_t vld1q_u16_x4(uint16_t *a) { return ret; } -static inline uint8x16x4_t vld1q_u8_x4(uint8_t *a) { +static inline uint8x16x4_t vld1q_u8_x4(uint8_t const *a) { uint8x16x4_t ret = (uint8x16x4_t) {{ vld1q_u8(a), vld1q_u8(a+16), From 65c45b064a1b10683e8cbc425b4f4f32ef5017fa Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 5 Oct 2022 13:58:28 +0300 Subject: [PATCH 499/798] Fix memcpy() overflow in adler32_fold.c and crc32_fold.c * On 32-bit platforms, last parameter of memcpy() is limited to SSIZE_MAX, but is likely to overlap if used --- adler32_fold.c | 15 ++++++++++----- crc32_fold.c | 15 ++++++++++----- zbuild.h | 6 ++++++ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/adler32_fold.c b/adler32_fold.c index 66d63dd351..adaabe0210 100644 --- a/adler32_fold.c +++ b/adler32_fold.c @@ -7,14 +7,19 @@ #include "functable.h" #include "adler32_fold.h" +#include + Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { adler = functable.adler32(adler, src, len); - while (len > SIZE_MAX) { - memcpy(dst, src, SIZE_MAX); - dst += SIZE_MAX; - src += SIZE_MAX; - len -= SIZE_MAX; +/* Test that we don't try to copy more than actually fits in available address space */ +#if INTPTR_MAX > SSIZE_MAX + while (len > SSIZE_MAX) { + memcpy(dst, src, SSIZE_MAX); + dst += SSIZE_MAX; + src += SSIZE_MAX; + len -= SSIZE_MAX; } +#endif if (len) { memcpy(dst, src, (size_t)len); } diff --git a/crc32_fold.c b/crc32_fold.c index eb0aeeb761..b1011debd9 100644 --- a/crc32_fold.c +++ b/crc32_fold.c @@ -7,6 +7,8 @@ #include "crc32_fold.h" +#include + Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc) { crc->value = CRC32_INITIAL_VALUE; return crc->value; @@ -14,12 +16,15 @@ Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc) { Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len) { crc->value = functable.crc32(crc->value, src, len); - while (len > SIZE_MAX) { - memcpy(dst, src, SIZE_MAX); - dst += SIZE_MAX; - src += SIZE_MAX; - len -= SIZE_MAX; +/* Test that we don't try to copy more than actually fits in available address space */ +#if INTPTR_MAX > SSIZE_MAX + while (len > SSIZE_MAX) { + memcpy(dst, src, SSIZE_MAX); + dst += SSIZE_MAX; + src += SSIZE_MAX; + len -= SSIZE_MAX; } +#endif if (len) { memcpy(dst, src, (size_t)len); } diff --git a/zbuild.h b/zbuild.h index 10a7fd6b3d..510c5addb2 100644 --- a/zbuild.h +++ b/zbuild.h @@ -46,6 +46,12 @@ # else typedef long ssize_t; # endif + +# if defined(_WIN64) + #define SSIZE_MAX _I64_MAX +# else + #define SSIZE_MAX LONG_MAX +# endif #endif /* MS Visual Studio does not allow inline in C, only C++. From b57e10d316f0e5214979d5d206f2ef24b5b817fb Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sun, 2 Oct 2022 23:01:52 +0500 Subject: [PATCH 500/798] Fix AVX2 detect Signed-off-by: Vladislav Shchapov --- cmake/detect-intrinsics.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index d2b42ca142..20164c5bce 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -132,6 +132,8 @@ macro(check_avx2_intrinsics) if(NOT NATIVEFLAG) set(AVX2FLAG "-mavx2") endif() + elseif(MSVC) + set(AVX2FLAG "/arch:AVX2") endif() # Check whether compiler supports AVX2 intrinics set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG} ${NATIVEFLAG}") From 78284a439fcd530b22b2f64a8764c54904812c11 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Tue, 11 Oct 2022 18:12:16 +0500 Subject: [PATCH 501/798] Fix missing intrinsics (MSVS 2015, 2017) Signed-off-by: Vladislav Shchapov --- arch/x86/adler32_ssse3_p.h | 2 +- fallback_builtins.h | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/adler32_ssse3_p.h b/arch/x86/adler32_ssse3_p.h index ba914e1df5..0b7ddcf9da 100644 --- a/arch/x86/adler32_ssse3_p.h +++ b/arch/x86/adler32_ssse3_p.h @@ -12,7 +12,7 @@ #include static inline uint32_t partial_hsum(__m128i x) { - __m128i second_int = _mm_bsrli_si128(x, 8); + __m128i second_int = _mm_srli_si128(x, 8); __m128i sum = _mm_add_epi32(x, second_int); return _mm_cvtsi128_si32(sum); } diff --git a/fallback_builtins.h b/fallback_builtins.h index 32bb54dc6f..eacaee36bf 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -71,4 +71,22 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { #endif // __AVX2__ +/* Missing zero-extension AVX and AVX512 intrinsics. + * Fixed in Microsoft Visual Studio 2017 version 15.7 + * https://developercommunity.visualstudio.com/t/missing-zero-extension-avx-and-avx512-intrinsics/175737 + */ +#if defined(_MSC_VER) && _MSC_VER < 1914 +#ifdef __AVX2__ +static inline __m256i _mm256_zextsi128_si256(__m128i a) { + return _mm256_inserti128_si256(_mm256_setzero_si256(), a, 0); +} +#endif // __AVX2__ + +#ifdef __AVX512F__ +static inline __m512i _mm512_zextsi128_si512(__m128i a) { + return _mm512_inserti32x4(_mm512_setzero_si512(), a, 0); +} +#endif // __AVX512F__ +#endif // defined(_MSC_VER) && _MSC_VER < 1914 + #endif // include guard FALLBACK_BUILTINS_H From 08fc981ce21df6cd404e1771dbeb29d7be69d793 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sun, 2 Oct 2022 18:16:24 +0500 Subject: [PATCH 502/798] Fix crc32_fold_pclmulqdq.c(241): error C2719: 'fold3': formal parameter with requested alignment of 16 won't be aligned (MSVC 2015 Win32). Signed-off-by: Vladislav Shchapov --- arch/x86/crc32_fold_pclmulqdq.c | 13 +++++++------ arch/x86/crc32_fold_pclmulqdq_tpl.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 104455e36e..5754b8d713 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -238,17 +238,18 @@ static inline void crc32_fold_load(__m128i *fold, __m128i *fold0, __m128i *fold1 *fold3 = _mm_load_si128(fold + 3); } -static inline void crc32_fold_save(__m128i *fold, __m128i fold0, __m128i fold1, __m128i fold2, __m128i fold3) { - _mm_storeu_si128(fold + 0, fold0); - _mm_storeu_si128(fold + 1, fold1); - _mm_storeu_si128(fold + 2, fold2); - _mm_storeu_si128(fold + 3, fold3); +static inline void crc32_fold_save(__m128i *fold, const __m128i *fold0, const __m128i *fold1, + const __m128i *fold2, const __m128i *fold3) { + _mm_storeu_si128(fold + 0, *fold0); + _mm_storeu_si128(fold + 1, *fold1); + _mm_storeu_si128(fold + 2, *fold2); + _mm_storeu_si128(fold + 3, *fold3); } Z_INTERNAL uint32_t crc32_fold_pclmulqdq_reset(crc32_fold *crc) { __m128i xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); __m128i xmm_zero = _mm_setzero_si128(); - crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_zero, xmm_zero, xmm_zero); + crc32_fold_save((__m128i *)crc->fold, &xmm_crc0, &xmm_zero, &xmm_zero, &xmm_zero); return 0; } diff --git a/arch/x86/crc32_fold_pclmulqdq_tpl.h b/arch/x86/crc32_fold_pclmulqdq_tpl.h index 36207953bc..0799638e04 100644 --- a/arch/x86/crc32_fold_pclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_pclmulqdq_tpl.h @@ -184,6 +184,6 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64 partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); } - crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3); + crc32_fold_save((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); } #endif From e3a34f2cd9ca1304ce83649633d04cfafbbe08d9 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sun, 2 Oct 2022 16:23:25 +0500 Subject: [PATCH 503/798] Improve Microsoft Visual Studio CI Signed-off-by: Vladislav Shchapov --- .github/workflows/cmake.yml | 38 +++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index c81f47a3df..d6347079d0 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -348,15 +348,45 @@ jobs: packages: ninja-build llvm-11-tools gcov-exec: llvm-cov-11 gcov - - name: Windows MSVC Win32 + - name: Windows MSVC 2022 v143 Win32 os: windows-latest compiler: cl - cmake-args: -A Win32 + cmake-args: -G "Visual Studio 17 2022" -A Win32 -T v143 - - name: Windows MSVC Win64 + - name: Windows MSVC 2022 v143 Win64 os: windows-latest compiler: cl - cmake-args: -A x64 + cmake-args: -G "Visual Studio 17 2022" -A x64 -T v143 + + - name: Windows MSVC 2022 v142 Win32 + os: windows-latest + compiler: cl + cmake-args: -G "Visual Studio 17 2022" -A Win32 -T v142 + + - name: Windows MSVC 2022 v142 Win64 + os: windows-latest + compiler: cl + cmake-args: -G "Visual Studio 17 2022" -A x64 -T v142 + + - name: Windows MSVC 2022 v141 Win32 + os: windows-latest + compiler: cl + cmake-args: -G "Visual Studio 17 2022" -A Win32 -T v141 + + - name: Windows MSVC 2022 v141 Win64 + os: windows-latest + compiler: cl + cmake-args: -G "Visual Studio 17 2022" -A x64 -T v141 + + - name: Windows MSVC 2019 v140 Win32 + os: windows-2019 + compiler: cl + cmake-args: -G "Visual Studio 16 2019" -A Win32 -T v140 + + - name: Windows MSVC 2019 v140 Win64 + os: windows-2019 + compiler: cl + cmake-args: -G "Visual Studio 16 2019" -A x64 -T v140 - name: Windows MSVC ARM No Test os: windows-latest From 527610a84e771aab1068756c196465c1a51c37f0 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Thu, 20 Oct 2022 06:28:44 +0200 Subject: [PATCH 504/798] Fix deflate() with Z_BEST_COMPRESSION ignoring the dictionary deflate_slow() uses s->quick_insert_string(), while deflateSetDictionary() uses functable.insert_string(). These functions use different hashing algorithms, which leads to deflate_slow() ignoring the dictionary. Fix by using s->insert_string() instead of functable.insert_string(), which is set by lm_set_level() and matches what deflate_*() uses (suggested by Mika Lindqvist). --- deflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deflate.c b/deflate.c index e17f791717..5be02fe0f7 100644 --- a/deflate.c +++ b/deflate.c @@ -404,7 +404,7 @@ int32_t Z_EXPORT PREFIX(deflateSetDictionary)(PREFIX3(stream) *strm, const uint8 while (s->lookahead >= STD_MIN_MATCH) { str = s->strstart; n = s->lookahead - (STD_MIN_MATCH - 1); - functable.insert_string(s, str, n); + s->insert_string(s, str, n); s->strstart = str + n; s->lookahead = STD_MIN_MATCH - 1; fill_window(s); From 3934621295f76eecb7b6a9bb987195c39c50c440 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Wed, 12 Oct 2022 22:21:21 +0100 Subject: [PATCH 505/798] Fix typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 932214a88f..c2254a4328 100644 --- a/README.md +++ b/README.md @@ -233,7 +233,7 @@ Advanced Build Options Related Projects ---------------- -* Fork of the popular minigzip https://github.com/zlib-ng/minizip-ng +* Fork of the popular minizip https://github.com/zlib-ng/minizip-ng * Python tool to benchmark minigzip/minideflate https://github.com/zlib-ng/deflatebench * Python tool to benchmark pigz https://github.com/zlib-ng/pigzbench * 3rd party patches for zlib-ng compatibility https://github.com/zlib-ng/patches From 185f636e777371985e9c5323e42fc4d718d2c5b6 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 13 Oct 2022 18:18:52 +0300 Subject: [PATCH 506/798] [MinGW] Disable GCC warning about using MS format specifiers in ISO C conformant code --- CMakeLists.txt | 3 +++ configure | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 65827c227b..aa70ebebc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,6 +246,9 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") set(NOLTOFLAG "-fno-lto") endif() endif() + if(MINGW) + list(APPEND WARNFLAGS_DISABLE -Wno-pedantic-ms-format) + endif() else() if(WITH_NATIVE_INSTRUCTIONS) message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration") diff --git a/configure b/configure index ea4ac3977c..2980e1effb 100755 --- a/configure +++ b/configure @@ -459,7 +459,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then EXE='.exe' ;; MINGW* | mingw*) ARFLAGS="rcs" - CFLAGS="${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE=1" + CFLAGS="${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE=1 -Wno-pedantic-ms-format" SFLAGS="${CFLAGS}" shared_ext='.dll' sharedlibdir='${bindir}' From baf0fd123411b6a6b864b5ac27d5a34bc9035909 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Thu, 13 Oct 2022 16:07:37 +0100 Subject: [PATCH 507/798] Enable and fix -Wimplicit-fallthrough warnings --- CMakeLists.txt | 2 +- configure | 2 +- infback.c | 1 + inflate.c | 22 ++++++++++++++++++++++ zbuild.h | 16 ++++++++++++++++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aa70ebebc0..2abeb69b6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -199,7 +199,7 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") # Enable warnings in GCC and Clang set(WARNFLAGS -Wall) set(WARNFLAGS_MAINTAINER -Wextra -Wpedantic) - set(WARNFLAGS_DISABLE -Wno-implicit-fallthrough) + set(WARNFLAGS_DISABLE) if(WITH_NATIVE_INSTRUCTIONS) if(BASEARCH_PPC_FOUND) set(NATIVEFLAG "-mcpu=native") diff --git a/configure b/configure index 2980e1effb..77005308c1 100755 --- a/configure +++ b/configure @@ -393,7 +393,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then SFLAGS="${SFLAGS} ${NATIVE_FLAG}" fi if test "$warn" -eq 1; then - CFLAGS="${CFLAGS} -Wextra -Wpedantic -Wno-implicit-fallthrough" + CFLAGS="${CFLAGS} -Wextra -Wpedantic" fi if test $debug -eq 1; then CFLAGS="${CFLAGS} -DZLIB_DEBUG" diff --git a/infback.c b/infback.c index f56db8e86d..79ce086511 100644 --- a/infback.c +++ b/infback.c @@ -349,6 +349,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in } Tracev((stderr, "inflate: codes ok\n")); state->mode = LEN; + Z_FALLTHROUGH; case LEN: /* use inflate_fast() if we have enough input and output */ diff --git a/inflate.c b/inflate.c index e109182fd3..ead160df8e 100644 --- a/inflate.c +++ b/inflate.c @@ -509,6 +509,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { CRC2(state->check, hold); INITBITS(); state->mode = TIME; + Z_FALLTHROUGH; case TIME: NEEDBITS(32); @@ -518,6 +519,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { CRC4(state->check, hold); INITBITS(); state->mode = OS; + Z_FALLTHROUGH; case OS: NEEDBITS(16); @@ -529,6 +531,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; + Z_FALLTHROUGH; case EXLEN: if (state->flags & 0x0400) { @@ -543,6 +546,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->head->extra = NULL; } state->mode = EXTRA; + Z_FALLTHROUGH; case EXTRA: if (state->flags & 0x0400) { @@ -570,6 +574,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } state->length = 0; state->mode = NAME; + Z_FALLTHROUGH; case NAME: if (state->flags & 0x0800) { @@ -591,6 +596,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } state->length = 0; state->mode = COMMENT; + Z_FALLTHROUGH; case COMMENT: if (state->flags & 0x1000) { @@ -612,6 +618,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->head->comment = NULL; } state->mode = HCRC; + Z_FALLTHROUGH; case HCRC: if (state->flags & 0x0200) { @@ -637,6 +644,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; + Z_FALLTHROUGH; case DICT: if (state->havedict == 0) { @@ -645,10 +653,12 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } strm->adler = state->check = ADLER32_INITIAL_VALUE; state->mode = TYPE; + Z_FALLTHROUGH; case TYPE: if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + Z_FALLTHROUGH; case TYPEDO: /* determine and dispatch block type */ @@ -699,9 +709,11 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->mode = COPY_; if (flush == Z_TREES) goto inf_leave; + Z_FALLTHROUGH; case COPY_: state->mode = COPY; + Z_FALLTHROUGH; case COPY: /* copy stored block from input to output */ @@ -741,6 +753,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { Tracev((stderr, "inflate: table sizes ok\n")); state->have = 0; state->mode = LENLENS; + Z_FALLTHROUGH; case LENLENS: /* get code length code lengths (not a typo) */ @@ -762,6 +775,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { Tracev((stderr, "inflate: code lengths ok\n")); state->have = 0; state->mode = CODELENS; + Z_FALLTHROUGH; case CODELENS: /* get length and distance code code lengths */ @@ -842,9 +856,11 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->mode = LEN_; if (flush == Z_TREES) goto inf_leave; + Z_FALLTHROUGH; case LEN_: state->mode = LEN; + Z_FALLTHROUGH; case LEN: /* use inflate_fast() if we have enough input and output */ @@ -906,6 +922,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* length code */ state->extra = (here.op & 15); state->mode = LENEXT; + Z_FALLTHROUGH; case LENEXT: /* get extra bits, if any */ @@ -918,6 +935,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { Tracevv((stderr, "inflate: length %u\n", state->length)); state->was = state->length; state->mode = DIST; + Z_FALLTHROUGH; case DIST: /* get distance code */ @@ -947,6 +965,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->offset = here.val; state->extra = (here.op & 15); state->mode = DISTEXT; + Z_FALLTHROUGH; case DISTEXT: /* get distance extra bits, if any */ @@ -964,6 +983,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #endif Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; + Z_FALLTHROUGH; case MATCH: /* copy match from window to output */ @@ -1052,6 +1072,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } #ifdef GUNZIP state->mode = LENGTH; + Z_FALLTHROUGH; case LENGTH: if (state->wrap && state->flags) { @@ -1065,6 +1086,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } #endif state->mode = DONE; + Z_FALLTHROUGH; case DONE: /* inflate stream terminated properly */ diff --git a/zbuild.h b/zbuild.h index 510c5addb2..384dace34b 100644 --- a/zbuild.h +++ b/zbuild.h @@ -39,6 +39,22 @@ # endif #endif +#ifndef Z_HAS_ATTRIBUTE +# if defined(__has_attribute) +# define Z_HAS_ATTRIBUTE(a) __has_attribute(a) +# else +# define Z_HAS_ATTRIBUTE(a) 0 +# endif +#endif + +#ifndef Z_FALLTHROUGH +# if Z_HAS_ATTRIBUTE(__fallthrough__) || (defined(__GNUC__) && (__GNUC__ >= 7)) +# define Z_FALLTHROUGH __attribute__((__fallthrough__)) +# else +# define Z_FALLTHROUGH do {} while(0) /* fallthrough */ +# endif +#endif + /* This has to be first include that defines any types */ #if defined(_MSC_VER) # if defined(_WIN64) From 0c118a14dd56d0484a8ca432cf801b9a6e6d024a Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Thu, 29 Sep 2022 19:30:31 +0100 Subject: [PATCH 508/798] Detect the availability of _Thread_local using a configure check --- CMakeLists.txt | 16 ++++++++++++++++ configure | 16 ++++++++++++++++ zbuild.h | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2abeb69b6e..20ca1beb8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -386,6 +386,21 @@ if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL) add_definitions(-DHAVE_VISIBILITY_INTERNAL) endif() +# +# check for _Thread_local() support in the compiler +# +check_c_source_compiles( + "_Thread_local int test; + int main(void) { + (void)test; + return 0; + }" + HAVE_THREAD_LOCAL +) +if(HAVE_THREAD_LOCAL) + add_definitions(-DHAVE_THREAD_LOCAL) +endif() + # # check for __builtin_ctz() support in the compiler # @@ -401,6 +416,7 @@ check_c_source_compiles( if(HAVE_BUILTIN_CTZ) add_definitions(-DHAVE_BUILTIN_CTZ) endif() + # # check for __builtin_ctzll() support in the compiler # diff --git a/configure b/configure index 77005308c1..a64e1403ac 100755 --- a/configure +++ b/configure @@ -942,6 +942,22 @@ EOF fi fi +# Check for _Thread_local support in compiler +cat > $test.c << EOF +_Thread_local int test; +int main(void) { + (void)test; + return 0; +} +EOF +if try ${CC} ${CFLAGS} $test.c $LDSHAREDLIBC; then + echo "Checking for _Thread_local ... Yes." | tee -a configure.log + CFLAGS="$CFLAGS -DHAVE_THREAD_LOCAL" + SFLAGS="$SFLAGS -DHAVE_THREAD_LOCAL" +else + echo "Checking for _Thread_local ... No." | tee -a configure.log +fi + # Check for __builtin_ctz() support in compiler cat > $test.c << EOF int main(void) { diff --git a/zbuild.h b/zbuild.h index 384dace34b..c96d48b31f 100644 --- a/zbuild.h +++ b/zbuild.h @@ -27,7 +27,7 @@ /* Determine compiler support for TLS */ #ifndef Z_TLS -# if defined(STDC11) && !defined(__STDC_NO_THREADS__) +# ifdef HAVE_THREAD_LOCAL # define Z_TLS _Thread_local # elif defined(__GNUC__) || defined(__SUNPRO_C) # define Z_TLS __thread From f127bc96fc57d05f2cda19406cfc506cf5256e26 Mon Sep 17 00:00:00 2001 From: tch69 <44942508+tch69@users.noreply.github.com> Date: Thu, 27 Oct 2022 21:42:19 +0700 Subject: [PATCH 509/798] Makefile.in: distclean should remove zlib.pc instead of clean --- Makefile.in | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index f068184e3a..88d40cb662 100644 --- a/Makefile.in +++ b/Makefile.in @@ -367,7 +367,6 @@ clean: rm -rf objs rm -f *.gcda *.gcno *.gcov rm -f a.out a.exe - rm -f *.pc rm -f *._h rm -rf btmp1 btmp2 pkgtmp1 pkgtmp2 @@ -375,7 +374,7 @@ maintainer-clean: distclean distclean: clean @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) distclean; fi @if [ -f test/Makefile ]; then $(MAKE) -C test distclean; fi - rm -f $(PKGFILE) configure.log zconf.h zconf.h.cmakein zlib$(SUFFIX).h zlib_name_mangling$(SUFFIX)}.h + rm -f $(PKGFILE) configure.log zconf.h zconf.h.cmakein zlib$(SUFFIX).h zlib_name_mangling$(SUFFIX)}.h *.pc -@rm -f .DS_Store # Reset Makefile if building inside source tree @if [ -f Makefile.in ]; then \ From e63f36b1cf615a81e2cfa2d97fc54a5f493c9c19 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 28 Sep 2022 00:50:36 +0200 Subject: [PATCH 510/798] Introduce ZLIBNG_ENABLE_TESTS This patch adds the ability to run zlib-ng test suite against the original zlib as follows: cmake -DZLIB_COMPAT=ON -DZLIBNG_ENABLE_TESTS=OFF . make LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu make test The benefit of this is that modifications to the original zlib can be tested with a more extensive zlib-ng's testsuite, and the assumptions that the zlib-ng tests make can be validated against the original zlib. In addition to a number of tests that exercise purely zlib-ng specific API, there are a few that expect zlib-ng specific behavior from the original zlib API: - deflate() (obviously) emits different streams - zlib-ng's deflatePrime() can take more than 16 bits - zVersion() returns a different string Adjust or disable the respective tests for ZLIBNG_ENABLE_TESTS=OFF. --- CMakeLists.txt | 2 ++ README.md | 1 + test/CMakeLists.txt | 39 +++++++++++++++++++++++++++++--------- test/example.c | 18 ++++++++++-------- test/test_deflate_prime.cc | 8 ++++---- test/test_shared.h | 10 ++++++++++ test/test_shared_ng.h | 23 ++++++++++++++++++++++ 7 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 test/test_shared_ng.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 20ca1beb8d..ca395b2da6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ endif() option(WITH_GZFILEOP "Compile with support for gzFile related functions" ON) option(ZLIB_COMPAT "Compile with zlib compatible API" OFF) option(ZLIB_ENABLE_TESTS "Build test binaries" ON) +option(ZLIBNG_ENABLE_TESTS "Test zlib-ng specific API" ON) option(WITH_FUZZERS "Build test/fuzz" OFF) option(WITH_BENCHMARKS "Build test/benchmarks" OFF) option(WITH_BENCHMARK_APPS "Build application benchmarks" OFF) @@ -1178,6 +1179,7 @@ endif() add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile related functions") add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Compile with zlib compatible API") add_feature_info(ZLIB_ENABLE_TESTS ZLIB_ENABLE_TESTS "Build test binaries") +add_feature_info(ZLIBNG_ENABLE_TESTS ZLIBNG_ENABLE_TESTS "Test zlib-ng specific API") add_feature_info(WITH_SANITIZER WITH_SANITIZER "Enable sanitizer support") add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz") add_feature_info(WITH_BENCHMARKS WITH_BENCHMARKS "Build test/benchmarks") diff --git a/README.md b/README.md index c2254a4328..a1218d44d0 100644 --- a/README.md +++ b/README.md @@ -228,6 +228,7 @@ Advanced Build Options | WITH_INFLATE_STRICT | | Build with strict inflate distance checking | OFF | | WITH_INFLATE_ALLOW_INVALID_DIST | | Build with zero fill for inflate invalid distances | OFF | | INSTALL_UTILS | | Copy minigzip and minideflate during install | OFF | +| ZLIBNG_ENABLE_TESTS | | Test zlib-ng specific API | ON | Related Projects diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ad002d9cef..61322e077b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,6 +9,10 @@ macro(configure_test_executable target) endif() endmacro() +if(ZLIBNG_ENABLE_TESTS) + add_definitions(-DZLIBNG_ENABLE_TESTS) +endif() + add_executable(example example.c) configure_test_executable(example) target_link_libraries(example zlib) @@ -51,7 +55,10 @@ target_link_libraries(infcover zlib) if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) target_sources(infcover PRIVATE ${PROJECT_SOURCE_DIR}/inftrees.c) endif() -add_test(NAME infcover COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) +# infcover references zng_inflate_table() and struct inflate_state, which are internal to zlib-ng. +if(ZLIBNG_ENABLE_TESTS) + add_test(NAME infcover COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) +endif() add_executable(makefixed ${PROJECT_SOURCE_DIR}/tools/makefixed.c ${PROJECT_SOURCE_DIR}/inftrees.c) configure_test_executable(makefixed) @@ -135,15 +142,12 @@ else() add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) endif() add_library(GTest::GTest ALIAS gtest) + add_library(GTest::Main ALIAS gtest_main) endif() set(TEST_SRCS - test_adler32.cc - test_aligned_alloc.cc - test_compare256.cc test_compress.cc test_compress_bound.cc - test_crc32.cc test_cve-2003-0107.cc test_deflate_bound.cc test_deflate_copy.cc @@ -158,17 +162,27 @@ else() test_deflate_tune.cc test_dict.cc test_inflate_adler32.cc - test_inflate_sync.cc test_large_buffers.cc test_small_buffers.cc - test_version.cc ) if(WITH_GZFILEOP) list(APPEND TEST_SRCS test_gzio.cc) endif() - add_executable(gtest_zlib test_main.cc ${TEST_SRCS}) + if(ZLIBNG_ENABLE_TESTS) + list(APPEND TEST_SRCS + test_adler32.cc # adler32_neon(), etc + test_aligned_alloc.cc # zng_alloc_aligned() + test_compare256.cc # compare256_neon(), etc + test_crc32.cc # crc32_acle(), etc + test_inflate_sync.cc # expects a certain compressed block layout + test_main.cc # cpu_check_features() + test_version.cc # expects a fixed version string + ) + endif() + + add_executable(gtest_zlib ${TEST_SRCS}) configure_test_executable(gtest_zlib) if(WITH_SANITIZER STREQUAL "Memory") @@ -200,7 +214,14 @@ else() target_link_libraries(gtest_zlib external_zlib) endif() - target_link_libraries(gtest_zlib zlibstatic GTest::GTest) + if((NOT ZLIBNG_ENABLE_TESTS) AND ZLIB_COMPAT AND (NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS)) + # Link dynamically in order to be able to substitute zlib-ng with zlib. + target_link_libraries(gtest_zlib zlib GTest::Main) + else() + # Link statically in order to test internal zlib-ng functions. + target_link_libraries(gtest_zlib zlibstatic) + endif() + target_link_libraries(gtest_zlib GTest::GTest) find_package(Threads) if(Threads_FOUND) diff --git a/test/example.c b/test/example.c index 33232dedda..c6556ed197 100644 --- a/test/example.c +++ b/test/example.c @@ -15,12 +15,9 @@ #include #include -#define TESTFILE "foo.gz" +#include "test_shared_ng.h" -static const char hello[] = "hello, hello!"; -/* "hello world" would be more standard, but the repeated "hello" - * stresses the compression code better, sorry... - */ +#define TESTFILE "foo.gz" static const char dictionary[] = "hello"; static unsigned long dictId = 0; /* Adler32 value of the dictionary */ @@ -437,8 +434,10 @@ void test_flush(unsigned char *compr, z_size_t *comprLen) { *comprLen = (z_size_t)c_stream.total_out; } +#ifdef ZLIBNG_ENABLE_TESTS /* =========================================================================== * Test inflateSync() + * We expect a certain compressed block layout, so skip this with the original zlib. */ void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { int err; @@ -474,6 +473,7 @@ void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr, si printf("after inflateSync(): hel%s\n", (char *)uncompr); } +#endif /* =========================================================================== * Test deflate() with preset dictionary @@ -785,7 +785,7 @@ void test_deflate_prime(unsigned char *compr, size_t comprLen, unsigned char *un err = PREFIX(deflatePrime)(&c_stream, 5, 0x0); CHECK_ERR(err, "deflatePrime"); /* Gzip modified time */ - err = PREFIX(deflatePrime)(&c_stream, 32, 0x0); + err = deflate_prime_32(&c_stream, 0); CHECK_ERR(err, "deflatePrime"); /* Gzip extra flags */ err = PREFIX(deflatePrime)(&c_stream, 8, 0x0); @@ -805,10 +805,10 @@ void test_deflate_prime(unsigned char *compr, size_t comprLen, unsigned char *un /* Gzip uncompressed data crc32 */ crc = PREFIX(crc32)(0, (const uint8_t *)hello, (uint32_t)len); - err = PREFIX(deflatePrime)(&c_stream, 32, crc); + err = deflate_prime_32(&c_stream, crc); CHECK_ERR(err, "deflatePrime"); /* Gzip uncompressed data length */ - err = PREFIX(deflatePrime)(&c_stream, 32, (uint32_t)len); + err = deflate_prime_32(&c_stream, (uint32_t)len); CHECK_ERR(err, "deflatePrime"); err = PREFIX(deflateEnd)(&c_stream); @@ -993,7 +993,9 @@ int main(int argc, char *argv[]) { #endif test_flush(compr, &comprLen); +#ifdef ZLIBNG_ENABLE_TESTS test_sync(compr, comprLen, uncompr, uncomprLen); +#endif comprLen = uncomprLen; test_dict_deflate(compr, comprLen); diff --git a/test/test_deflate_prime.cc b/test/test_deflate_prime.cc index 135a2d435f..75dcf3177a 100644 --- a/test/test_deflate_prime.cc +++ b/test/test_deflate_prime.cc @@ -12,7 +12,7 @@ #include #include -#include "test_shared.h" +#include "test_shared_ng.h" #include @@ -42,7 +42,7 @@ TEST(deflate, prime) { err = PREFIX(deflatePrime)(&c_stream, 5, 0x0); EXPECT_EQ(err, Z_OK); /* Gzip modified time */ - err = PREFIX(deflatePrime)(&c_stream, 32, 0x0); + err = deflate_prime_32(&c_stream, 0x0); EXPECT_EQ(err, Z_OK); /* Gzip extra flags */ err = PREFIX(deflatePrime)(&c_stream, 8, 0x0); @@ -61,10 +61,10 @@ TEST(deflate, prime) { /* Gzip uncompressed data crc32 */ crc = PREFIX(crc32)(0, (const uint8_t *)hello, (uint32_t)hello_len); - err = PREFIX(deflatePrime)(&c_stream, 32, crc); + err = deflate_prime_32(&c_stream, crc); EXPECT_EQ(err, Z_OK); /* Gzip uncompressed data length */ - err = PREFIX(deflatePrime)(&c_stream, 32, (uint32_t)hello_len); + err = deflate_prime_32(&c_stream, (uint32_t)hello_len); EXPECT_EQ(err, Z_OK); err = PREFIX(deflateEnd)(&c_stream); diff --git a/test/test_shared.h b/test/test_shared.h index f942967e5b..df92a56b3b 100644 --- a/test/test_shared.h +++ b/test/test_shared.h @@ -1,2 +1,12 @@ +#ifndef TEST_SHARED_H +#define TEST_SHARED_H + +/* Test definitions that can be used in the original zlib build environment. */ + +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ static const char hello[] = "hello, hello!"; static const int hello_len = sizeof(hello); + +#endif diff --git a/test/test_shared_ng.h b/test/test_shared_ng.h new file mode 100644 index 0000000000..81e451998f --- /dev/null +++ b/test/test_shared_ng.h @@ -0,0 +1,23 @@ +#ifndef TEST_SHARED_NG_H +#define TEST_SHARED_NG_H + +#include "test_shared.h" + +/* Test definitions that can only be used in the zlib-ng build environment. */ + +static inline int deflate_prime_32(PREFIX3(stream) *stream, uint32_t value) { + int err; + +#ifdef ZLIBNG_ENABLE_TESTS + err = PREFIX(deflatePrime)(stream, 32, value); +#else + /* zlib's deflatePrime() takes at most 16 bits */ + err = PREFIX(deflatePrime)(stream, 16, value & 0xffff); + if (err != Z_OK) return err; + err = PREFIX(deflatePrime)(stream, 16, value >> 16); +#endif + + return err; +} + +#endif From b3dcf11b4204a16fde71fa8224d7b7054e225b93 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Thu, 13 Oct 2022 14:59:18 +0100 Subject: [PATCH 511/798] Support using aligned_alloc() for memory allocation --- CMakeLists.txt | 6 ++++++ configure | 19 +++++++++++++++++++ zbuild.h | 3 +++ zutil_p.h | 4 +++- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca395b2da6..642d35f42b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -343,6 +343,12 @@ if(HAVE_POSIX_MEMALIGN) add_definitions(-DHAVE_POSIX_MEMALIGN) endif() set(CMAKE_REQUIRED_DEFINITIONS) +set(CMAKE_REQUIRED_DEFINITIONS -D_ISOC11_SOURCE=1) +check_function_exists(aligned_alloc HAVE_ALIGNED_ALLOC) +if(HAVE_ALIGNED_ALLOC) + add_definitions(-DHAVE_ALIGNED_ALLOC) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) if(WITH_SANITIZER STREQUAL "Address") add_address_sanitizer() diff --git a/configure b/configure index a64e1403ac..552148caae 100755 --- a/configure +++ b/configure @@ -706,6 +706,25 @@ else fi echo >> configure.log +cat > $test.c < +int main(void) { + void *ptr = aligned_alloc(64, 10); + if (ptr) + free(ptr); + return 0; +} +EOF +if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then + echo "Checking for aligned_alloc... Yes." | tee -a configure.log + CFLAGS="${CFLAGS} -DHAVE_ALIGNED_ALLOC" + SFLAGS="${SFLAGS} -DHAVE_ALIGNED_ALLOC" +else + echo "Checking for aligned_alloc... No." | tee -a configure.log +fi +echo >> configure.log + # check for strerror() for use by gz* functions cat > $test.c < diff --git a/zbuild.h b/zbuild.h index c96d48b31f..7fa4322ab5 100644 --- a/zbuild.h +++ b/zbuild.h @@ -5,6 +5,9 @@ #ifndef _POSIX_C_SOURCE # define _POSIX_C_SOURCE 200809L /* snprintf, posix_memalign, strdup */ #endif +#ifndef _ISOC11_SOURCE +# define _ISOC11_SOURCE 1 /* aligned_alloc */ +#endif #include #include diff --git a/zutil_p.h b/zutil_p.h index fdfb4438a9..318b4d9011 100644 --- a/zutil_p.h +++ b/zutil_p.h @@ -5,7 +5,7 @@ #ifndef ZUTIL_P_H #define ZUTIL_P_H -#if defined(__APPLE__) || defined(HAVE_POSIX_MEMALIGN) +#if defined(__APPLE__) || defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_ALIGNED_ALLOC) # include #elif defined(__FreeBSD__) # include @@ -23,6 +23,8 @@ static inline void *zng_alloc(size_t size) { return (void *)_aligned_malloc(size, 64); #elif defined(__APPLE__) return (void *)malloc(size); /* MacOS always aligns to 16 bytes */ +#elif defined(HAVE_ALIGNED_ALLOC) + return (void *)aligned_alloc(64, size); #else return (void *)memalign(64, size); #endif From 60ed1ab3e77531595c606d71cc35237af556fced Mon Sep 17 00:00:00 2001 From: Piotr Sikora Date: Sun, 21 Aug 2022 17:41:54 -0700 Subject: [PATCH 512/798] Add support for compiling to WebAssembly using Emscripten. Co-authored-by: Nathan Moinvaziri --- cmake/detect-arch.c | 4 ++++ cmake/detect-arch.cmake | 3 +++ 2 files changed, 7 insertions(+) diff --git a/cmake/detect-arch.c b/cmake/detect-arch.c index 43ddb126ae..ff1a05a253 100644 --- a/cmake/detect-arch.c +++ b/cmake/detect-arch.c @@ -101,6 +101,10 @@ #error archfound riscv32 #endif +// Emscripten (WebAssembly) +#elif defined(__EMSCRIPTEN__) + #error archfound wasm32 + // return 'unrecognized' if we do not know what architecture this is #else #error archfound unrecognized diff --git a/cmake/detect-arch.cmake b/cmake/detect-arch.cmake index f0547ba310..6f29c4a102 100644 --- a/cmake/detect-arch.cmake +++ b/cmake/detect-arch.cmake @@ -88,6 +88,9 @@ elseif("${ARCH}" MATCHES "rs6000") elseif("${ARCH}" MATCHES "riscv(32|64)") set(BASEARCH "riscv") set(BASEARCH_RISCV_FOUND TRUE) +elseif("${ARCH}" MATCHES "wasm32") + set(BASEARCH "wasm32") + set(BASEARCH_WASM32_FOUND TRUE) else() set(BASEARCH "x86") set(BASEARCH_X86_FOUND TRUE) From 2e39c6d68b5d944e1c0de5faeb99e731162899ea Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 21 Aug 2022 19:26:32 -0700 Subject: [PATCH 513/798] Turn off tests for Emscripten that use large amounts of data. --- configure | 8 +++++++- test/CMakeLists.txt | 20 ++++++++++++-------- test/Makefile.in | 4 ++-- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 552148caae..5381ee65ac 100755 --- a/configure +++ b/configure @@ -2193,6 +2193,12 @@ for file in $SRCDIR/$ARCHDIR/*.c; do fi done +# Emscripten does not support large amounts of data via stdin/out +# https://github.com/emscripten-core/emscripten/issues/16755#issuecomment-1102732849 +if test "$CHOST" != "wasm32"; then + TEST="${TEST} ghtests" +fi + # Generate Makefile in test dir mkdir -p test if test $QEMU_ARCH; then QEMU_RUN="qemu-$QEMU_ARCH -L /usr/${CHOST}/"; fi @@ -2201,7 +2207,7 @@ sed < $SRCDIR/test/Makefile.in " /^CFLAGS *=/s#=.*#=$CFLAGS# /^LDFLAGS *=/s#=.*#=$LDFLAGS# /^EXE *=/s#=.*#=$EXE# -/^oldtests: */s#:.*#: $TEST# +/^alltests: */s#:.*#: $TEST# /^SRCDIR *=/s#=.*#=$SRCDIR/test# /^SRCTOP *=/s#=.*#=$SRCDIR# /^QEMU_RUN *=/s#=.*#=$QEMU_RUN# diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 61322e077b..3b71688811 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -72,17 +72,21 @@ add_executable(makecrct ${PROJECT_SOURCE_DIR}/tools/makecrct.c) configure_test_executable(makecrct) set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -# Runs tests targeting CVEs -include(cmake/test-cves.cmake) +# Emscripten does not support large amounts of data via stdin/out +# https://github.com/emscripten-core/emscripten/issues/16755#issuecomment-1102732849 +if(NOT BASEARCH_WASM32_FOUND) + # Runs tests targeting CVEs + include(cmake/test-cves.cmake) -# Run tests with data files -include(cmake/test-data.cmake) + # Run tests with data files + include(cmake/test-data.cmake) -# Run tests targeting GitHub issues -include(cmake/test-issues.cmake) + # Run tests targeting GitHub issues + include(cmake/test-issues.cmake) -# Run tests targeting tools -include(cmake/test-tools.cmake) + # Run tests targeting tools + include(cmake/test-tools.cmake) +endif() if(WITH_FUZZERS) add_subdirectory(fuzz) diff --git a/test/Makefile.in b/test/Makefile.in index 4cd1399ec5..e10de00bad 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -13,9 +13,9 @@ TEST_LDFLAGS=-L.. ../$(LIBNAME).a QEMU_RUN= QEMU_VER:=$(shell command -v $(QEMU_RUN) --version 2> /dev/null) -all: oldtests ghtests +all: alltests -oldtests: #set by ../configure +alltests: #set by ../configure check_cross_dep: ifneq (,$(QEMU_RUN)) ifeq (,$(QEMU_VER)) From e273dd65edb9a4dd2b7ce649596e812e70107dfe Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 20 Aug 2022 09:09:55 -0700 Subject: [PATCH 514/798] Don't run deflate concurrency Google Test for Emscripten/WASM32. --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3b71688811..3bf1f76734 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -228,7 +228,7 @@ else() target_link_libraries(gtest_zlib GTest::GTest) find_package(Threads) - if(Threads_FOUND) + if(Threads_FOUND AND NOT BASEARCH_WASM32_FOUND) target_sources(gtest_zlib PRIVATE test_deflate_concurrency.cc) if(UNIX AND NOT APPLE) # On Linux, use a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590 From ebba7d7bfead92d52464b586f81e269a8d495d3d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 21 Aug 2022 17:48:25 -0700 Subject: [PATCH 515/798] Remove unused qemu-run variable from configure workflow matrix. The configure script automatically determines this with variable QEMU_ARCH. --- .github/workflows/configure.yml | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 4c0d395d7d..babdbe617d 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -36,7 +36,6 @@ jobs: configure-args: --warn chost: arm-linux-gnueabi packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross - qemu-run: qemu-arm - name: Ubuntu GCC ARM SF Compat No Opt os: ubuntu-latest @@ -44,7 +43,6 @@ jobs: configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies chost: arm-linux-gnueabi packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross - qemu-run: qemu-arm - name: Ubuntu GCC ARM HF os: ubuntu-latest @@ -52,7 +50,6 @@ jobs: configure-args: --warn chost: arm-linux-gnueabihf packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross - qemu-run: qemu-arm - name: Ubuntu GCC ARM HF No ACLE os: ubuntu-latest @@ -60,7 +57,6 @@ jobs: configure-args: --warn --without-acle chost: arm-linux-gnueabihf packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross - qemu-run: qemu-arm - name: Ubuntu GCC ARM HF No NEON os: ubuntu-latest @@ -68,7 +64,6 @@ jobs: configure-args: --warn --without-neon chost: arm-linux-gnueabihf packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross - qemu-run: qemu-arm - name: Ubuntu GCC ARM HF Compat No Opt os: ubuntu-latest @@ -76,7 +71,6 @@ jobs: configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies chost: arm-linux-gnueabihf packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross - qemu-run: qemu-arm - name: Ubuntu GCC AARCH64 os: ubuntu-latest @@ -84,7 +78,6 @@ jobs: configure-args: --warn chost: aarch64-linux-gnu packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 - name: Ubuntu GCC AARCH64 No ACLE os: ubuntu-latest @@ -92,7 +85,6 @@ jobs: configure-args: --warn --without-acle chost: aarch64-linux-gnu packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 - name: Ubuntu GCC AARCH64 No NEON os: ubuntu-latest @@ -100,7 +92,6 @@ jobs: configure-args: --warn --without-neon chost: aarch64-linux-gnu packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 - name: Ubuntu GCC AARCH64 Compat No Opt os: ubuntu-latest @@ -108,7 +99,6 @@ jobs: configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies chost: aarch64-linux-gnu packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 - name: Ubuntu GCC PPC os: ubuntu-latest @@ -116,7 +106,6 @@ jobs: configure-args: --warn --static chost: powerpc-linux-gnu packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross - qemu-run: qemu-ppc cflags: -static ldflags: -static @@ -126,7 +115,6 @@ jobs: configure-args: --warn --without-power8 chost: powerpc-linux-gnu packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross - qemu-run: qemu-ppc - name: Ubuntu GCC PPC64 os: ubuntu-latest @@ -134,7 +122,6 @@ jobs: configure-args: --warn --static chost: powerpc-linux-gnu packages: qemu qemu-user gcc-powerpc64-linux-gnu libc-dev-ppc64-cross - qemu-run: qemu-ppc64 cflags: -static ldflags: -static @@ -144,7 +131,6 @@ jobs: configure-args: --warn chost: powerpc64le-linux-gnu packages: qemu qemu-user gcc-powerpc64le-linux-gnu libc-dev-ppc64el-cross - qemu-run: qemu-ppc64le - name: Ubuntu GCC S390X os: ubuntu-latest @@ -152,7 +138,6 @@ jobs: configure-args: --warn --static chost: s390x-linux-gnu packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross - qemu-run: qemu-s390x cflags: -static ldflags: -static @@ -162,7 +147,6 @@ jobs: configure-args: --warn --static --without-crc32-vx chost: s390x-linux-gnu packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross - qemu-run: qemu-s390x cflags: -static ldflags: -static @@ -220,8 +204,6 @@ jobs: - name: Run test cases run: make test working-directory: ${{ matrix.build-dir }} - env: - QEMU_RUN: ${{ matrix.qemu-run }} - name: Upload build errors uses: actions/upload-artifact@v2 From e228ee6f96208a6eea7eb4485d8370c1d06ce292 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 21 Aug 2022 18:37:14 -0700 Subject: [PATCH 516/798] Added cmake and configure matrix runs for Emscripten. --- .github/workflows/cmake.yml | 9 +++++++++ .github/workflows/configure.yml | 14 +++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index d6347079d0..038d8b3b8e 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -348,6 +348,11 @@ jobs: packages: ninja-build llvm-11-tools gcov-exec: llvm-cov-11 gcov + - name: Ubuntu Emscripten WASM32 + os: ubuntu-latest + chost: wasm32 + cmake-args: -DCMAKE_TOOLCHAIN_FILE=${EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_C_COMPILER_TARGET=wasm32 -DCMAKE_CROSSCOMPILING_EMULATOR=${EMSDK_NODE} -DZLIB_COMPAT=ON + - name: Windows MSVC 2022 v143 Win32 os: windows-latest compiler: cl @@ -473,6 +478,10 @@ jobs: env: HOMEBREW_NO_INSTALL_CLEANUP: 1 + - name: Install Emscripten + if: contains(matrix.name, 'WASM32') + uses: mymindstorm/setup-emsdk@v11 + - name: Initialize Wine # Prevent parallel test jobs from initializing Wine at the same time if: contains(matrix.packages, 'wine') diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index babdbe617d..fb29baf330 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -160,6 +160,14 @@ jobs: compiler: gcc configure-args: --warn --zlib-compat --static --with-dfltcc-deflate --with-dfltcc-inflate + - name: Ubuntu Emscripten WASM32 + os: ubuntu-latest + chost: wasm32 + configure-args: --warn --zlib-compat --static + configure-prefix: emconfigure + cflags: -static + ldflags: -static + - name: macOS GCC Symbol Prefix os: macOS-latest compiler: gcc-9 @@ -185,11 +193,15 @@ jobs: sudo apt-get update sudo apt-get install -y ${{ matrix.packages }} + - name: Install Emscripten + if: contains(matrix.name, 'WASM32') + uses: mymindstorm/setup-emsdk@v11 + - name: Generate project files run: | mkdir ${{ matrix.build-dir || '.not-used' }} cd ${{ matrix.build-dir || '.' }} - ${{ matrix.build-src-dir || '.' }}/configure ${{ matrix.configure-args }} + ${{ matrix.configure-prefix }} ${{ matrix.build-src-dir || '.' }}/configure ${{ matrix.configure-args }} env: CC: ${{ matrix.compiler }} CFLAGS: ${{ matrix.cflags }} From 7ad4e1865e9d555badcdaff8add1297db2fb6aff Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 21 Aug 2022 18:59:45 -0700 Subject: [PATCH 517/798] Upload generated makefiles when configure runs fail. --- .github/workflows/configure.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index fb29baf330..cd787eb396 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -223,5 +223,6 @@ jobs: with: name: ${{ matrix.name }} (configure) path: | + **/Makefile ${{ matrix.build-dir || '.' }}/configure.log retention-days: 30 From 354be239442c765b6bd39f80a0933b854b034d90 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 9 Oct 2022 18:41:50 -0700 Subject: [PATCH 518/798] All overriding the emulator used by configure script with EMU_RUN. --- .github/workflows/configure.yml | 2 ++ configure | 11 +++++++++-- test/Makefile.in | 20 ++++++++++---------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index cd787eb396..48651fa6cf 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -167,6 +167,7 @@ jobs: configure-prefix: emconfigure cflags: -static ldflags: -static + emu-run: node - name: macOS GCC Symbol Prefix os: macOS-latest @@ -207,6 +208,7 @@ jobs: CFLAGS: ${{ matrix.cflags }} LDFLAGS: ${{ matrix.ldflags }} CHOST: ${{ matrix.chost }} + EMU_RUN: ${{ matrix.emu-run }} CI: true - name: Compile source code diff --git a/configure b/configure index 5381ee65ac..bb8d15c8ec 100755 --- a/configure +++ b/configure @@ -2199,9 +2199,16 @@ if test "$CHOST" != "wasm32"; then TEST="${TEST} ghtests" fi +# Determine emulator to use when running tests +if test -z "$EMU_RUN" && test $QEMU_ARCH; then + EMU_RUN="qemu-$QEMU_ARCH -L /usr/${CHOST}/" +fi +if test -n "$EMU_RUN"; then + echo "Using cross-compile emulator: $EMU_RUN" +fi + # Generate Makefile in test dir mkdir -p test -if test $QEMU_ARCH; then QEMU_RUN="qemu-$QEMU_ARCH -L /usr/${CHOST}/"; fi sed < $SRCDIR/test/Makefile.in " /^CC *=/s#=.*#=$CC# /^CFLAGS *=/s#=.*#=$CFLAGS# @@ -2210,7 +2217,7 @@ sed < $SRCDIR/test/Makefile.in " /^alltests: */s#:.*#: $TEST# /^SRCDIR *=/s#=.*#=$SRCDIR/test# /^SRCTOP *=/s#=.*#=$SRCDIR# -/^QEMU_RUN *=/s#=.*#=$QEMU_RUN# +/^EMU_RUN *=/s#=.*#=$EMU_RUN# /^LIBNAME *=/s#=.*#=$LIBNAME# " > test/Makefile diff --git a/test/Makefile.in b/test/Makefile.in index e10de00bad..d2658e7ce4 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -10,16 +10,16 @@ SRCTOP= LIBNAME= TEST_LDFLAGS=-L.. ../$(LIBNAME).a -QEMU_RUN= -QEMU_VER:=$(shell command -v $(QEMU_RUN) --version 2> /dev/null) +EMU_RUN= all: alltests alltests: #set by ../configure check_cross_dep: -ifneq (,$(QEMU_RUN)) +ifneq (,$(findstring qemu,$(EMU_RUN))) +QEMU_VER:=$(shell command -v $(EMU_RUN) --version 2> /dev/null) ifeq (,$(QEMU_VER)) - $(error "You need QEMU to run tests on non-native platform") + $(error You need QEMU to run tests on non-native platform) endif endif @@ -28,7 +28,7 @@ ALL_SRC_FILES := $(wildcard ../*) teststatic: check_cross_dep @TMPST=tmpst_$$$$; \ HELLOST=tmphellost_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${QEMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${QEMU_RUN} ../example$(EXE) $$TMPST; then \ + if echo hello world | ${EMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${EMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${EMU_RUN} ../example$(EXE) $$TMPST; then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; exit 1; \ @@ -42,7 +42,7 @@ testshared: check_cross_dep SHLIB_PATH=`pwd`/..:$(SHLIB_PATH) ; export SHLIB_PATH; \ TMPSH=tmpsh_$$$$; \ HELLOSH=tmphellosh_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${QEMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH; then \ + if echo hello world | ${EMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${EMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${EMU_RUN} ../examplesh$(EXE) $$TMPSH; then \ echo ' *** zlib shared test OK ***'; \ else \ echo ' *** zlib shared test FAILED ***'; exit 1; \ @@ -54,25 +54,25 @@ ghtests: testGH-361 testGH-364 testGH-751 testGH-1235 .PHONY: testGH-361 testGH-361: - $(QEMU_RUN) ../minigzip$(EXE) -4 <$(SRCDIR)/GH-361/test.txt >/dev/null + $(EMU_RUN) ../minigzip$(EXE) -4 <$(SRCDIR)/GH-361/test.txt >/dev/null switchlevels$(EXE): $(SRCDIR)/switchlevels.c $(CC) $(CFLAGS) -I.. -I$(SRCTOP) -o $@ $< $(TEST_LDFLAGS) .PHONY: testGH-364 testGH-364: switchlevels$(EXE) - $(QEMU_RUN) ./switchlevels$(EXE) 1 5 9 3 <$(SRCDIR)/GH-364/test.bin >/dev/null + $(EMU_RUN) ./switchlevels$(EXE) 1 5 9 3 <$(SRCDIR)/GH-364/test.bin >/dev/null .PHONY: testGH-751 testGH-751: - $(QEMU_RUN) ../minigzip$(EXE) <$(SRCDIR)/GH-751/test.txt | $(QEMU_RUN) ../minigzip$(EXE) -d >/dev/null + $(EMU_RUN) ../minigzip$(EXE) <$(SRCDIR)/GH-751/test.txt | $(EMU_RUN) ../minigzip$(EXE) -d >/dev/null gh1235$(EXE): $(SRCDIR)/gh1235.c $(CC) $(CFLAGS) -I.. -I$(SRCTOP) -o $@ $< $(TEST_LDFLAGS) .PHONY: testGH-1235 testGH-1235: gh1235$(EXE) - $(QEMU_RUN) ./gh1235$(EXE) + $(EMU_RUN) ./gh1235$(EXE) clean: rm -f *.o *.gcda *.gcno *.gcov From 595f050b9f7324fb3ad840dae2a6de4f7d5a3de7 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 4 Nov 2022 16:31:13 +0000 Subject: [PATCH 519/798] Use CMake detection for Emscripten due to a bug in vcpkg. When installing for wasm32 with vcpkg, CMake's try_run does not end up running with the correct compiler. This issue has been mention in a few existing vcpkg portfiles. Alternatively, we could check the VCPKG_TARGET_ARCHITECTURE variable for wasm32 but instead we check for EMSCRIPTEN CMake variable. --- cmake/detect-arch.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/detect-arch.cmake b/cmake/detect-arch.cmake index 6f29c4a102..21c237d61a 100644 --- a/cmake/detect-arch.cmake +++ b/cmake/detect-arch.cmake @@ -16,6 +16,8 @@ elseif(MSVC) elseif ("${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARM64") set(ARCH "aarch64") endif() +elseif(EMSCRIPTEN) + set(ARCH "wasm32") elseif(CMAKE_CROSSCOMPILING) set(ARCH ${CMAKE_C_COMPILER_TARGET}) else() From 69059f3e8cb42c851bd23f204e8507f297c29ae7 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Mon, 5 Dec 2022 14:06:09 +0200 Subject: [PATCH 520/798] Ubuntu 22.04 CI image doesn't have clang-11 installed. --- .github/workflows/cmake.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 038d8b3b8e..b7c2dcf555 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -291,7 +291,7 @@ jobs: os: ubuntu-latest compiler: clang-11 cxx-compiler: clang++-11 - packages: llvm-11-tools + packages: clang-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang @@ -300,7 +300,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cmake-args: -DWITH_INFLATE_STRICT=ON - packages: llvm-11-tools + packages: clang-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_inflate_strict @@ -309,7 +309,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cmake-args: -DWITH_INFLATE_ALLOW_INVALID_DIST=ON - packages: llvm-11-tools + packages: clang-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_inflate_allow_invalid_dist @@ -318,7 +318,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cmake-args: -DWITH_REDUCED_MEM=ON - packages: llvm-11-tools + packages: clang-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_reduced_mem @@ -327,7 +327,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cflags: -DUSE_MMAP - packages: llvm-11-tools + packages: clang-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_mmap @@ -335,7 +335,7 @@ jobs: os: ubuntu-latest compiler: clang-11 cxx-compiler: clang++-11 - packages: llvm-11-tools + packages: clang-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_debug build-config: Debug @@ -345,7 +345,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cmake-args: -GNinja -DWITH_SANITIZER=Memory - packages: ninja-build llvm-11-tools + packages: ninja-build clang-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov - name: Ubuntu Emscripten WASM32 From a90fd51ff0d8860dca1cc20f07a8f6284987abea Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Sun, 4 Dec 2022 19:51:12 +0200 Subject: [PATCH 521/798] Update wine32 dependencies for Ubuntu 22.04 --- .github/workflows/cmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index b7c2dcf555..63c48bbf21 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -264,9 +264,9 @@ jobs: cmake-args: -GNinja -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Memory - name: Ubuntu MinGW i686 - os: ubuntu-latest + os: ubuntu-22.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake - packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.34-7 libpcre2-8-0:i386=10.34-7 libodbc1=2.3.6-0.1build1 libodbc1:i386=2.3.6-0.1build1 libwine:i386=5.0-3ubuntu1 libgphoto2-6:i386=2.5.25-0ubuntu0.1 libsane:i386=1.0.29-0ubuntu5.2 libgd3=2.2.5-5.2ubuntu2.1 libgd3:i386=2.2.5-5.2ubuntu2.1 + packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.39-3ubuntu0.1 libpcre2-8-0:i386=10.39-3ubuntu0.1 libodbc1=2.3.9-5 libodbc1:i386=2.3.9-5 libwine:i386=6.0.3~repack-1 libgphoto2-6:i386=2.5.27-1build2 libsane:i386=1.1.1-5 libgd3=2.3.0-2ubuntu2 libgd3:i386=2.3.0-2ubuntu2 ldflags: -static codecov: ubuntu_gcc_mingw_i686 # Limit parallel test jobs to prevent wine errors From b1291a4b86c153b317a27ac6435171046fb9d010 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 19 Nov 2022 15:03:41 -0800 Subject: [PATCH 522/798] Fixed cast to smaller integer type on MSYS2 Clang64. zlib/crc32_braid.c:128:24: error: cast to smaller integer type 'unsigned long' from 'const uint8_t *' (aka 'const unsigned char *') --- crc32_braid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crc32_braid.c b/crc32_braid.c index 07af068de1..acdf37e923 100644 --- a/crc32_braid.c +++ b/crc32_braid.c @@ -125,7 +125,7 @@ Z_INTERNAL uint32_t crc32_braid(uint32_t crc, const uint8_t *buf, uint64_t len) int k; /* Compute the CRC up to a z_word_t boundary. */ - while (len && ((z_size_t)buf & (W - 1)) != 0) { + while (len && ((uintptr_t)buf & (W - 1)) != 0) { len--; DO1; } From 506b4389f9d82551717b854e6395fb84c5048fe3 Mon Sep 17 00:00:00 2001 From: LGTM Migrator Date: Wed, 9 Nov 2022 11:28:47 +0000 Subject: [PATCH 523/798] Add CodeQL workflow for GitHub code scanning --- .github/workflows/codeql.yml | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..1cfa4d7fa9 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,41 @@ +name: "CodeQL" + +on: + push: + branches: [ "develop" ] + pull_request: + branches: [ "develop" ] + schedule: + - cron: "27 17 * * 0" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ cpp ] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{ matrix.language }}" From 3eab3173ac7d1d53457452f3cd1eaeea5b2d43df Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Thu, 20 Oct 2022 02:28:47 +0200 Subject: [PATCH 524/798] IBM zSystems DFLTCC: Support inflate with small window There is no hardware control for DFLTCC window size, and because of that supporting small windows for deflate is not trivial: one has to make sure that DFLTCC does not emit large distances, which most likely entails somehow trimming the window and/or input in order to make sure that whave + avail_in <= wsize. But inflate is much easier: one only has to allocate enough space. Do that in dfltcc_alloc_window(), and also introduce ZCOPY_WINDOW() in order to copy everything, not just what the software implementation cares about. After this change, software and hardware window formats no longer match: the software will use wbits and wsize, and the hardware will use HB_BITS and HB_SIZE. Unlike deflate, inflate does not switch between software and hardware implementations mid-stream, which leaves only inflateSetDictionary() and inflateGetDictionary() interesting. --- arch/s390/README.md | 18 +++++----- arch/s390/dfltcc_common.c | 8 +++-- arch/s390/dfltcc_common.h | 3 ++ arch/s390/dfltcc_deflate.c | 42 ++---------------------- arch/s390/dfltcc_detail.h | 43 ++++++++++++++++++++++++ arch/s390/dfltcc_inflate.c | 67 +++++++++++++++++++++++++++++++++----- arch/s390/dfltcc_inflate.h | 16 +++++++++ inflate.c | 7 ++-- inflate_p.h | 5 +++ test/CMakeLists.txt | 1 + test/test_small_window.cc | 67 ++++++++++++++++++++++++++++++++++++++ 11 files changed, 216 insertions(+), 61 deletions(-) create mode 100644 test/test_small_window.cc diff --git a/arch/s390/README.md b/arch/s390/README.md index 18a7ca8cd9..2c3165412c 100644 --- a/arch/s390/README.md +++ b/arch/s390/README.md @@ -63,15 +63,15 @@ integrated with the rest of zlib-ng using hook macros. DFLTCC takes as arguments a parameter block, an input buffer, an output buffer and a window. `ZALLOC_DEFLATE_STATE()`, `ZALLOC_INFLATE_STATE()`, `ZFREE_STATE()`, `ZCOPY_DEFLATE_STATE()`, `ZCOPY_INFLATE_STATE()`, -`ZALLOC_WINDOW()` and `TRY_FREE_WINDOW()` macros encapsulate allocation -details for the parameter block (which is allocated alongside zlib-ng -state) and the window (which must be page-aligned). - -While inflate software and hardware window formats match, this is not -the case for deflate. Therefore, `deflateSetDictionary()` and -`deflateGetDictionary()` need special handling, which is triggered using -`DEFLATE_SET_DICTIONARY_HOOK()` and `DEFLATE_GET_DICTIONARY_HOOK()` -macros. +`ZALLOC_WINDOW()`, `ZCOPY_WINDOW()` and `TRY_FREE_WINDOW()` macros encapsulate +allocation details for the parameter block (which is allocated alongside +zlib-ng state) and the window (which must be page-aligned and large enough). + +Software and hardware window formats do not match, therefore, +`deflateSetDictionary()`, `deflateGetDictionary()`, `inflateSetDictionary()` +and `inflateGetDictionary()` need special handling, which is triggered using +`DEFLATE_SET_DICTIONARY_HOOK()`, `DEFLATE_GET_DICTIONARY_HOOK()`, +`INFLATE_SET_DICTIONARY_HOOK()` and `INFLATE_GET_DICTIONARY_HOOK()` macros. `deflateResetKeep()` and `inflateResetKeep()` update the DFLTCC parameter block using `DEFLATE_RESET_KEEP_HOOK()` and diff --git a/arch/s390/dfltcc_common.c b/arch/s390/dfltcc_common.c index 2937d8d645..78be718114 100644 --- a/arch/s390/dfltcc_common.c +++ b/arch/s390/dfltcc_common.c @@ -20,9 +20,9 @@ void Z_INTERNAL *PREFIX(dfltcc_alloc_window)(PREFIX3(streamp) strm, uInt items, void *w; /* To simplify freeing, we store the pointer to the allocated buffer right - * before the window. + * before the window. Note that DFLTCC always uses HB_SIZE bytes. */ - p = ZALLOC(strm, sizeof(void *) + items * size + PAGE_ALIGN, sizeof(unsigned char)); + p = ZALLOC(strm, sizeof(void *) + MAX(items * size, HB_SIZE) + PAGE_ALIGN, sizeof(unsigned char)); if (p == NULL) return NULL; w = ALIGN_UP((char *)p + sizeof(void *), PAGE_ALIGN); @@ -30,6 +30,10 @@ void Z_INTERNAL *PREFIX(dfltcc_alloc_window)(PREFIX3(streamp) strm, uInt items, return w; } +void Z_INTERNAL PREFIX(dfltcc_copy_window)(void *dest, const void *src, size_t n) { + memcpy(dest, src, MAX(n, HB_SIZE)); +} + void Z_INTERNAL PREFIX(dfltcc_free_window)(PREFIX3(streamp) strm, void *w) { if (w) ZFREE(strm, *(void **)((unsigned char *)w - sizeof(void *))); diff --git a/arch/s390/dfltcc_common.h b/arch/s390/dfltcc_common.h index 4f48bd9a4f..b73437411b 100644 --- a/arch/s390/dfltcc_common.h +++ b/arch/s390/dfltcc_common.h @@ -4,12 +4,15 @@ #include "zutil.h" void Z_INTERNAL *PREFIX(dfltcc_alloc_window)(PREFIX3(streamp) strm, uInt items, uInt size); +void Z_INTERNAL PREFIX(dfltcc_copy_window)(void *dest, const void *src, size_t n); void Z_INTERNAL PREFIX(dfltcc_free_window)(PREFIX3(streamp) strm, void *w); #define ZFREE_STATE ZFREE #define ZALLOC_WINDOW PREFIX(dfltcc_alloc_window) +#define ZCOPY_WINDOW PREFIX(dfltcc_copy_window) + #define ZFREE_WINDOW PREFIX(dfltcc_free_window) #define TRY_FREE_WINDOW PREFIX(dfltcc_free_window) diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index 0210ddc17f..ab3343aeab 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -376,36 +376,6 @@ int Z_INTERNAL PREFIX(dfltcc_can_set_reproducible)(PREFIX3(streamp) strm, int re /* Preloading history. */ -static void append_history(struct dfltcc_param_v0 *param, unsigned char *history, const unsigned char *buf, uInt count) { - size_t offset; - size_t n; - - /* Do not use more than 32K */ - if (count > HB_SIZE) { - buf += count - HB_SIZE; - count = HB_SIZE; - } - offset = (param->ho + param->hl) % HB_SIZE; - if (offset + count <= HB_SIZE) - /* Circular history buffer does not wrap - copy one chunk */ - memcpy(history + offset, buf, count); - else { - /* Circular history buffer wraps - copy two chunks */ - n = HB_SIZE - offset; - memcpy(history + offset, buf, n); - memcpy(history, buf + n, count - n); - } - n = param->hl + count; - if (n <= HB_SIZE) - /* All history fits into buffer - no need to discard anything */ - param->hl = n; - else { - /* History does not fit into buffer - discard extra bytes */ - param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE; - param->hl = HB_SIZE; - } -} - int Z_INTERNAL PREFIX(dfltcc_deflate_set_dictionary)(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length) { deflate_state *state = (deflate_state *)strm->state; @@ -423,16 +393,8 @@ int Z_INTERNAL PREFIX(dfltcc_deflate_get_dictionary)(PREFIX3(streamp) strm, unsi struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; - if (dictionary) { - if (param->ho + param->hl <= HB_SIZE) - /* Circular history buffer does not wrap - copy one chunk */ - memcpy(dictionary, state->window + param->ho, param->hl); - else { - /* Circular history buffer wraps - copy two chunks */ - memcpy(dictionary, state->window + param->ho, HB_SIZE - param->ho); - memcpy(dictionary + HB_SIZE - param->ho, state->window, param->ho + param->hl - HB_SIZE); - } - } + if (dictionary) + get_history(param, state->window, dictionary); if (dict_length) *dict_length = param->hl; return Z_OK; diff --git a/arch/s390/dfltcc_detail.h b/arch/s390/dfltcc_detail.h index e1d625b84a..354c2f5550 100644 --- a/arch/s390/dfltcc_detail.h +++ b/arch/s390/dfltcc_detail.h @@ -267,3 +267,46 @@ static inline void dfltcc_reset_state(struct dfltcc_state *dfltcc_state) { static inline void dfltcc_copy_state(void *dst, const void *src, uInt size, uInt extension_size) { memcpy(dst, src, ALIGN_UP(size, 8) + extension_size); } + +static inline void append_history(struct dfltcc_param_v0 *param, unsigned char *history, + const unsigned char *buf, uInt count) { + size_t offset; + size_t n; + + /* Do not use more than 32K */ + if (count > HB_SIZE) { + buf += count - HB_SIZE; + count = HB_SIZE; + } + offset = (param->ho + param->hl) % HB_SIZE; + if (offset + count <= HB_SIZE) + /* Circular history buffer does not wrap - copy one chunk */ + memcpy(history + offset, buf, count); + else { + /* Circular history buffer wraps - copy two chunks */ + n = HB_SIZE - offset; + memcpy(history + offset, buf, n); + memcpy(history, buf + n, count - n); + } + n = param->hl + count; + if (n <= HB_SIZE) + /* All history fits into buffer - no need to discard anything */ + param->hl = n; + else { + /* History does not fit into buffer - discard extra bytes */ + param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE; + param->hl = HB_SIZE; + } +} + +static inline void get_history(struct dfltcc_param_v0 *param, const unsigned char *history, + unsigned char *buf) { + if (param->ho + param->hl <= HB_SIZE) + /* Circular history buffer does not wrap - copy one chunk */ + memcpy(buf, history + param->ho, param->hl); + else { + /* Circular history buffer wraps - copy two chunks */ + memcpy(buf, history + param->ho, HB_SIZE - param->ho); + memcpy(buf + HB_SIZE - param->ho, history, param->ho + param->hl - HB_SIZE); + } +} diff --git a/arch/s390/dfltcc_inflate.c b/arch/s390/dfltcc_inflate.c index b7ecbe275c..34fbbb2278 100644 --- a/arch/s390/dfltcc_inflate.c +++ b/arch/s390/dfltcc_inflate.c @@ -39,10 +39,6 @@ int Z_INTERNAL PREFIX(dfltcc_can_inflate)(PREFIX3(streamp) strm) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - /* Unsupported compression settings */ - if (state->wbits != HB_BITS) - return 0; - /* Unsupported hardware */ return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) && is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0); } @@ -98,8 +94,6 @@ dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, i /* Translate stream to parameter block */ param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32; param->sbb = state->bits; - param->hl = state->whave; /* Software and hardware history formats match */ - param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1); if (param->hl) param->nt = 0; /* Honor history for the first block */ param->cv = state->flags ? ZSWAP32(state->check) : state->check; @@ -113,8 +107,6 @@ dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, i strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); state->last = cc == DFLTCC_CC_OK; state->bits = param->sbb; - state->whave = param->hl; - state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1); strm->adler = state->check = state->flags ? ZSWAP32(param->cv) : param->cv; if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) { /* Report an error if stream is corrupted */ @@ -134,9 +126,33 @@ int Z_INTERNAL PREFIX(dfltcc_was_inflate_used)(PREFIX3(streamp) strm) { return !param->nt; } +/* + Rotates a circular buffer. + The implementation is based on https://cplusplus.com/reference/algorithm/rotate/ + */ +static void rotate(unsigned char *start, unsigned char *pivot, unsigned char *end) { + unsigned char *p = pivot; + unsigned char tmp; + + while (p != start) { + tmp = *start; + *start = *p; + *p = tmp; + + start++; + p++; + + if (p == end) + p = pivot; + else if (start == pivot) + pivot = p; + } +} + int Z_INTERNAL PREFIX(dfltcc_inflate_disable)(PREFIX3(streamp) strm) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); + struct dfltcc_param_v0 *param = &dfltcc_state->param; if (!PREFIX(dfltcc_can_inflate)(strm)) return 0; @@ -148,5 +164,40 @@ int Z_INTERNAL PREFIX(dfltcc_inflate_disable)(PREFIX3(streamp) strm) { return 1; /* DFLTCC was not used yet - decompress in software */ memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); + /* Convert the window from the hardware to the software format */ + rotate(state->window, state->window + param->ho, state->window + HB_SIZE); + state->whave = state->wnext = MIN(param->hl, state->wsize); return 0; } + +/* + Preloading history. +*/ +int Z_INTERNAL PREFIX(dfltcc_inflate_set_dictionary)(PREFIX3(streamp) strm, + const unsigned char *dictionary, uInt dict_length) { + struct inflate_state *state = (struct inflate_state *)strm->state; + struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); + struct dfltcc_param_v0 *param = &dfltcc_state->param; + + if (PREFIX(inflate_ensure_window)(state)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + + append_history(param, state->window, dictionary, dict_length); + state->havedict = 1; + return Z_OK; +} + +int Z_INTERNAL PREFIX(dfltcc_inflate_get_dictionary)(PREFIX3(streamp) strm, + unsigned char *dictionary, uInt *dict_length) { + struct inflate_state *state = (struct inflate_state *)strm->state; + struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); + struct dfltcc_param_v0 *param = &dfltcc_state->param; + + if (dictionary && state->window) + get_history(param, state->window, dictionary); + if (dict_length) + *dict_length = param->hl; + return Z_OK; +} diff --git a/arch/s390/dfltcc_inflate.h b/arch/s390/dfltcc_inflate.h index 5e86fe87f4..632fada621 100644 --- a/arch/s390/dfltcc_inflate.h +++ b/arch/s390/dfltcc_inflate.h @@ -15,6 +15,10 @@ typedef enum { dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, int flush, int *ret); int Z_INTERNAL PREFIX(dfltcc_was_inflate_used)(PREFIX3(streamp) strm); int Z_INTERNAL PREFIX(dfltcc_inflate_disable)(PREFIX3(streamp) strm); +int Z_INTERNAL PREFIX(dfltcc_inflate_set_dictionary)(PREFIX3(streamp) strm, + const unsigned char *dictionary, uInt dict_length); +int Z_INTERNAL PREFIX(dfltcc_inflate_get_dictionary)(PREFIX3(streamp) strm, + unsigned char *dictionary, uInt* dict_length); #define ZALLOC_INFLATE_STATE PREFIX(dfltcc_alloc_inflate_state) #define ZCOPY_INFLATE_STATE PREFIX(dfltcc_copy_inflate_state) @@ -51,4 +55,16 @@ int Z_INTERNAL PREFIX(dfltcc_inflate_disable)(PREFIX3(streamp) strm); if (PREFIX(dfltcc_was_inflate_used)((strm))) return Z_STREAM_ERROR; \ } while (0) +#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \ + do { \ + if (PREFIX(dfltcc_can_inflate)((strm))) \ + return PREFIX(dfltcc_inflate_set_dictionary)((strm), (dict), (dict_len)); \ + } while (0) + +#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \ + do { \ + if (PREFIX(dfltcc_can_inflate)((strm))) \ + return PREFIX(dfltcc_inflate_get_dictionary)((strm), (dict), (dict_len)); \ + } while (0) + #endif diff --git a/inflate.c b/inflate.c index ead160df8e..c4de058436 100644 --- a/inflate.c +++ b/inflate.c @@ -1157,6 +1157,8 @@ int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *di return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; + INFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ + /* copy dictionary */ if (state->whave && dictionary != NULL) { memcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); @@ -1186,6 +1188,8 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8 return Z_DATA_ERROR; } + INFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ + /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ ret = updatewindow(strm, dictionary + dictLength, dictLength, 0); @@ -1349,8 +1353,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou } copy->next = copy->codes + (state->next - state->codes); if (window != NULL) { - wsize = 1U << state->wbits; - memcpy(window, state->window, wsize); + ZCOPY_WINDOW(window, state->window, 1U << state->wbits); } copy->window = window; dest->state = (struct internal_state *)copy; diff --git a/inflate_p.h b/inflate_p.h index 7122d7ce65..e3daae1e1c 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -17,6 +17,7 @@ # define ZCOPY_INFLATE_STATE(dst, src) memcpy(dst, src, sizeof(struct inflate_state)) /* Memory management for the window. Useful for allocation the aligned window. */ # define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) +# define ZCOPY_WINDOW(dest, src, n) memcpy(dest, src, n) # define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr) /* Invoked at the end of inflateResetKeep(). Useful for initializing arch-specific extension blocks. */ # define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0) @@ -32,6 +33,10 @@ # define INFLATE_MARK_HOOK(strm) do {} while (0) /* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */ # define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) +/* Invoked at the beginning of inflateSetDictionary(). Useful for checking arch-specific window data. */ +# define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) +/* Invoked at the beginning of inflateGetDictionary(). Useful for adjusting arch-specific window data. */ +# define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) #endif /* diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3bf1f76734..a5b4d7590a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -168,6 +168,7 @@ else() test_inflate_adler32.cc test_large_buffers.cc test_small_buffers.cc + test_small_window.cc ) if(WITH_GZFILEOP) diff --git a/test/test_small_window.cc b/test/test_small_window.cc new file mode 100644 index 0000000000..e351efac0d --- /dev/null +++ b/test/test_small_window.cc @@ -0,0 +1,67 @@ +/* test_small_window.cc - Test deflate() and inflate() with a small window and a preset dictionary */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include + +TEST(small_window, basic) { + PREFIX3(stream) stream; + int err; + unsigned char plain[128]; + unsigned char dictionary1[(1 << 9) - sizeof(plain) / 2]; + size_t i; + unsigned char compr[sizeof(plain)]; + unsigned int compr_len; + unsigned char plain_again[sizeof(plain)]; + + memset(&stream, 0, sizeof(stream)); + err = PREFIX(deflateInit2)(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, -9, 8, Z_DEFAULT_STRATEGY); + EXPECT_EQ(err, Z_OK); + + /* Use a large dictionary that is loaded in two parts */ + memset(dictionary1, 'a', sizeof(dictionary1)); + err = PREFIX(deflateSetDictionary)(&stream, dictionary1, (unsigned int)sizeof(dictionary1)); + EXPECT_EQ(err, Z_OK); + for (i = 0; i < sizeof(plain); i++) + plain[i] = (unsigned char)i; + err = PREFIX(deflateSetDictionary)(&stream, plain, (unsigned int)sizeof(plain)); + EXPECT_EQ(err, Z_OK); + + stream.next_in = plain; + stream.avail_in = (uint32_t)sizeof(plain); + stream.next_out = compr; + stream.avail_out = (uint32_t)sizeof(compr); + err = PREFIX(deflate)(&stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + compr_len = sizeof(compr) - stream.avail_out; + + err = PREFIX(deflateEnd)(&stream); + EXPECT_EQ(err, Z_OK); + + memset(&stream, 0, sizeof(stream)); + err = PREFIX(inflateInit2)(&stream, -9); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(inflateSetDictionary)(&stream, dictionary1, (unsigned int)sizeof(dictionary1)); + EXPECT_EQ(err, Z_OK); + err = PREFIX(inflateSetDictionary)(&stream, plain, (unsigned int)sizeof(plain)); + EXPECT_EQ(err, Z_OK); + + stream.next_in = compr; + stream.avail_in = compr_len; + stream.next_out = plain_again; + stream.avail_out = (unsigned int)sizeof(plain_again); + + err = PREFIX(inflate)(&stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_STREAM_END); + + err = PREFIX(inflateEnd)(&stream); + EXPECT_EQ(err, Z_OK); + + EXPECT_TRUE(memcmp(plain_again, plain, sizeof(plain)) == 0); +} From 31ce5efac4598fd5aedecbb51c75189f773ca82f Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Sun, 11 Dec 2022 16:26:00 +0200 Subject: [PATCH 525/798] llvm-cov-11 needs llvm-11 on Ubuntu 22.04. --- .github/workflows/cmake.yml | 12 ++++++------ .github/workflows/pigz.yml | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 63c48bbf21..d78aa5e0f9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -291,7 +291,7 @@ jobs: os: ubuntu-latest compiler: clang-11 cxx-compiler: clang++-11 - packages: clang-11 llvm-11-tools + packages: clang-11 llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang @@ -300,7 +300,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cmake-args: -DWITH_INFLATE_STRICT=ON - packages: clang-11 llvm-11-tools + packages: clang-11 llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_inflate_strict @@ -309,7 +309,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cmake-args: -DWITH_INFLATE_ALLOW_INVALID_DIST=ON - packages: clang-11 llvm-11-tools + packages: clang-11 llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_inflate_allow_invalid_dist @@ -318,7 +318,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cmake-args: -DWITH_REDUCED_MEM=ON - packages: clang-11 llvm-11-tools + packages: clang-11 llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_reduced_mem @@ -327,7 +327,7 @@ jobs: compiler: clang-11 cxx-compiler: clang++-11 cflags: -DUSE_MMAP - packages: clang-11 llvm-11-tools + packages: clang-11 llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_mmap @@ -335,7 +335,7 @@ jobs: os: ubuntu-latest compiler: clang-11 cxx-compiler: clang++-11 - packages: clang-11 llvm-11-tools + packages: clang-11 llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_debug build-config: Debug diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index fc604200b4..4400892440 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -22,14 +22,14 @@ jobs: - name: Ubuntu Clang os: ubuntu-latest compiler: clang - packages: llvm-11-tools + packages: llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_pigz - name: Ubuntu Clang No Optim os: ubuntu-latest compiler: clang - packages: llvm-11-tools + packages: llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_pigz_no_optim cmake-args: -DWITH_OPTIM=OFF @@ -38,7 +38,7 @@ jobs: - name: Ubuntu Clang No Threads os: ubuntu-latest compiler: clang - packages: llvm-11-tools + packages: llvm-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_pigz_no_threads cmake-args: -DWITH_THREADS=OFF -DPIGZ_VERSION=v2.6 From 06b579a3c46d84aeeb3d104d1d55f5e6bbe92359 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Thu, 15 Dec 2022 06:51:51 +0200 Subject: [PATCH 526/798] Tell scan-build ASSERT_TRUE() behaves like assert(). --- test/test_aligned_alloc.cc | 2 ++ test/test_compare256.cc | 3 +++ test/test_compress_bound.cc | 4 ++-- test/test_deflate_bound.cc | 4 ++-- test/test_deflate_dict.cc | 4 ++-- test/test_deflate_header.cc | 4 ++-- test/test_deflate_params.cc | 4 ++-- test/test_deflate_pending.cc | 4 ++-- test/test_gzio.cc | 4 ++-- test/test_large_buffers.cc | 4 ++-- test/test_shared.h | 6 ++++++ 11 files changed, 27 insertions(+), 16 deletions(-) diff --git a/test/test_aligned_alloc.cc b/test/test_aligned_alloc.cc index 259d474b87..de73c7ec32 100644 --- a/test/test_aligned_alloc.cc +++ b/test/test_aligned_alloc.cc @@ -11,6 +11,8 @@ extern "C" { #include +#include "test_shared.h" + void *zng_calloc_unaligned(void *opaque, unsigned items, unsigned size) { uint8_t *pointer = (uint8_t *)calloc(1, (items * size) + 2); Z_UNUSED(opaque); diff --git a/test/test_compare256.cc b/test/test_compare256.cc index 7c4dab9899..663ad96334 100644 --- a/test/test_compare256.cc +++ b/test/test_compare256.cc @@ -15,8 +15,11 @@ extern "C" { #include +#include "test_shared.h" + #define MAX_COMPARE_SIZE (256) + /* Ensure that compare256 returns the correct match length */ static inline void compare256_match_check(compare256_func compare256) { int32_t match_len, i; diff --git a/test/test_compress_bound.cc b/test/test_compress_bound.cc index cd5f6e5b95..d51452b235 100644 --- a/test/test_compress_bound.cc +++ b/test/test_compress_bound.cc @@ -12,10 +12,10 @@ #include #include -#include "test_shared.h" - #include +#include "test_shared.h" + #define MAX_LENGTH (32) class compress_bound_variant : public testing::TestWithParam { diff --git a/test/test_deflate_bound.cc b/test/test_deflate_bound.cc index 27020c6f92..8de65535f2 100644 --- a/test/test_deflate_bound.cc +++ b/test/test_deflate_bound.cc @@ -12,10 +12,10 @@ #include #include -#include "test_shared.h" - #include +#include "test_shared.h" + #define MAX_LENGTH (32) typedef struct { diff --git a/test/test_deflate_dict.cc b/test/test_deflate_dict.cc index 7a060a8dea..781c70db27 100644 --- a/test/test_deflate_dict.cc +++ b/test/test_deflate_dict.cc @@ -12,10 +12,10 @@ #include #include -#include "test_shared.h" - #include +#include "test_shared.h" + TEST(deflate, dictionary) { PREFIX3(stream) c_stream; uint8_t compr[128]; diff --git a/test/test_deflate_header.cc b/test/test_deflate_header.cc index 92f4612089..46d3478c1e 100644 --- a/test/test_deflate_header.cc +++ b/test/test_deflate_header.cc @@ -12,10 +12,10 @@ #include #include -#include "test_shared.h" - #include +#include "test_shared.h" + TEST(deflate, header) { PREFIX3(stream) c_stream; PREFIX(gz_header) *head; diff --git a/test/test_deflate_params.cc b/test/test_deflate_params.cc index f5f5066ad1..9fadea85f9 100644 --- a/test/test_deflate_params.cc +++ b/test/test_deflate_params.cc @@ -16,10 +16,10 @@ #include "deflate.h" -#include "test_shared.h" - #include +#include "test_shared.h" + #define COMPR_BUFFER_SIZE (48 * 1024) #define UNCOMPR_BUFFER_SIZE (64 * 1024) #define UNCOMPR_RAND_SIZE (8 * 1024) diff --git a/test/test_deflate_pending.cc b/test/test_deflate_pending.cc index b107dd43c1..8ccedbf33d 100644 --- a/test/test_deflate_pending.cc +++ b/test/test_deflate_pending.cc @@ -12,10 +12,10 @@ #include #include -#include "test_shared.h" - #include +#include "test_shared.h" + TEST(deflate, pending) { PREFIX3(stream) c_stream; uint8_t compr[128]; diff --git a/test/test_gzio.cc b/test/test_gzio.cc index 59e46f520a..3cab1dbe40 100644 --- a/test/test_gzio.cc +++ b/test/test_gzio.cc @@ -12,10 +12,10 @@ #include #include -#include "test_shared.h" - #include +#include "test_shared.h" + #define TESTFILE "foo.gz" TEST(gzip, readwrite) { diff --git a/test/test_large_buffers.cc b/test/test_large_buffers.cc index 9bf133998a..3c1208140d 100644 --- a/test/test_large_buffers.cc +++ b/test/test_large_buffers.cc @@ -13,10 +13,10 @@ #include #include -#include "test_shared.h" - #include +#include "test_shared.h" + #define COMPR_BUFFER_SIZE (48 * 1024) #define UNCOMPR_BUFFER_SIZE (32 * 1024) #define UNCOMPR_RAND_SIZE (8 * 1024) diff --git a/test/test_shared.h b/test/test_shared.h index df92a56b3b..616f57342c 100644 --- a/test/test_shared.h +++ b/test/test_shared.h @@ -9,4 +9,10 @@ static const char hello[] = "hello, hello!"; static const int hello_len = sizeof(hello); +/* Clang static analyzer doesn't understand googletest's ASSERT_TRUE, so we need to tell that it's like assert() */ +#ifdef __clang_analyzer__ +# undef ASSERT_TRUE +# define ASSERT_TRUE assert +#endif + #endif From b4d728fe43e474b8cd9dce12c5aa35105ad8d89b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 27 Dec 2022 15:25:07 -0800 Subject: [PATCH 527/798] Use Clang 11.1.0 sources same as Clang version on Ubuntu 22. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index d78aa5e0f9..bdc489f802 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -490,7 +490,7 @@ jobs: - name: Compile LLVM C++ libraries (MSAN) if: contains(matrix.name, 'MSAN') run: | - git clone --depth=1 https://github.com/llvm/llvm-project --single-branch --branch llvmorg-11.0.0 + git clone --depth=1 https://github.com/llvm/llvm-project --single-branch --branch llvmorg-11.1.0 cmake -S llvm-project/llvm -B llvm-project/build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" \ From 30fceb80d5d8589381e68ed86cffe7d738334157 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 27 Dec 2022 15:27:13 -0800 Subject: [PATCH 528/798] Fixed MSAN failed to allocate error on Ubuntu 22. https://github.com/llvm/llvm-project/issues/55785 --- .github/workflows/cmake.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index bdc489f802..02461eeda1 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -347,6 +347,8 @@ jobs: cmake-args: -GNinja -DWITH_SANITIZER=Memory packages: ninja-build clang-11 llvm-11-tools gcov-exec: llvm-cov-11 gcov + # https://github.com/llvm/llvm-project/issues/55785 + msan-options: use_sigaltstack=0 - name: Ubuntu Emscripten WASM32 os: ubuntu-latest From 435d3b931b959a42f493fe488c121b483fe785a3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 27 Dec 2022 14:24:40 -0800 Subject: [PATCH 529/798] Force sparc64 to ubuntu 20.04 to prevent segfault. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 02461eeda1..754df5bccc 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -218,7 +218,7 @@ jobs: codecov: ubuntu_gcc_ppc64le - name: Ubuntu GCC SPARC64 - os: ubuntu-latest + os: ubuntu-20.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake packages: qemu qemu-user gcc-sparc64-linux-gnu g++-sparc64-linux-gnu libc-dev-sparc64-cross ldflags: -static From c4e7e231c80f1182e0e85301e4ccc8b17457e02e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 27 Dec 2022 14:42:22 -0800 Subject: [PATCH 530/798] Force ppc64le to ubuntu 20.04 to prevent illegal instruction. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 754df5bccc..11ed5311a1 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -212,7 +212,7 @@ jobs: codecov: ubuntu_gcc_ppc64 - name: Ubuntu GCC PPC64LE - os: ubuntu-latest + os: ubuntu-20.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake packages: qemu qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc-dev-ppc64el-cross codecov: ubuntu_gcc_ppc64le From 2ff9398fded2f1bec8b42c0e27002de9f80bbe74 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Thu, 22 Dec 2022 10:34:57 +0100 Subject: [PATCH 531/798] IBM zSystems DFLTCC: Do not update strm.adler for raw streams Commit d38dd9240f2d ("IBM Z DFLTCC: Fix updating strm.adler with inflate()") broke libxml2, as can be seen with the repro from [1]: $ echo "" | gzip >file.xml.gz $ python3 -c 'import libxml2; libxml2.parseFile("file.xml.gz")' file.xml.gz:1: parser error : Document is empty This is because libxml2 expects strm.adler to be untouched for raw streams. Fix this and a similar issue in deflate by adding state->wrap checks. Add tests. [1] https://bugzilla.redhat.com/show_bug.cgi?id=2155328 [2] https://gitlab.gnome.org/GNOME/libxml2/-/blob/v2.10.3/xzlib.c#L607 --- arch/s390/dfltcc_deflate.c | 11 ++++--- arch/s390/dfltcc_inflate.c | 8 +++-- test/CMakeLists.txt | 1 + test/test_deflate_header.cc | 3 ++ test/test_raw.cc | 58 +++++++++++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 test/test_raw.cc diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index ab3343aeab..3ad988afc7 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -240,7 +240,10 @@ int Z_INTERNAL PREFIX(dfltcc_deflate)(PREFIX3(streamp) strm, int flush, block_st *strm->next_out = (unsigned char)state->bi_buf; /* Honor history and check value */ param->nt = 0; - param->cv = state->wrap == 2 ? ZSWAP32(state->crc_fold.value) : strm->adler; + if (state->wrap == 1) + param->cv = strm->adler; + else if (state->wrap == 2) + param->cv = ZSWAP32(state->crc_fold.value); /* When opening a block, choose a Huffman-Table Type */ if (!param->bcf) { @@ -271,10 +274,10 @@ int Z_INTERNAL PREFIX(dfltcc_deflate)(PREFIX3(streamp) strm, int flush, block_st state->bi_buf = 0; /* Avoid accessing next_out */ else state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1); - if (state->wrap == 2) - state->crc_fold.value = ZSWAP32(param->cv); - else + if (state->wrap == 1) strm->adler = param->cv; + else if (state->wrap == 2) + state->crc_fold.value = ZSWAP32(param->cv); /* Unmask the input data */ strm->avail_in += masked_avail_in; diff --git a/arch/s390/dfltcc_inflate.c b/arch/s390/dfltcc_inflate.c index 34fbbb2278..f0d3951b59 100644 --- a/arch/s390/dfltcc_inflate.c +++ b/arch/s390/dfltcc_inflate.c @@ -92,11 +92,12 @@ dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, i } /* Translate stream to parameter block */ - param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32; + param->cvt = ((state->wrap & 4) && state->flags) ? CVT_CRC32 : CVT_ADLER32; param->sbb = state->bits; if (param->hl) param->nt = 0; /* Honor history for the first block */ - param->cv = state->flags ? ZSWAP32(state->check) : state->check; + if (state->wrap & 4) + param->cv = state->flags ? ZSWAP32(state->check) : state->check; /* Inflate */ do { @@ -107,7 +108,8 @@ dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, i strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); state->last = cc == DFLTCC_CC_OK; state->bits = param->sbb; - strm->adler = state->check = state->flags ? ZSWAP32(param->cv) : param->cv; + if (state->wrap & 4) + strm->adler = state->check = state->flags ? ZSWAP32(param->cv) : param->cv; if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) { /* Report an error if stream is corrupted */ state->mode = BAD; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a5b4d7590a..55a3057be7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -167,6 +167,7 @@ else() test_dict.cc test_inflate_adler32.cc test_large_buffers.cc + test_raw.cc test_small_buffers.cc test_small_window.cc ) diff --git a/test/test_deflate_header.cc b/test/test_deflate_header.cc index 46d3478c1e..0d1b7d0443 100644 --- a/test/test_deflate_header.cc +++ b/test/test_deflate_header.cc @@ -61,6 +61,9 @@ TEST(deflate, header) { EXPECT_EQ(err, Z_OK); } + /* Check CRC32. */ + EXPECT_EQ(c_stream.adler, 0xb56c3f9dU); + err = PREFIX(deflateEnd)(&c_stream); EXPECT_EQ(err, Z_OK); diff --git a/test/test_raw.cc b/test/test_raw.cc new file mode 100644 index 0000000000..69959d9e03 --- /dev/null +++ b/test/test_raw.cc @@ -0,0 +1,58 @@ +/* test_raw.cc - Test raw streams. */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include + +TEST(raw, basic) { + PREFIX3(stream) stream; + int err; + unsigned char plain[512]; + size_t i; + unsigned char compr[sizeof(plain)]; + unsigned int compr_len; + unsigned char plain_again[sizeof(plain)]; + + memset(&stream, 0, sizeof(stream)); + err = PREFIX(deflateInit2)(&stream, Z_BEST_SPEED, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + EXPECT_EQ(err, Z_OK); + + for (i = 0; i < sizeof(plain); i++) + plain[i] = (unsigned char)i; + stream.adler = 0x12345678; + stream.next_in = plain; + stream.avail_in = (uint32_t)sizeof(plain); + stream.next_out = compr; + stream.avail_out = (uint32_t)sizeof(compr); + err = PREFIX(deflate)(&stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + EXPECT_EQ(stream.adler, 0x12345678); + compr_len = sizeof(compr) - stream.avail_out; + + err = PREFIX(deflateEnd)(&stream); + EXPECT_EQ(err, Z_OK); + + memset(&stream, 0, sizeof(stream)); + err = PREFIX(inflateInit2)(&stream, -15); + EXPECT_EQ(err, Z_OK); + + stream.adler = 0x87654321; + stream.next_in = compr; + stream.avail_in = compr_len; + stream.next_out = plain_again; + stream.avail_out = (unsigned int)sizeof(plain_again); + + err = PREFIX(inflate)(&stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_STREAM_END); + EXPECT_EQ(stream.adler, 0x87654321); + + err = PREFIX(inflateEnd)(&stream); + EXPECT_EQ(err, Z_OK); + + EXPECT_TRUE(memcmp(plain_again, plain, sizeof(plain)) == 0); +} From 8d93a9895ba15b9dbcbfb97b3d8e15ace128a152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Thu, 4 Aug 2022 17:47:33 -0400 Subject: [PATCH 532/798] Increase ghostflow-director max-size for crc32_braid_tbl.h --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 49d4490d70..0b0d147e62 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ * text=auto *.c text *.h text +crc32_braid_tbl.h hooks-max-size=1000000 Makefile text configure text eol=lf From f0d3a28388693262947de6311294ddf09bf775d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Thu, 4 Aug 2022 16:55:30 -0400 Subject: [PATCH 533/798] Add missing symbol name mangling See https://github.com/InsightSoftwareConsortium/ITK/issues/3530 --- zlib_name_mangling-ng.h.in | 15 ++++++++++++++- zlib_name_mangling.h.in | 13 +++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/zlib_name_mangling-ng.h.in b/zlib_name_mangling-ng.h.in index 78ab9e3ef1..58f0728c6c 100644 --- a/zlib_name_mangling-ng.h.in +++ b/zlib_name_mangling-ng.h.in @@ -48,6 +48,9 @@ #define zng_deflateSetHeader @ZLIB_SYMBOL_PREFIX@zng_deflateSetHeader #define zng_deflateTune @ZLIB_SYMBOL_PREFIX@zng_deflateTune #define zng_deflate_copyright @ZLIB_SYMBOL_PREFIX@zng_deflate_copyright +#define zng_fill_window @ZLIB_SYMBOL_PREFIX@zng_fill_window +#define zng_fixedtables @ZLIB_SYMBOL_PREFIX@zng_fixedtables +#define zng_flush_pending @ZLIB_SYMBOL_PREFIX@zng_flush_pending #define zng_get_crc_table @ZLIB_SYMBOL_PREFIX@zng_get_crc_table #ifndef Z_SOLO # define zng_gz_error @ZLIB_SYMBOL_PREFIX@zng_gz_error @@ -113,8 +116,10 @@ #define zng_inflateUndermine @ZLIB_SYMBOL_PREFIX@zng_inflateUndermine #define zng_inflateValidate @ZLIB_SYMBOL_PREFIX@zng_inflateValidate #define zng_inflate_copyright @ZLIB_SYMBOL_PREFIX@zng_inflate_copyright +#define zng_inflate_ensure_window @ZLIB_SYMBOL_PREFIX@zng_inflate_ensure_window #define zng_inflate_fast @ZLIB_SYMBOL_PREFIX@zng_inflate_fast #define zng_inflate_table @ZLIB_SYMBOL_PREFIX@zng_inflate_table +#define zng_read_buf @ZLIB_SYMBOL_PREFIX@zng_read_buf #ifndef Z_SOLO # define zng_uncompress @ZLIB_SYMBOL_PREFIX@zng_uncompress # define zng_uncompress2 @ZLIB_SYMBOL_PREFIX@zng_uncompress2 @@ -153,6 +158,9 @@ #define zng_gz_header_s @ZLIB_SYMBOL_PREFIX@zng_gz_header_s #define internal_state @ZLIB_SYMBOL_PREFIX@internal_state +/* all zlib structs in zutil.h */ +#define zlibng_string @ZLIB_SYMBOL_PREFIX@zlibng_string + /* zlib-ng specific symbols */ #define zng_deflate_param @ZLIB_SYMBOL_PREFIX@zng_deflate_param #define zng_deflate_param_value @ZLIB_SYMBOL_PREFIX@zng_deflate_param_value @@ -161,8 +169,13 @@ #define zlibng_version @ZLIB_SYMBOL_PREFIX@zlibng_version #define zng_zError @ZLIB_SYMBOL_PREFIX@zng_zError -#define zng_inflateSyncPoint @ZLIB_SYMBOL_PREFIX@zng_inflateSyncPoint + +#define zng_alloc_aligned @ZLIB_SYMBOL_PREFIX@zng_alloc_aligned +#define zng_calloc @ZLIB_SYMBOL_PREFIX@zng_calloc +#define zng_cfree @ZLIB_SYMBOL_PREFIX@zng_cfree +#define zng_free_aligned @ZLIB_SYMBOL_PREFIX@zng_free_aligned #define zng_get_crc_table @ZLIB_SYMBOL_PREFIX@zng_get_crc_table +#define zng_inflateSyncPoint @ZLIB_SYMBOL_PREFIX@zng_inflateSyncPoint #define zng_inflateUndermine @ZLIB_SYMBOL_PREFIX@zng_inflateUndermine #define zng_inflateValidate @ZLIB_SYMBOL_PREFIX@zng_inflateValidate #define zng_inflateCodesUsed @ZLIB_SYMBOL_PREFIX@zng_inflateCodesUsed diff --git a/zlib_name_mangling.h.in b/zlib_name_mangling.h.in index 5a1b2cea7e..4b150eaa77 100644 --- a/zlib_name_mangling.h.in +++ b/zlib_name_mangling.h.in @@ -48,6 +48,9 @@ #define deflateSetHeader @ZLIB_SYMBOL_PREFIX@deflateSetHeader #define deflateTune @ZLIB_SYMBOL_PREFIX@deflateTune #define deflate_copyright @ZLIB_SYMBOL_PREFIX@deflate_copyright +#define fill_window @ZLIB_SYMBOL_PREFIX@fill_window +#define fixedtables @ZLIB_SYMBOL_PREFIX@fixedtables +#define flush_pending @ZLIB_SYMBOL_PREFIX@flush_pending #define get_crc_table @ZLIB_SYMBOL_PREFIX@get_crc_table #ifndef Z_SOLO # define gz_error @ZLIB_SYMBOL_PREFIX@gz_error @@ -113,8 +116,10 @@ #define inflateUndermine @ZLIB_SYMBOL_PREFIX@inflateUndermine #define inflateValidate @ZLIB_SYMBOL_PREFIX@inflateValidate #define inflate_copyright @ZLIB_SYMBOL_PREFIX@inflate_copyright +#define inflate_ensure_window @ZLIB_SYMBOL_PREFIX@inflate_ensure_window #define inflate_fast @ZLIB_SYMBOL_PREFIX@inflate_fast #define inflate_table @ZLIB_SYMBOL_PREFIX@inflate_table +#define read_buf @ZLIB_SYMBOL_PREFIX@read_buf #ifndef Z_SOLO # define uncompress @ZLIB_SYMBOL_PREFIX@uncompress # define uncompress2 @ZLIB_SYMBOL_PREFIX@uncompress2 @@ -155,5 +160,13 @@ /* all zlib structs in zutil.h */ #define z_errmsg @ZLIB_SYMBOL_PREFIX@z_errmsg +#define zlibng_string @ZLIB_SYMBOL_PREFIX@zlibng_string +#define zlibng_version @ZLIB_SYMBOL_PREFIX@zlibng_version + +/* zlib-ng specific symbols */ +#define zng_alloc_aligned @ZLIB_SYMBOL_PREFIX@zng_alloc_aligned +#define zng_calloc @ZLIB_SYMBOL_PREFIX@zng_calloc +#define zng_cfree @ZLIB_SYMBOL_PREFIX@zng_cfree +#define zng_free_aligned @ZLIB_SYMBOL_PREFIX@zng_free_aligned #endif /* ZLIB_NAME_MANGLING_H */ From b047c7247f1c0f3c8ee07545fe794c1ca0f4f1fc Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 25 Jun 2022 15:25:22 -0700 Subject: [PATCH 534/798] Prefix shared functions to prevent symbol conflict when linking native api against compat api. --- arch/s390/crc32-vx.c | 6 +++--- arch/x86/crc32_fold_pclmulqdq.c | 2 +- cpu_features.h | 2 +- crc32_braid.c | 2 +- crc32_braid_p.h | 2 +- deflate.c | 14 +++++++------- deflate.h | 2 +- deflate_fast.c | 2 +- deflate_huff.c | 2 +- deflate_medium.c | 2 +- deflate_p.h | 2 +- deflate_quick.c | 2 +- deflate_rle.c | 2 +- deflate_slow.c | 2 +- deflate_stored.c | 4 ++-- functable.c | 2 +- infback.c | 6 +++--- inflate.c | 8 ++++---- inflate.h | 2 +- test/benchmarks/benchmark_crc32.cc | 2 +- test/test_aligned_alloc.cc | 4 ++-- test/test_crc32.cc | 2 +- zutil.c | 24 ++++++++++++------------ zutil.h | 12 ++++++------ 24 files changed, 55 insertions(+), 55 deletions(-) diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index 340846083e..a64d629166 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -202,12 +202,12 @@ uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf uint64_t prealign, aligned, remaining; if (len < VX_MIN_LEN + VX_ALIGN_MASK) - return crc32_braid(crc, buf, len); + return PREFIX(crc32_braid)(crc, buf, len); if ((uintptr_t)buf & VX_ALIGN_MASK) { prealign = VX_ALIGNMENT - ((uintptr_t)buf & VX_ALIGN_MASK); len -= prealign; - crc = crc32_braid(crc, buf, prealign); + crc = PREFIX(crc32_braid)(crc, buf, prealign); buf += prealign; } aligned = len & ~VX_ALIGN_MASK; @@ -216,7 +216,7 @@ uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf crc = crc32_le_vgfm_16(crc ^ 0xffffffff, buf, (size_t)aligned) ^ 0xffffffff; if (remaining) - crc = crc32_braid(crc, buf + aligned, remaining); + crc = PREFIX(crc32_braid)(crc, buf + aligned, remaining); return crc; } diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 5754b8d713..aff1f80659 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -346,7 +346,7 @@ uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, uint64_t len) { /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for * these short lengths might also prove to be effective */ if (len < 64) - return crc32_braid(crc32, buf, len); + return PREFIX(crc32_braid)(crc32, buf, len); crc32_fold ALIGNED_(16) crc_state; crc32_fold_pclmulqdq_reset(&crc_state); diff --git a/cpu_features.h b/cpu_features.h index 84c5115632..b8de4b71e7 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -113,7 +113,7 @@ extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned le /* CRC32 */ typedef uint32_t (*crc32_func)(uint32_t crc32, const uint8_t *buf, uint64_t len); -extern uint32_t crc32_braid(uint32_t crc, const uint8_t *buf, uint64_t len); +extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, uint64_t len); #ifdef ARM_ACLE_CRC_HASH extern uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len); #elif defined(POWER8_VSX_CRC32) diff --git a/crc32_braid.c b/crc32_braid.c index acdf37e923..a7b9b7ebfc 100644 --- a/crc32_braid.c +++ b/crc32_braid.c @@ -111,7 +111,7 @@ static z_word_t crc_word(z_word_t data) { #endif /* W */ /* ========================================================================= */ -Z_INTERNAL uint32_t crc32_braid(uint32_t crc, const uint8_t *buf, uint64_t len) { +Z_INTERNAL uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, uint64_t len) { Z_REGISTER uint32_t c; /* Pre-condition the CRC */ diff --git a/crc32_braid_p.h b/crc32_braid_p.h index 53b7f53a66..26906b64ce 100644 --- a/crc32_braid_p.h +++ b/crc32_braid_p.h @@ -45,6 +45,6 @@ /* CRC polynomial. */ #define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ -extern uint32_t crc32_braid(uint32_t crc, const uint8_t *buf, uint64_t len); +extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, uint64_t len); #endif /* CRC32_BRAID_P_H_ */ diff --git a/deflate.c b/deflate.c index 5be02fe0f7..554aa7083b 100644 --- a/deflate.c +++ b/deflate.c @@ -202,11 +202,11 @@ int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level strm->msg = NULL; if (strm->zalloc == NULL) { - strm->zalloc = zng_calloc; + strm->zalloc = PREFIX3(calloc); strm->opaque = NULL; } if (strm->zfree == NULL) - strm->zfree = zng_cfree; + strm->zfree = PREFIX3(cfree); if (level == Z_DEFAULT_COMPRESSION) level = 6; @@ -400,14 +400,14 @@ int32_t Z_EXPORT PREFIX(deflateSetDictionary)(PREFIX3(stream) *strm, const uint8 next = strm->next_in; strm->avail_in = dictLength; strm->next_in = (z_const unsigned char *)dictionary; - fill_window(s); + PREFIX(fill_window)(s); while (s->lookahead >= STD_MIN_MATCH) { str = s->strstart; n = s->lookahead - (STD_MIN_MATCH - 1); s->insert_string(s, str, n); s->strstart = str + n; s->lookahead = STD_MIN_MATCH - 1; - fill_window(s); + PREFIX(fill_window)(s); } s->strstart += s->lookahead; s->block_start = (int)s->strstart; @@ -1090,7 +1090,7 @@ int32_t Z_EXPORT PREFIX(deflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ -Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size) { +Z_INTERNAL unsigned PREFIX(read_buf)(PREFIX3(stream) *strm, unsigned char *buf, unsigned size) { uint32_t len = strm->avail_in; len = MIN(len, size); @@ -1175,7 +1175,7 @@ static void lm_init(deflate_state *s) { * option -- not supported here). */ -void Z_INTERNAL fill_window(deflate_state *s) { +void Z_INTERNAL PREFIX(fill_window)(deflate_state *s) { unsigned n; unsigned int more; /* Amount of free space at the end of the window. */ unsigned int wsize = s->w_size; @@ -1219,7 +1219,7 @@ void Z_INTERNAL fill_window(deflate_state *s) { */ Assert(more >= 2, "more < 2"); - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + n = PREFIX(read_buf)(s->strm, s->window + s->strstart + s->lookahead, more); s->lookahead += n; /* Initialize the hash value now that we have some input: */ diff --git a/deflate.h b/deflate.h index ccb246a818..2d2ee3da11 100644 --- a/deflate.h +++ b/deflate.h @@ -373,7 +373,7 @@ static inline void put_uint64(deflate_state *s, uint64_t lld) { memory checker errors from longest match routines */ -void Z_INTERNAL fill_window(deflate_state *s); +void Z_INTERNAL PREFIX(fill_window)(deflate_state *s); void Z_INTERNAL slide_hash_c(deflate_state *s); /* in trees.c */ diff --git a/deflate_fast.c b/deflate_fast.c index c6e24e48a2..3184aa718c 100644 --- a/deflate_fast.c +++ b/deflate_fast.c @@ -29,7 +29,7 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); + PREFIX(fill_window)(s); if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { return need_more; } diff --git a/deflate_huff.c b/deflate_huff.c index 296201f6f1..b197e24d7c 100644 --- a/deflate_huff.c +++ b/deflate_huff.c @@ -19,7 +19,7 @@ Z_INTERNAL block_state deflate_huff(deflate_state *s, int flush) { for (;;) { /* Make sure that we have a literal to write. */ if (s->lookahead == 0) { - fill_window(s); + PREFIX(fill_window)(s); if (s->lookahead == 0) { if (flush == Z_NO_FLUSH) return need_more; diff --git a/deflate_medium.c b/deflate_medium.c index 1bb21c245b..47796e3221 100644 --- a/deflate_medium.c +++ b/deflate_medium.c @@ -179,7 +179,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { * string following the next current_match. */ if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); + PREFIX(fill_window)(s); if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { return need_more; } diff --git a/deflate_p.h b/deflate_p.h index af24681a56..dd2021a0f5 100644 --- a/deflate_p.h +++ b/deflate_p.h @@ -48,7 +48,7 @@ static inline void check_match(deflate_state *s, Pos start, Pos match, int lengt #endif Z_INTERNAL void PREFIX(flush_pending)(PREFIX3(stream) *strm); -Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size); +Z_INTERNAL unsigned PREFIX(read_buf)(PREFIX3(stream) *strm, unsigned char *buf, unsigned size); /* =========================================================================== * Save the match info and tally the frequency counts. Return true if diff --git a/deflate_quick.c b/deflate_quick.c index f7dfbe8aca..4d8013e710 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -70,7 +70,7 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { } if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD)) { - fill_window(s); + PREFIX(fill_window)(s); if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { return need_more; } diff --git a/deflate_rle.c b/deflate_rle.c index 9e669ec545..77df71f585 100644 --- a/deflate_rle.c +++ b/deflate_rle.c @@ -26,7 +26,7 @@ Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { * for the longest run, plus one for the unrolled loop. */ if (s->lookahead <= STD_MAX_MATCH) { - fill_window(s); + PREFIX(fill_window)(s); if (s->lookahead <= STD_MAX_MATCH && flush == Z_NO_FLUSH) return need_more; if (s->lookahead == 0) diff --git a/deflate_slow.c b/deflate_slow.c index 20fa0f39ac..9f1c913467 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -34,7 +34,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); + PREFIX(fill_window)(s); if (UNLIKELY(s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH)) { return need_more; } diff --git a/deflate_stored.c b/deflate_stored.c index a9bc92164c..6160896b3f 100644 --- a/deflate_stored.c +++ b/deflate_stored.c @@ -94,7 +94,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { * the check value. */ if (len) { - read_buf(s->strm, s->strm->next_out, len); + PREFIX(read_buf)(s->strm, s->strm->next_out, len); s->strm->next_out += len; s->strm->avail_out -= len; s->strm->total_out += len; @@ -157,7 +157,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { have = MIN(have, s->strm->avail_in); if (have) { - read_buf(s->strm, s->window + s->strstart, have); + PREFIX(read_buf)(s->strm, s->window + s->strstart, have); s->strstart += have; s->insert += MIN(have, s->w_size - s->insert); } diff --git a/functable.c b/functable.c index a96caafc5f..4af8a8a7d5 100644 --- a/functable.c +++ b/functable.c @@ -407,7 +407,7 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const uint8_t *buf, uint64_t len) { Assert(sizeof(uint64_t) >= sizeof(size_t), "crc32_z takes size_t but internally we have a uint64_t len"); - functable.crc32 = &crc32_braid; + functable.crc32 = &PREFIX(crc32_braid); cpu_check_features(); #ifdef ARM_ACLE_CRC_HASH if (arm_cpu_has_crc32) diff --git a/infback.c b/infback.c index 79ce086511..e57daab18d 100644 --- a/infback.c +++ b/infback.c @@ -39,11 +39,11 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateBackInit)(PREFIX3(stream) *strm, int32_t wi return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ if (strm->zalloc == NULL) { - strm->zalloc = zng_calloc; + strm->zalloc = PREFIX3(calloc); strm->opaque = NULL; } if (strm->zfree == NULL) - strm->zfree = zng_cfree; + strm->zfree = PREFIX3(cfree); state = ZALLOC_INFLATE_STATE(strm); if (state == NULL) return Z_MEM_ERROR; @@ -192,7 +192,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in state->mode = STORED; break; case 1: /* fixed block */ - fixedtables(state); + PREFIX(fixedtables)(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN; /* decode codes */ break; diff --git a/inflate.c b/inflate.c index c4de058436..7949120997 100644 --- a/inflate.c +++ b/inflate.c @@ -147,11 +147,11 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateInit2)(PREFIX3(stream) *strm, int32_t windo return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ if (strm->zalloc == NULL) { - strm->zalloc = zng_calloc; + strm->zalloc = PREFIX3(calloc); strm->opaque = NULL; } if (strm->zfree == NULL) - strm->zfree = zng_cfree; + strm->zfree = PREFIX3(cfree); state = ZALLOC_INFLATE_STATE(strm); if (state == NULL) return Z_MEM_ERROR; @@ -214,7 +214,7 @@ int32_t Z_EXPORT PREFIX(inflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32 fixed code decoding. This returns fixed tables from inffixed_tbl.h. */ -void Z_INTERNAL fixedtables(struct inflate_state *state) { +void Z_INTERNAL PREFIX(fixedtables)(struct inflate_state *state) { state->lencode = lenfix; state->lenbits = 9; state->distcode = distfix; @@ -677,7 +677,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->mode = STORED; break; case 1: /* fixed block */ - fixedtables(state); + PREFIX(fixedtables)(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); state->mode = LEN_; /* decode codes */ if (flush == Z_TREES) { diff --git a/inflate.h b/inflate.h index f9a7edd597..39cdf5d683 100644 --- a/inflate.h +++ b/inflate.h @@ -135,6 +135,6 @@ struct inflate_state { }; int Z_INTERNAL PREFIX(inflate_ensure_window)(struct inflate_state *state); -void Z_INTERNAL fixedtables(struct inflate_state *state); +void Z_INTERNAL PREFIX(fixedtables)(struct inflate_state *state); #endif /* INFLATE_H_ */ diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index c781c626f7..2cea046607 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -55,7 +55,7 @@ class crc32: public benchmark::Fixture { } \ BENCHMARK_REGISTER_F(crc32, name)->Range(1, MAX_RANDOM_INTS_SIZE); -BENCHMARK_CRC32(braid, crc32_braid, 1); +BENCHMARK_CRC32(braid, PREFIX(crc32_braid), 1); #ifdef ARM_ACLE_CRC_HASH BENCHMARK_CRC32(acle, crc32_acle, arm_cpu_has_crc32); diff --git a/test/test_aligned_alloc.cc b/test/test_aligned_alloc.cc index de73c7ec32..07f99a9da0 100644 --- a/test/test_aligned_alloc.cc +++ b/test/test_aligned_alloc.cc @@ -41,8 +41,8 @@ void zng_cfree_unaligned(void *opaque, void *ptr) { } TEST(zalloc, aligned_64) { - void *return_ptr = zng_alloc_aligned(zng_calloc_unaligned, 0, 1, 100, 64); + void *return_ptr = PREFIX3(alloc_aligned)(zng_calloc_unaligned, 0, 1, 100, 64); ASSERT_TRUE(return_ptr != NULL); EXPECT_EQ((intptr_t)return_ptr % 64, 0); - zng_free_aligned(zng_cfree_unaligned, 0, return_ptr); + PREFIX3(free_aligned)(zng_cfree_unaligned, 0, return_ptr); } diff --git a/test/test_crc32.cc b/test/test_crc32.cc index 1d839d78df..6b6af4bce5 100644 --- a/test/test_crc32.cc +++ b/test/test_crc32.cc @@ -206,7 +206,7 @@ INSTANTIATE_TEST_SUITE_P(crc32, crc32_variant, testing::ValuesIn(tests)); hash(GetParam(), func); \ } -TEST_CRC32(braid, crc32_braid, 1) +TEST_CRC32(braid, PREFIX(crc32_braid), 1) #ifdef ARM_ACLE_CRC_HASH TEST_CRC32(acle, crc32_acle, arm_cpu_has_crc32) diff --git a/zutil.c b/zutil.c index 5583578615..54e5b02b02 100644 --- a/zutil.c +++ b/zutil.c @@ -20,18 +20,18 @@ z_const char * const PREFIX(z_errmsg)[10] = { (z_const char *)"" }; -const char zlibng_string[] = - " zlib-ng 2.1.0.devel forked from zlib"; - #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { return ZLIB_VERSION; } -#endif +#else +const char zlibng_string[] = + " zlib-ng 2.1.0.devel forked from zlib"; const char * Z_EXPORT zlibng_version(void) { return ZLIBNG_VERSION; } +#endif unsigned long Z_EXPORT PREFIX(zlibCompileFlags)(void) { unsigned long flags; @@ -100,26 +100,26 @@ const char * Z_EXPORT PREFIX(zError)(int err) { return ERR_MSG(err); } -void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size) { +void Z_INTERNAL *PREFIX3(calloc)(void *opaque, unsigned items, unsigned size) { Z_UNUSED(opaque); return zng_alloc((size_t)items * (size_t)size); } -void Z_INTERNAL zng_cfree(void *opaque, void *ptr) { +void Z_INTERNAL PREFIX3(cfree)(void *opaque, void *ptr) { Z_UNUSED(opaque); zng_free(ptr); } /* Since we support custom memory allocators, some which might not align memory as we expect, * we have to ask for extra memory and return an aligned pointer. */ -void Z_INTERNAL *zng_alloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align) { +void Z_INTERNAL *PREFIX3(alloc_aligned)(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align) { uintptr_t return_ptr, original_ptr; uint32_t alloc_size, align_diff; void *ptr; /* If no custom calloc function used then call zlib-ng's aligned calloc */ - if (zalloc == zng_calloc) - return zng_calloc(opaque, items, size); + if (zalloc == PREFIX3(calloc)) + return PREFIX3(calloc)(opaque, items, size); /* Allocate enough memory for proper alignment and to store the original memory pointer */ alloc_size = sizeof(void *) + (items * size) + align; @@ -141,10 +141,10 @@ void Z_INTERNAL *zng_alloc_aligned(zng_calloc_func zalloc, void *opaque, unsigne return (void *)return_ptr; } -void Z_INTERNAL zng_free_aligned(zng_cfree_func zfree, void *opaque, void *ptr) { +void Z_INTERNAL PREFIX3(free_aligned)(zng_cfree_func zfree, void *opaque, void *ptr) { /* If no custom cfree function used then call zlib-ng's aligned cfree */ - if (zfree == zng_cfree) { - zng_cfree(opaque, ptr); + if (zfree == PREFIX3(cfree)) { + PREFIX3(cfree)(opaque, ptr); return; } if (!ptr) diff --git a/zutil.h b/zutil.h index 25716c5711..7f177ef1f0 100644 --- a/zutil.h +++ b/zutil.h @@ -126,17 +126,17 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ /* memory allocation functions */ -void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size); -void Z_INTERNAL zng_cfree(void *opaque, void *ptr); +void Z_INTERNAL *PREFIX3(calloc)(void *opaque, unsigned items, unsigned size); +void Z_INTERNAL PREFIX3(cfree)(void *opaque, void *ptr); typedef void *zng_calloc_func(void *opaque, unsigned items, unsigned size); typedef void zng_cfree_func(void *opaque, void *ptr); -void Z_INTERNAL *zng_alloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align); -void Z_INTERNAL zng_free_aligned(zng_cfree_func zfree, void *opaque, void *ptr); +void Z_INTERNAL *PREFIX3(alloc_aligned)(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align); +void Z_INTERNAL PREFIX3(free_aligned)(zng_cfree_func zfree, void *opaque, void *ptr); -#define ZALLOC(strm, items, size) zng_alloc_aligned((strm)->zalloc, (strm)->opaque, (items), (size), 64) -#define ZFREE(strm, addr) zng_free_aligned((strm)->zfree, (strm)->opaque, (void *)(addr)) +#define ZALLOC(strm, items, size) PREFIX3(alloc_aligned)((strm)->zalloc, (strm)->opaque, (items), (size), 64) +#define ZFREE(strm, addr) PREFIX3(free_aligned)((strm)->zfree, (strm)->opaque, (void *)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} From 43fd141840821bd09b96a8ce2b4dec5b5ad563ff Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Thu, 13 Oct 2022 18:52:50 +0100 Subject: [PATCH 535/798] Allow gtest_zlib to be manually disabled --- CMakeLists.txt | 2 ++ README.md | 1 + test/CMakeLists.txt | 24 +++++++++++++++++------- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 642d35f42b..4400fea584 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ option(WITH_GZFILEOP "Compile with support for gzFile related functions" ON) option(ZLIB_COMPAT "Compile with zlib compatible API" OFF) option(ZLIB_ENABLE_TESTS "Build test binaries" ON) option(ZLIBNG_ENABLE_TESTS "Test zlib-ng specific API" ON) +option(WITH_GTEST "Build gtest_zlib" ON) option(WITH_FUZZERS "Build test/fuzz" OFF) option(WITH_BENCHMARKS "Build test/benchmarks" OFF) option(WITH_BENCHMARK_APPS "Build application benchmarks" OFF) @@ -1187,6 +1188,7 @@ add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Compile with zlib compatible API") add_feature_info(ZLIB_ENABLE_TESTS ZLIB_ENABLE_TESTS "Build test binaries") add_feature_info(ZLIBNG_ENABLE_TESTS ZLIBNG_ENABLE_TESTS "Test zlib-ng specific API") add_feature_info(WITH_SANITIZER WITH_SANITIZER "Enable sanitizer support") +add_feature_info(WITH_GTEST WITH_GTEST "Build gtest_zlib") add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz") add_feature_info(WITH_BENCHMARKS WITH_BENCHMARKS "Build test/benchmarks") add_feature_info(WITH_BENCHMARK_APPS WITH_BENCHMARK_APPS "Build application benchmarks") diff --git a/README.md b/README.md index a1218d44d0..80b921b2c7 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ Build Options | WITH_NEW_STRATEGIES | --without-new-strategies | Use new strategies | ON | | WITH_NATIVE_INSTRUCTIONS | --native | Compiles with full instruction set supported on this host (gcc/clang -march=native) | OFF | | WITH_SANITIZER | | Build with sanitizer (memory, address, undefined) | OFF | +| WITH_GTEST | | Build gtest_zlib | ON | | WITH_FUZZERS | | Build test/fuzz | OFF | | WITH_BENCHMARKS | | Build test/benchmarks | OFF | | WITH_MAINTAINER_WARNINGS | | Build with project maintainer warnings | OFF | diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 55a3057be7..11cf73175e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -92,16 +92,26 @@ if(WITH_FUZZERS) add_subdirectory(fuzz) endif() -if(CMAKE_VERSION VERSION_LESS 3.12) - message(WARNING "Minimum cmake version of 3.12 not met for GoogleTest or benchmarks!") -else() - enable_language(CXX) +if(WITH_GTEST OR WITH_BENCHMARKS) + if(CMAKE_VERSION VERSION_LESS 3.12) + message(WARNING "Minimum cmake version of 3.12 not met for GoogleTest or benchmarks!") - include(FetchContent) + set(WITH_GTEST OFF) + set(WITH_GTEST OFF PARENT_SCOPE) - if(WITH_BENCHMARKS) - add_subdirectory(benchmarks) + set(WITH_BENCHMARKS OFF) + set(WITH_BENCHMARKS OFF PARENT_SCOPE) + else() + enable_language(CXX) endif() +endif() + +if(WITH_BENCHMARKS) + add_subdirectory(benchmarks) +endif() + +if(WITH_GTEST) + include(FetchContent) # Google test requires at least C++11 set(CMAKE_CXX_STANDARD 11) From 9121a3c425a7d71ce54439e83deec6b8da4738b3 Mon Sep 17 00:00:00 2001 From: Piotr Kubaj Date: Tue, 6 Sep 2022 19:19:15 +0200 Subject: [PATCH 536/798] Fix build on FreeBSD/powerpc* Use elf_aux_info() instead of getauxval() on FreeBSD. --- arch/power/power_features.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/power/power_features.c b/arch/power/power_features.c index 7c0350c66e..62fc9495c6 100644 --- a/arch/power/power_features.c +++ b/arch/power/power_features.c @@ -7,6 +7,9 @@ #ifdef HAVE_SYS_AUXV_H # include #endif +#ifdef __FreeBSD__ +#include +#endif #include "../../zbuild.h" #include "power_features.h" @@ -17,7 +20,11 @@ Z_INTERNAL int power_cpu_has_arch_3_00 = 0; void Z_INTERNAL power_check_features(void) { #ifdef PPC_FEATURES unsigned long hwcap; +#ifdef __FreeBSD__ + elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); +#else hwcap = getauxval(AT_HWCAP); +#endif if (hwcap & PPC_FEATURE_HAS_ALTIVEC) power_cpu_has_altivec = 1; @@ -25,7 +32,11 @@ void Z_INTERNAL power_check_features(void) { #ifdef POWER_FEATURES unsigned long hwcap2; +#ifdef __FreeBSD__ + elf_aux_info(AT_HWCAP2, &hwcap2, sizeof(hwcap2)); +#else hwcap2 = getauxval(AT_HWCAP2); +#endif if (hwcap2 & PPC_FEATURE2_ARCH_2_07) power_cpu_has_arch_2_07 = 1; From 0a59b4e7454b39c20a4eca88716e18d93431f96f Mon Sep 17 00:00:00 2001 From: Piotr Kubaj Date: Wed, 28 Sep 2022 00:57:46 +0200 Subject: [PATCH 537/798] Add FreeBSD/powerpc* support to cmake/detect-intrinsics.cmake --- cmake/detect-intrinsics.cmake | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 20164c5bce..3fa74b483f 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -297,8 +297,17 @@ macro(check_ppc_intrinsics) set(CMAKE_REQUIRED_FLAGS "${PPCFLAGS} ${NATIVEFLAG}") check_c_source_compiles( "#include + #ifdef __FreeBSD__ + #include + #endif int main() { + #ifdef __FreeBSD__ + unsigned long hwcap; + elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE_HAS_ALTIVEC); + #else return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); + #endif }" HAVE_VMX ) @@ -315,8 +324,17 @@ macro(check_power8_intrinsics) set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG} ${NATIVEFLAG}") check_c_source_compiles( "#include + #ifdef __FreeBSD__ + #include + #endif int main() { + #ifdef __FreeBSD__ + unsigned long hwcap; + elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE2_ARCH_2_07); + #else return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); + #endif }" HAVE_POWER8_INTRIN ) From 296bd8c0ab372bd30118ddc679e9392dd5cabb98 Mon Sep 17 00:00:00 2001 From: Piotr Kubaj Date: Tue, 4 Oct 2022 01:43:02 +0200 Subject: [PATCH 538/798] Fix configure script for FreeBSD/powerpc* --- configure | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/configure b/configure index bb8d15c8ec..5e21b449bc 100755 --- a/configure +++ b/configure @@ -739,13 +739,20 @@ else echo "Checking for strerror... No." | tee -a configure.log fi -# check for getauxval() for architecture feature detection at run-time +# check for getauxval() or elf_aux_info() for architecture feature detection at run-time cat > $test.c < -int main() { return getauxval(0); } +int main() { +#ifdef __FreeBSD__ +int test; +return elf_aux_info(AT_PAGESZ, &test, sizeof(test)); +#else +return getauxval(0); +#endif +} EOF if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then - echo "Checking for getauxval() in sys/auxv.h... Yes." | tee -a configure.log + echo "Checking for getauxval() or elf_aux_info() in sys/auxv.h... Yes." | tee -a configure.log CFLAGS="${CFLAGS} -DHAVE_SYS_AUXV_H" SFLAGS="${SFLAGS} -DHAVE_SYS_AUXV_H" else @@ -1242,8 +1249,19 @@ EOF echo "Checking if -mno-vsx is supported ... No." | tee -a configure.log fi cat > $test.c << EOF +#ifdef __FreeBSD__ +#include +#endif #include -int main() { return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); } +int main() { +#ifdef __FreeBSD__ +unsigned long hwcap; +elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); +return (hwcap & PPC_FEATURE_HAS_ALTIVEC); +#else +return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); +#endif +} EOF if try $CC -c $CFLAGS -maltivec $test.c; then HAVE_VMX=1 @@ -1257,8 +1275,19 @@ EOF check_power8_intrinsics() { # Check whether features needed by POWER8 optimisations are available cat > $test.c << EOF +#ifdef __FreeBSD__ +#include +#endif #include -int main() { return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); } +int main() { +#ifdef __FreeBSD__ +unsigned long hwcap; +elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap)); +return (hwcap & PPC_FEATURE2_ARCH_2_07); +#else +return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); +#endif +} EOF if test $buildpower8 -eq 1 && try $CC -c $CFLAGS -mcpu=power8 $test.c; then HAVE_POWER8_INTRIN=1 From bd321660c916266cd98b496212114ba29d48aaed Mon Sep 17 00:00:00 2001 From: Piotr Kubaj Date: Sat, 12 Nov 2022 01:51:22 +0100 Subject: [PATCH 539/798] Correct indents --- arch/power/power_features.c | 2 +- configure | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/power/power_features.c b/arch/power/power_features.c index 62fc9495c6..0614ff0f25 100644 --- a/arch/power/power_features.c +++ b/arch/power/power_features.c @@ -8,7 +8,7 @@ # include #endif #ifdef __FreeBSD__ -#include +# include #endif #include "../../zbuild.h" #include "power_features.h" diff --git a/configure b/configure index 5e21b449bc..8dae722a69 100755 --- a/configure +++ b/configure @@ -744,10 +744,10 @@ cat > $test.c < int main() { #ifdef __FreeBSD__ -int test; -return elf_aux_info(AT_PAGESZ, &test, sizeof(test)); + int test; + return elf_aux_info(AT_PAGESZ, &test, sizeof(test)); #else -return getauxval(0); + return getauxval(0); #endif } EOF @@ -1255,11 +1255,11 @@ EOF #include int main() { #ifdef __FreeBSD__ -unsigned long hwcap; -elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); -return (hwcap & PPC_FEATURE_HAS_ALTIVEC); + unsigned long hwcap; + elf_aux_info(AT_HWCAP, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE_HAS_ALTIVEC); #else -return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); + return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); #endif } EOF @@ -1281,11 +1281,11 @@ check_power8_intrinsics() { #include int main() { #ifdef __FreeBSD__ -unsigned long hwcap; -elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap)); -return (hwcap & PPC_FEATURE2_ARCH_2_07); + unsigned long hwcap; + elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE2_ARCH_2_07); #else -return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); + return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); #endif } EOF From d828e0788fadce80dd5f0d872f6eaccdfc53432b Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 29 Dec 2022 13:39:35 +0100 Subject: [PATCH 540/798] Fix visibility of a few internal functions. --- arch/x86/crc32_fold_pclmulqdq.c | 2 +- arch/x86/crc32_fold_vpclmulqdq_tpl.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index aff1f80659..c6f0484279 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -342,7 +342,7 @@ Z_INTERNAL uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc) { return crc->value; } -uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, uint64_t len) { +Z_INTERNAL uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, uint64_t len) { /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for * these short lengths might also prove to be effective */ if (len < 64) diff --git a/arch/x86/crc32_fold_vpclmulqdq_tpl.h b/arch/x86/crc32_fold_vpclmulqdq_tpl.h index e75278f984..421b64da02 100644 --- a/arch/x86/crc32_fold_vpclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_vpclmulqdq_tpl.h @@ -4,10 +4,10 @@ */ #ifdef COPY -uint64_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, +Z_INTERNAL uint64_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, uint64_t len) { #else -uint64_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, +Z_INTERNAL uint64_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, uint64_t len, __m128i init_crc, int32_t first) { __m512i zmm_initial = _mm512_zextsi128_si512(init_crc); From b12c6a3a69204e31c75688395496c8a95f8734fd Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 19 Jan 2023 02:01:11 +0200 Subject: [PATCH 541/798] Change configure workflow to use gcc-11 for MacOS * gcc-9 is not installed on macos-latest runner --- .github/workflows/configure.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 48651fa6cf..c2927f73b3 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -171,17 +171,17 @@ jobs: - name: macOS GCC Symbol Prefix os: macOS-latest - compiler: gcc-9 + compiler: gcc-11 configure-args: --sprefix=zTest_ - name: macOS GCC Symbol Prefix & Compat os: macOS-latest - compiler: gcc-9 + compiler: gcc-11 configure-args: --zlib-compat --sprefix=zTest_ - name: macOS GCC os: macOS-latest - compiler: gcc-9 + compiler: gcc-11 configure-args: --warn steps: From 392b74da6806d15ca61df8856d83831993ead0e7 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 19 Jan 2023 01:47:14 +0200 Subject: [PATCH 542/798] Change pkgcheck to use macos-11 runner * macos-latest runner doesn't have XCode 11.7.0 anymore, newer XCode versions have incompatible toolchain --- .github/workflows/pkgcheck.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 3b8c712c22..180c2433ba 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -56,19 +56,19 @@ jobs: packages: qemu gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc6-dev-ppc64el-cross - name: macOS Clang - os: macOS-latest + os: macOS-11 compiler: clang cxx-compiler: clang++ - name: macOS Clang Native - os: macOS-latest + os: macOS-11 compiler: clang cxx-compiler: clang++ cmake-args: -DWITH_NATIVE_INSTRUCTIONS=ON configure-args: --native - name: macOS Clang Symbol Prefix - os: macOS-latest + os: macOS-11 compiler: clang cxx-compiler: clang++ cmake-args: -DZLIB_SYMBOL_PREFIX=zTest_ From 1bcbd0341d41371c65f24e7adadb6198fd36cc68 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Wed, 11 Jan 2023 20:04:41 +0000 Subject: [PATCH 543/798] Delete ctzl.h --- arch/arm/ctzl.h | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 arch/arm/ctzl.h diff --git a/arch/arm/ctzl.h b/arch/arm/ctzl.h deleted file mode 100644 index 77218deec3..0000000000 --- a/arch/arm/ctzl.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef ARM_CTZL_H -#define ARM_CTZL_H - -#include - -#if defined(_MSC_VER) && !defined(__clang__) -static __forceinline unsigned long __builtin_ctzl(unsigned long value) { - return _arm_clz(_arm_rbit(value)); -} -#endif - -#endif From 359e572966e1ef3fcfd8282f8d487d1587e09db9 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 13 Jan 2023 21:21:43 +0300 Subject: [PATCH 544/798] Use const char* for z_error argument --- zbuild.h | 2 +- zutil.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zbuild.h b/zbuild.h index 7fa4322ab5..901111cd79 100644 --- a/zbuild.h +++ b/zbuild.h @@ -203,7 +203,7 @@ #ifdef ZLIB_DEBUG # include extern int Z_INTERNAL z_verbose; - extern void Z_INTERNAL z_error(char *m); + extern void Z_INTERNAL z_error(const char *m); # define Assert(cond, msg) {if (!(cond)) z_error(msg);} # define Trace(x) {if (z_verbose >= 0) fprintf x;} # define Tracev(x) {if (z_verbose > 0) fprintf x;} diff --git a/zutil.c b/zutil.c index 54e5b02b02..cd67cf435e 100644 --- a/zutil.c +++ b/zutil.c @@ -87,7 +87,7 @@ unsigned long Z_EXPORT PREFIX(zlibCompileFlags)(void) { # endif int Z_INTERNAL z_verbose = verbose; -void Z_INTERNAL z_error(char *m) { +void Z_INTERNAL z_error(const char *m) { fprintf(stderr, "%s\n", m); exit(1); } From 7659b386a6b657cb47c06c7c59d1b72f547da9c9 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 13 Jan 2023 21:23:07 +0300 Subject: [PATCH 545/798] Make sure inflate_p.h is fully guarded by header guard --- inflate_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inflate_p.h b/inflate_p.h index e3daae1e1c..27b6102778 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -125,8 +125,6 @@ bits -= bits & 7; \ } while (0) -#endif - /* Set mode=BAD and prepare error message */ #define SET_BAD(errmsg) \ do { \ @@ -208,3 +206,5 @@ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, uint64_t len, return out; } + +#endif From 3bf0f6e9a0f882909a1111d97381eec3ac931980 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Tue, 17 Jan 2023 05:50:14 +0300 Subject: [PATCH 546/798] Do not use cpuid.h on Windows According to msdn docs __cpuid/__cpuidex/_xgetbv are provided by intrin.h and should be used on windows --- arch/x86/x86_features.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index 0de8349941..d1ac51c55c 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -9,7 +9,7 @@ #include "../../zbuild.h" -#ifdef _MSC_VER +#ifdef _WIN32 # include #else // Newer versions of GCC and clang come with cpuid.h @@ -32,7 +32,7 @@ Z_INTERNAL int x86_cpu_has_os_save_ymm; Z_INTERNAL int x86_cpu_has_os_save_zmm; static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _MSC_VER +#ifdef _WIN32 unsigned int registers[4]; __cpuid((int *)registers, info); @@ -46,7 +46,7 @@ static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, } static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _MSC_VER +#ifdef _WIN32 unsigned int registers[4]; __cpuidex((int *)registers, info, subinfo); @@ -60,7 +60,7 @@ static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, } static inline uint64_t xgetbv(unsigned int xcr) { -#ifdef _MSC_VER +#ifdef _WIN32 return _xgetbv(xcr); #else uint32_t eax, edx; From e49d55848f8ee50fb55a47df3bafc13c6966d019 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 13 Jan 2023 21:31:48 +0300 Subject: [PATCH 547/798] Fix compilation error where `crc32_fold` type matches field name in struct functable_s If functable.h is included by a c++ compiler, compiler issues the following error (VS 2022): ``` zlib-ng/functable.h(20,49): error C2327: 'functable_s::crc32_fold': is not a type name, static, or enumerator ``` The error happens on line 20 because on previous line crc32_fold is declared as a struct member. Using `struct crc32_fold_s` instead of `crc32_fold` fixes the error. --- functable.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/functable.h b/functable.h index 838af2fd95..a5690871c1 100644 --- a/functable.h +++ b/functable.h @@ -14,10 +14,10 @@ struct functable_s { uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, uint64_t len); uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, uint64_t len); - uint32_t (* crc32_fold_reset) (crc32_fold *crc); - void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); - void (* crc32_fold) (crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); - uint32_t (* crc32_fold_final) (crc32_fold *crc); + uint32_t (* crc32_fold_reset) (struct crc32_fold_s *crc); + void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, uint64_t len); + void (* crc32_fold) (struct crc32_fold_s *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); + uint32_t (* crc32_fold_final) (struct crc32_fold_s *crc); uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* chunksize) (void); uint8_t* (* chunkcopy) (uint8_t *out, uint8_t const *from, unsigned len); From 23e43059328b0ae99f86a61aba6d8652d08e3ccc Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 30 Sep 2022 16:06:42 +0100 Subject: [PATCH 548/798] Use size_t instead of uint64_t for len in all crc32 functions --- arch/arm/crc32_acle.c | 2 +- arch/power/crc32_power8.c | 2 +- arch/s390/crc32-vx.c | 8 ++++---- arch/x86/crc32_fold_pclmulqdq.c | 12 ++++++------ arch/x86/crc32_fold_pclmulqdq_tpl.h | 18 +++++++++--------- arch/x86/crc32_fold_vpclmulqdq_tpl.h | 10 +++++----- cpu_features.h | 16 ++++++++-------- crc32_braid.c | 4 ++-- crc32_braid_p.h | 2 +- crc32_fold.c | 17 +++-------------- crc32_fold.h | 4 ++-- functable.c | 9 +++------ functable.h | 6 +++--- 13 files changed, 48 insertions(+), 62 deletions(-) diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index ef18ae81ec..701c9925cd 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -13,7 +13,7 @@ #endif #include "../../zbuild.h" -uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len) { +uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { Z_REGISTER uint32_t c; Z_REGISTER const uint16_t *buf2; Z_REGISTER const uint32_t *buf4; diff --git a/arch/power/crc32_power8.c b/arch/power/crc32_power8.c index fbb64721e6..1cb5f299f3 100644 --- a/arch/power/crc32_power8.c +++ b/arch/power/crc32_power8.c @@ -48,7 +48,7 @@ static unsigned int crc32_align(unsigned int crc, const unsigned char *p, unsign static unsigned int ALIGNED_(32) __crc32_vpmsum(unsigned int crc, const void* p, unsigned long len); -Z_INTERNAL uint32_t crc32_power8(uint32_t crc, const unsigned char *p, uint64_t _len) { +Z_INTERNAL uint32_t crc32_power8(uint32_t crc, const unsigned char *p, size_t _len) { unsigned int prealign; unsigned int tail; diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index a64d629166..78c0be5cee 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -21,7 +21,7 @@ typedef unsigned char uv16qi __attribute__((vector_size(16))); typedef unsigned int uv4si __attribute__((vector_size(16))); typedef unsigned long long uv2di __attribute__((vector_size(16))); -static uint32_t crc32_le_vgfm_16(uint32_t crc, const uint8_t *buf, uint64_t len) { +static uint32_t crc32_le_vgfm_16(uint32_t crc, const uint8_t *buf, size_t len) { /* * The CRC-32 constant block contains reduction constants to fold and * process particular chunks of the input data stream in parallel. @@ -198,8 +198,8 @@ static uint32_t crc32_le_vgfm_16(uint32_t crc, const uint8_t *buf, uint64_t len) #define VX_ALIGNMENT 16L #define VX_ALIGN_MASK (VX_ALIGNMENT - 1) -uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf, uint64_t len) { - uint64_t prealign, aligned, remaining; +uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf, size_t len) { + size_t prealign, aligned, remaining; if (len < VX_MIN_LEN + VX_ALIGN_MASK) return PREFIX(crc32_braid)(crc, buf, len); @@ -213,7 +213,7 @@ uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf aligned = len & ~VX_ALIGN_MASK; remaining = len & VX_ALIGN_MASK; - crc = crc32_le_vgfm_16(crc ^ 0xffffffff, buf, (size_t)aligned) ^ 0xffffffff; + crc = crc32_le_vgfm_16(crc ^ 0xffffffff, buf, aligned) ^ 0xffffffff; if (remaining) crc = PREFIX(crc32_braid)(crc, buf + aligned, remaining); diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index c6f0484279..ecee0c578c 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -32,11 +32,11 @@ #include #ifdef X86_VPCLMULQDQ_CRC -extern uint64_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, uint64_t len, __m128i init_crc, +extern size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, __m128i init_crc, int32_t first); -extern uint64_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, uint64_t len); +extern size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len); #endif static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { @@ -185,7 +185,7 @@ static const unsigned ALIGNED_(32) pshufb_shf_table[60] = { 0x0201008f, 0x06050403, 0x0a090807, 0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ }; -static void partial_fold(const uint64_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, +static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, __m128i *xmm_crc_part) { const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, @@ -342,7 +342,7 @@ Z_INTERNAL uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc) { return crc->value; } -Z_INTERNAL uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, uint64_t len) { +Z_INTERNAL uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len) { /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for * these short lengths might also prove to be effective */ if (len < 64) diff --git a/arch/x86/crc32_fold_pclmulqdq_tpl.h b/arch/x86/crc32_fold_pclmulqdq_tpl.h index 0799638e04..47bbc0111b 100644 --- a/arch/x86/crc32_fold_pclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_pclmulqdq_tpl.h @@ -20,9 +20,9 @@ #ifdef X86_PCLMULQDQ_CRC #ifdef COPY -Z_INTERNAL void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { #else -Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc) { +Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { #endif unsigned long algn_diff; __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; @@ -47,9 +47,9 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64 if (len == 0) return; - memcpy(partial_buf, src, (size_t)len); + memcpy(partial_buf, src, len); xmm_crc_part = _mm_load_si128((const __m128i *)partial_buf); - memcpy(dst, partial_buf, (size_t)len); + memcpy(dst, partial_buf, len); #endif goto partial; } @@ -82,10 +82,10 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64 #ifdef X86_VPCLMULQDQ_CRC if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { #ifdef COPY - uint64_t n = fold_16_vpclmulqdq_copy(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); + size_t n = fold_16_vpclmulqdq_copy(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); dst += n; #else - uint64_t n = fold_16_vpclmulqdq(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, src, len, + size_t n = fold_16_vpclmulqdq(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, src, len, xmm_initial, first); first = 0; #endif @@ -176,12 +176,12 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64 partial: if (len) { - memcpy(&xmm_crc_part, src, (size_t)len); + memcpy(&xmm_crc_part, src, len); #ifdef COPY _mm_storeu_si128((__m128i *)partial_buf, xmm_crc_part); - memcpy(dst, partial_buf, (size_t)len); + memcpy(dst, partial_buf, len); #endif - partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + partial_fold(len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); } crc32_fold_save((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); diff --git a/arch/x86/crc32_fold_vpclmulqdq_tpl.h b/arch/x86/crc32_fold_vpclmulqdq_tpl.h index 421b64da02..3d27cb3dfb 100644 --- a/arch/x86/crc32_fold_vpclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_vpclmulqdq_tpl.h @@ -4,18 +4,18 @@ */ #ifdef COPY -Z_INTERNAL uint64_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len) { #else -Z_INTERNAL uint64_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, - __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, uint64_t len, +Z_INTERNAL size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, __m128i init_crc, int32_t first) { __m512i zmm_initial = _mm512_zextsi128_si512(init_crc); #endif __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; __m512i z0, z1, z2, z3; - uint64_t len_tmp = len; + size_t len_tmp = len; const __m512i zmm_fold4 = _mm512_set4_epi32( 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); const __m512i zmm_fold16 = _mm512_set4_epi32( diff --git a/cpu_features.h b/cpu_features.h index b8de4b71e7..9d10ce7df0 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -65,10 +65,10 @@ extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, cons /* CRC32 folding */ #ifdef X86_PCLMULQDQ_CRC extern uint32_t crc32_fold_pclmulqdq_reset(crc32_fold *crc); -extern void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); -extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); +extern void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); extern uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc); -extern uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, uint64_t len); +extern uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len); #endif /* memory chunking */ @@ -111,15 +111,15 @@ extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned le #endif /* CRC32 */ -typedef uint32_t (*crc32_func)(uint32_t crc32, const uint8_t *buf, uint64_t len); +typedef uint32_t (*crc32_func)(uint32_t crc32, const uint8_t *buf, size_t len); -extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, uint64_t len); +extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, size_t len); #ifdef ARM_ACLE_CRC_HASH -extern uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, uint64_t len); +extern uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len); #elif defined(POWER8_VSX_CRC32) -extern uint32_t crc32_power8(uint32_t crc, const uint8_t *buf, uint64_t len); +extern uint32_t crc32_power8(uint32_t crc, const uint8_t *buf, size_t len); #elif defined(S390_CRC32_VX) -extern uint32_t PREFIX(s390_crc32_vx)(uint32_t crc, const uint8_t *buf, uint64_t len); +extern uint32_t PREFIX(s390_crc32_vx)(uint32_t crc, const uint8_t *buf, size_t len); #endif /* compare256 */ diff --git a/crc32_braid.c b/crc32_braid.c index a7b9b7ebfc..96754b53df 100644 --- a/crc32_braid.c +++ b/crc32_braid.c @@ -111,7 +111,7 @@ static z_word_t crc_word(z_word_t data) { #endif /* W */ /* ========================================================================= */ -Z_INTERNAL uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, uint64_t len) { +Z_INTERNAL uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, size_t len) { Z_REGISTER uint32_t c; /* Pre-condition the CRC */ @@ -120,7 +120,7 @@ Z_INTERNAL uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, uint64 #ifdef W /* If provided enough bytes, do a braided CRC calculation. */ if (len >= N * W + W - 1) { - uint64_t blks; + size_t blks; z_word_t const *words; int k; diff --git a/crc32_braid_p.h b/crc32_braid_p.h index 26906b64ce..1d8a07068a 100644 --- a/crc32_braid_p.h +++ b/crc32_braid_p.h @@ -45,6 +45,6 @@ /* CRC polynomial. */ #define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ -extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, uint64_t len); +extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, size_t len); #endif /* CRC32_BRAID_P_H_ */ diff --git a/crc32_fold.c b/crc32_fold.c index b1011debd9..5b3c7c459f 100644 --- a/crc32_fold.c +++ b/crc32_fold.c @@ -14,23 +14,12 @@ Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc) { return crc->value; } -Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { crc->value = functable.crc32(crc->value, src, len); -/* Test that we don't try to copy more than actually fits in available address space */ -#if INTPTR_MAX > SSIZE_MAX - while (len > SSIZE_MAX) { - memcpy(dst, src, SSIZE_MAX); - dst += SSIZE_MAX; - src += SSIZE_MAX; - len -= SSIZE_MAX; - } -#endif - if (len) { - memcpy(dst, src, (size_t)len); - } + memcpy(dst, src, len); } -Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc) { +Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { /* Note: while this is basically the same thing as the vanilla CRC function, we still need * a functable entry for it so that we can generically dispatch to this function with the * same arguments for the versions that _do_ do a folding CRC but we don't want a copy. The diff --git a/crc32_fold.h b/crc32_fold.h index 6aef546709..0d2ff66967 100644 --- a/crc32_fold.h +++ b/crc32_fold.h @@ -14,8 +14,8 @@ typedef struct crc32_fold_s { } crc32_fold; Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc); -Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len); -Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); +Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); Z_INTERNAL uint32_t crc32_fold_final_c(crc32_fold *crc); #endif diff --git a/functable.c b/functable.c index 4af8a8a7d5..5dd5e54d4c 100644 --- a/functable.c +++ b/functable.c @@ -233,7 +233,7 @@ Z_INTERNAL uint32_t crc32_fold_reset_stub(crc32_fold *crc) { return functable.crc32_fold_reset(crc); } -Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { functable.crc32_fold_copy = &crc32_fold_copy_c; cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC @@ -243,7 +243,7 @@ Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_ functable.crc32_fold_copy(crc, dst, src, len); } -Z_INTERNAL void crc32_fold_stub(crc32_fold *crc, const uint8_t *src, uint64_t len, uint32_t init_crc) { +Z_INTERNAL void crc32_fold_stub(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { functable.crc32_fold = &crc32_fold_c; cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC @@ -403,10 +403,7 @@ Z_INTERNAL uint8_t* chunkmemset_safe_stub(uint8_t *out, unsigned dist, unsigned return functable.chunkmemset_safe(out, dist, len, left); } -Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const uint8_t *buf, uint64_t len) { - Assert(sizeof(uint64_t) >= sizeof(size_t), - "crc32_z takes size_t but internally we have a uint64_t len"); - +Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const uint8_t *buf, size_t len) { functable.crc32 = &PREFIX(crc32_braid); cpu_check_features(); #ifdef ARM_ACLE_CRC_HASH diff --git a/functable.h b/functable.h index a5690871c1..9b6ec3b542 100644 --- a/functable.h +++ b/functable.h @@ -13,10 +13,10 @@ struct functable_s { uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, uint64_t len); uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); - uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, uint64_t len); + uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, size_t len); uint32_t (* crc32_fold_reset) (struct crc32_fold_s *crc); - void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, uint64_t len); - void (* crc32_fold) (struct crc32_fold_s *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); + void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, size_t len); + void (* crc32_fold) (struct crc32_fold_s *crc, const uint8_t *src, size_t len, uint32_t init_crc); uint32_t (* crc32_fold_final) (struct crc32_fold_s *crc); uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* chunksize) (void); From 1ab443812aceab6c80ccd573ecdd06f73a84eef4 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 30 Sep 2022 16:54:16 +0100 Subject: [PATCH 549/798] Use size_t instead of uint64_t for len in all adler32 functions --- adler32.c | 2 +- adler32_fold.c | 15 ++----------- adler32_fold.h | 2 +- adler32_p.h | 6 +++--- arch/arm/adler32_neon.c | 10 ++++----- arch/power/adler32_power8.c | 2 +- arch/power/adler32_vmx.c | 6 +++--- arch/x86/adler32_avx2_tpl.h | 10 ++++----- arch/x86/adler32_avx512_tpl.h | 6 +++--- arch/x86/adler32_avx512_vnni.c | 8 +++---- arch/x86/adler32_sse42.c | 4 ++-- arch/x86/adler32_ssse3.c | 10 ++++----- cpu_features.h | 26 +++++++++++------------ functable.c | 4 ++-- functable.h | 4 ++-- test/benchmarks/benchmark_adler32_copy.cc | 4 ++-- 16 files changed, 54 insertions(+), 65 deletions(-) diff --git a/adler32.c b/adler32.c index c47f764586..95ac13c304 100644 --- a/adler32.c +++ b/adler32.c @@ -8,7 +8,7 @@ #include "adler32_p.h" /* ========================================================================= */ -Z_INTERNAL uint32_t adler32_c(uint32_t adler, const uint8_t *buf, uint64_t len) { +Z_INTERNAL uint32_t adler32_c(uint32_t adler, const uint8_t *buf, size_t len) { uint32_t sum2; unsigned n; diff --git a/adler32_fold.c b/adler32_fold.c index adaabe0210..e2f6f9ac7d 100644 --- a/adler32_fold.c +++ b/adler32_fold.c @@ -9,19 +9,8 @@ #include -Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { adler = functable.adler32(adler, src, len); -/* Test that we don't try to copy more than actually fits in available address space */ -#if INTPTR_MAX > SSIZE_MAX - while (len > SSIZE_MAX) { - memcpy(dst, src, SSIZE_MAX); - dst += SSIZE_MAX; - src += SSIZE_MAX; - len -= SSIZE_MAX; - } -#endif - if (len) { - memcpy(dst, src, (size_t)len); - } + memcpy(dst, src, len); return adler; } diff --git a/adler32_fold.h b/adler32_fold.h index bdaf2130fe..20aa1c7400 100644 --- a/adler32_fold.h +++ b/adler32_fold.h @@ -6,6 +6,6 @@ #ifndef ADLER32_FOLD_H_ #define ADLER32_FOLD_H_ -Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); +Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif diff --git a/adler32_p.h b/adler32_p.h index 8fe41b1422..38ba2ad721 100644 --- a/adler32_p.h +++ b/adler32_p.h @@ -26,7 +26,7 @@ static inline uint32_t adler32_len_1(uint32_t adler, const uint8_t *buf, uint32_ return adler | (sum2 << 16); } -static inline uint32_t adler32_len_16(uint32_t adler, const uint8_t *buf, uint64_t len, uint32_t sum2) { +static inline uint32_t adler32_len_16(uint32_t adler, const uint8_t *buf, size_t len, uint32_t sum2) { while (len) { --len; adler += *buf++; @@ -38,7 +38,7 @@ static inline uint32_t adler32_len_16(uint32_t adler, const uint8_t *buf, uint64 return adler | (sum2 << 16); } -static inline uint32_t adler32_copy_len_16(uint32_t adler, const uint8_t *buf, uint8_t *dst, uint64_t len, uint32_t sum2) { +static inline uint32_t adler32_copy_len_16(uint32_t adler, const uint8_t *buf, uint8_t *dst, size_t len, uint32_t sum2) { while (len--) { *dst = *buf++; adler += *dst++; @@ -50,7 +50,7 @@ static inline uint32_t adler32_copy_len_16(uint32_t adler, const uint8_t *buf, u return adler | (sum2 << 16); } -static inline uint32_t adler32_len_64(uint32_t adler, const uint8_t *buf, uint64_t len, uint32_t sum2) { +static inline uint32_t adler32_len_64(uint32_t adler, const uint8_t *buf, size_t len, uint32_t sum2) { #ifdef UNROLL_MORE while (len >= 16) { len -= 16; diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index 9b9d65ddd4..c8871cc0cd 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -10,7 +10,7 @@ #include "../../zbuild.h" #include "../../adler32_p.h" -static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { +static void NEON_accum32(uint32_t *s, const uint8_t *buf, size_t len) { static const uint16_t ALIGNED_(16) taps[64] = { 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, @@ -39,10 +39,10 @@ static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { uint16x8_t s2_4, s2_5, s2_6, s2_7; s2_4 = s2_5 = s2_6 = s2_7 = vdupq_n_u16(0); - uint64_t num_iter = len >> 2; + size_t num_iter = len >> 2; int rem = len & 3; - for (uint64_t i = 0; i < num_iter; ++i) { + for (size_t i = 0; i < num_iter; ++i) { uint8x16x4_t d0_d3 = vld1q_u8_x4(buf); /* Unfortunately it doesn't look like there's a direct sum 8 bit to 32 @@ -133,7 +133,7 @@ static void NEON_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { s[1] = vget_lane_u32(as, 1); } -static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, uint64_t len) { +static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, size_t len) { unsigned int i; for (i = 0; i < len; ++i) { pair[0] += buf[i]; @@ -141,7 +141,7 @@ static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, uint64_t len) { } } -uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, uint64_t len) { +uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len) { /* split Adler-32 into component sums */ uint32_t sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; diff --git a/arch/power/adler32_power8.c b/arch/power/adler32_power8.c index 0e8e0d162c..497e2f92c8 100644 --- a/arch/power/adler32_power8.c +++ b/arch/power/adler32_power8.c @@ -52,7 +52,7 @@ static inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsi return __a; } -uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, uint64_t len) { +uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len) { uint32_t s1 = adler & 0xffff; uint32_t s2 = (adler >> 16) & 0xffff; diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index 2c8eb68270..1b648820d0 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -12,7 +12,7 @@ #define vmx_zero() (vec_splat_u32(0)) -static inline void vmx_handle_head_or_tail(uint32_t *pair, const uint8_t *buf, uint64_t len) { +static inline void vmx_handle_head_or_tail(uint32_t *pair, const uint8_t *buf, size_t len) { unsigned int i; for (i = 0; i < len; ++i) { pair[0] += buf[i]; @@ -20,7 +20,7 @@ static inline void vmx_handle_head_or_tail(uint32_t *pair, const uint8_t *buf, u } } -static void vmx_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { +static void vmx_accum32(uint32_t *s, const uint8_t *buf, size_t len) { /* Different taps for the separable components of sums */ const vector unsigned char t0 = {64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49}; const vector unsigned char t1 = {48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33}; @@ -113,7 +113,7 @@ static void vmx_accum32(uint32_t *s, const uint8_t *buf, uint64_t len) { vec_ste(s2acc, 0, s+1); } -uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, uint64_t len) { +uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len) { uint32_t sum2; uint32_t pair[16] ALIGNED_(16); memset(&pair[2], 0, 14); diff --git a/arch/x86/adler32_avx2_tpl.h b/arch/x86/adler32_avx2_tpl.h index 4ff1838de0..0b2e89be43 100644 --- a/arch/x86/adler32_avx2_tpl.h +++ b/arch/x86/adler32_avx2_tpl.h @@ -11,8 +11,8 @@ #include "adler32_avx2_p.h" #ifdef X86_SSE42_ADLER32 -extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); -extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, uint64_t len); +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len); #define copy_sub32(a, b, c, d) adler32_fold_copy_sse42(a, b, c, d) #define sub32(a, b, c) adler32_ssse3(a, b, c) @@ -22,9 +22,9 @@ extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, uint64_t len); #endif #ifdef COPY -Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { #else -Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) { #endif if (src == NULL) return 1L; if (len == 0) return adler; @@ -61,7 +61,7 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, uint64_t le __m256i vs1_0 = vs1; __m256i vs3 = _mm256_setzero_si256(); - uint64_t k = MIN(len, NMAX); + size_t k = MIN(len, NMAX); k -= k % 32; len -= k; diff --git a/arch/x86/adler32_avx512_tpl.h b/arch/x86/adler32_avx512_tpl.h index 2419865988..6ed39b45df 100644 --- a/arch/x86/adler32_avx512_tpl.h +++ b/arch/x86/adler32_avx512_tpl.h @@ -14,9 +14,9 @@ #ifdef X86_AVX512_ADLER32 #ifdef COPY -Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { #else -Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t len) { #endif if (src == NULL) return 1L; @@ -52,7 +52,7 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, uint64_t 56, 57, 58, 59, 60, 61, 62, 63, 64); const __m512i dot3v = _mm512_set1_epi16(1); const __m512i zero = _mm512_setzero_si512(); - uint64_t k; + size_t k; while (len >= 64) { __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index ecebdec733..42a166062f 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -18,7 +18,7 @@ #include "adler32_avx512_p.h" #include "adler32_avx2_p.h" -Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size_t len) { if (src == NULL) return 1L; if (len == 0) return adler; @@ -54,7 +54,7 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, uint while (len >= 64) { vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1)); - uint64_t k = MIN(len, NMAX); + size_t k = MIN(len, NMAX); k -= k % 64; len -= k; __m512i vs1_0 = vs1; @@ -120,7 +120,7 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, uint return adler; } -Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { if (src == NULL) return 1L; if (len == 0) return adler; @@ -151,7 +151,7 @@ Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, while (len >= 32) { vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0)); vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1)); - uint64_t k = MIN(len, NMAX); + size_t k = MIN(len, NMAX); k -= k % 32; len -= k; __m256i vs1_0 = vs1; diff --git a/arch/x86/adler32_sse42.c b/arch/x86/adler32_sse42.c index 5e68e4c41e..ec0513409b 100644 --- a/arch/x86/adler32_sse42.c +++ b/arch/x86/adler32_sse42.c @@ -14,7 +14,7 @@ #ifdef X86_SSE42_ADLER32 -Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { uint32_t adler0, adler1; adler1 = (adler >> 16) & 0xffff; adler0 = adler & 0xffff; @@ -31,7 +31,7 @@ Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); const __m128i dot3v = _mm_set1_epi16(1); - uint64_t k; + size_t k; while (len >= 16) { diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 45fddd42af..1f4abba507 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -14,7 +14,7 @@ #include -Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, uint64_t len) { +Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len) { uint32_t sum2; /* split Adler-32 into component sums */ @@ -46,10 +46,10 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, uint64_t l * additions worthwhile or if it's worth it to just eat the cost of an unaligned * load. This is a pretty simple test, just test if 16 - the remainder + len is * < 16 */ - uint64_t max_iters = NMAX; - uint64_t rem = (uintptr_t)buf & 15; - uint64_t align_offset = 16 - rem; - uint64_t k = 0; + size_t max_iters = NMAX; + size_t rem = (uintptr_t)buf & 15; + size_t align_offset = 16 - rem; + size_t k = 0; if (rem) { if (len < 16 + align_offset) { /* Let's eat the cost of this one unaligned load so that diff --git a/cpu_features.h b/cpu_features.h index 9d10ce7df0..72e40a1652 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -23,43 +23,43 @@ extern void cpu_check_features(void); /* adler32 */ -typedef uint32_t (*adler32_func)(uint32_t adler, const uint8_t *buf, uint64_t len); +typedef uint32_t (*adler32_func)(uint32_t adler, const uint8_t *buf, size_t len); -extern uint32_t adler32_c(uint32_t adler, const uint8_t *buf, uint64_t len); +extern uint32_t adler32_c(uint32_t adler, const uint8_t *buf, size_t len); #ifdef ARM_NEON_ADLER32 -extern uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, uint64_t len); +extern uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len); #endif #ifdef PPC_VMX_ADLER32 -extern uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, uint64_t len); +extern uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len); #endif #ifdef X86_SSSE3_ADLER32 -extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, uint64_t len); +extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len); #endif #ifdef X86_AVX2_ADLER32 -extern uint32_t adler32_avx2(uint32_t adler, const uint8_t *buf, uint64_t len); +extern uint32_t adler32_avx2(uint32_t adler, const uint8_t *buf, size_t len); #endif #ifdef X86_AVX512_ADLER32 -extern uint32_t adler32_avx512(uint32_t adler, const uint8_t *buf, uint64_t len); +extern uint32_t adler32_avx512(uint32_t adler, const uint8_t *buf, size_t len); #endif #ifdef X86_AVX512VNNI_ADLER32 -extern uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *buf, uint64_t len); +extern uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *buf, size_t len); #endif #ifdef POWER8_VSX_ADLER32 -extern uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, uint64_t len); +extern uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len); #endif /* adler32 folding */ #ifdef X86_SSE42_ADLER32 -extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif #ifdef X86_AVX2_ADLER32 -extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); +extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif #ifdef X86_AVX512_ADLER32 -extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); +extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif #ifdef X86_AVX512VNNI_ADLER32 -extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); +extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif /* CRC32 folding */ diff --git a/functable.c b/functable.c index 5dd5e54d4c..260d52f2f3 100644 --- a/functable.c +++ b/functable.c @@ -162,7 +162,7 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc return functable.longest_match_slow(s, cur_match); } -Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const uint8_t *buf, uint64_t len) { +Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const uint8_t *buf, size_t len) { // Initialize default functable.adler32 = &adler32_c; cpu_check_features(); @@ -202,7 +202,7 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const uint8_t *buf, uint64_t le return functable.adler32(adler, buf, len); } -Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { functable.adler32_fold_copy = &adler32_fold_copy_c; #if (defined X86_SSE42_ADLER32) if (x86_cpu_has_sse42) diff --git a/functable.h b/functable.h index 9b6ec3b542..531f3a1cef 100644 --- a/functable.h +++ b/functable.h @@ -11,8 +11,8 @@ #include "adler32_fold.h" struct functable_s { - uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, uint64_t len); - uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); + uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, size_t len); + uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, size_t len); uint32_t (* crc32_fold_reset) (struct crc32_fold_s *crc); void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, size_t len); diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index 71ac72f295..f89659a7f1 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -18,7 +18,7 @@ extern "C" { #define MAX_RANDOM_INTS (1024 * 1024) #define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t)) -typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const uint8_t *buf, uint64_t len); +typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const uint8_t *buf, size_t len); class adler32_copy: public benchmark::Fixture { private: @@ -76,7 +76,7 @@ class adler32_copy: public benchmark::Fixture { state.SkipWithError("CPU does not support " #name); \ } \ Bench(state, [](uint32_t init_sum, unsigned char *dst, \ - const uint8_t *buf, uint64_t len) -> uint32_t { \ + const uint8_t *buf, size_t len) -> uint32_t { \ memcpy(dst, buf, (size_t)len); \ return fptr(init_sum, buf, len); \ }); \ From 41a5e00e7c9fd8fce5c2135fe412d4e0f3f15eb3 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 30 Sep 2022 18:59:55 +0100 Subject: [PATCH 550/798] Fix MSVC warnings in benchmark code --- test/benchmarks/benchmark_adler32.cc | 2 +- test/benchmarks/benchmark_adler32_copy.cc | 2 +- test/benchmarks/benchmark_crc32.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index b691c23ff8..b94912ac96 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -42,7 +42,7 @@ class adler32: public benchmark::Fixture { uint32_t hash = 0; for (auto _ : state) { - hash = adler32(hash, (const unsigned char *)random_ints, state.range(0)); + hash = adler32(hash, (const unsigned char *)random_ints, (size_t)state.range(0)); } benchmark::DoNotOptimize(hash); diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index f89659a7f1..62998d41ee 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -49,7 +49,7 @@ class adler32_copy: public benchmark::Fixture { for (auto _ : state) { hash = adler32_func(hash, (unsigned char *)random_ints_dst, - (const unsigned char*)random_ints_src, state.range(0)); + (const unsigned char*)random_ints_src, (size_t)state.range(0)); } benchmark::DoNotOptimize(hash); diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index 2cea046607..f17ebf6c11 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -35,7 +35,7 @@ class crc32: public benchmark::Fixture { uint32_t hash = 0; for (auto _ : state) { - hash = crc32(hash, (const unsigned char *)random_ints, state.range(0)); + hash = crc32(hash, (const unsigned char *)random_ints, (size_t)state.range(0)); } benchmark::DoNotOptimize(hash); From 147dd9f0e9537af15fab17b1887149874f20a474 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Tue, 17 Jan 2023 04:39:37 +0300 Subject: [PATCH 551/798] Match __builtin_ctzl/__builtin_ctzll signatures make sure input/output args match original functions from clang/gcc --- fallback_builtins.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fallback_builtins.h b/fallback_builtins.h index eacaee36bf..5b49205ec6 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -12,16 +12,16 @@ /* This is not a general purpose replacement for __builtin_ctz. The function expects that value is != 0 * Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward is not checked */ -static __forceinline unsigned long __builtin_ctz(uint32_t value) { +static __forceinline int __builtin_ctz(unsigned int value) { #ifdef X86_FEATURES # ifndef X86_NOCHECK_TZCNT if (x86_cpu_has_tzcnt) # endif - return _tzcnt_u32(value); + return (int)_tzcnt_u32(value); #endif unsigned long trailing_zero; _BitScanForward(&trailing_zero, value); - return trailing_zero; + return (int)trailing_zero; } #define HAVE_BUILTIN_CTZ @@ -29,16 +29,16 @@ static __forceinline unsigned long __builtin_ctz(uint32_t value) { /* This is not a general purpose replacement for __builtin_ctzll. The function expects that value is != 0 * Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward64 is not checked */ -static __forceinline unsigned long long __builtin_ctzll(uint64_t value) { +static __forceinline int __builtin_ctzll(unsigned long long value) { #ifdef X86_FEATURES # ifndef X86_NOCHECK_TZCNT if (x86_cpu_has_tzcnt) # endif - return _tzcnt_u64(value); + return (int)_tzcnt_u64(value); #endif unsigned long trailing_zero; _BitScanForward64(&trailing_zero, value); - return trailing_zero; + return (int)trailing_zero; } #define HAVE_BUILTIN_CTZLL #endif // Microsoft AMD64 From 750a7a014a3e41d5663fc73fbedfb8eeab6603fe Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Tue, 13 Dec 2022 22:06:43 +0200 Subject: [PATCH 552/798] Fix ABI checking... * Ubuntu 22.04 use different format for ABI files so old ones need to be removed * Use more recent zlib-ng commit to avoid issues with internal adler32 and crc32 functions --- .gitattributes | 2 + ...25f673caa4c2-aarch64-unknown-linux-gnu.abi | 1286 ++++++++++ ...25f673caa4c2-arm-unknown-linux-gnueabi.abi | 1276 ++++++++++ ...f673caa4c2-arm-unknown-linux-gnueabihf.abi | 1276 ++++++++++ ...25f673caa4c2-powerpc-unknown-linux-gnu.abi | 1286 ++++++++++ ...f673caa4c2-powerpc64-unknown-linux-gnu.abi | 1268 ++++++++++ ...73caa4c2-powerpc64le-unknown-linux-gnu.abi | 1268 ++++++++++ ...5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi | 1263 ++++++++++ ...6ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi} | 28 +- ...06f73a84eef4-aarch64-unknown-linux-gnu.abi | 1958 +++++++++++++++ ...06f73a84eef4-arm-unknown-linux-gnueabi.abi | 1943 +++++++++++++++ ...f73a84eef4-arm-unknown-linux-gnueabihf.abi | 1935 +++++++++++++++ ...06f73a84eef4-powerpc-unknown-linux-gnu.abi | 1949 +++++++++++++++ ...f73a84eef4-powerpc64-unknown-linux-gnu.abi | 1948 +++++++++++++++ ...3a84eef4-powerpc64le-unknown-linux-gnu.abi | 1940 +++++++++++++++ ...dd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi | 2076 ++++++++++++++++ ...73ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi | 2108 +++++++++++++++++ ...661012b02acdd30281-x86_64-pc-linux-gnu.abi | 1533 ------------ test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi | 119 - test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi | 1037 -------- test/abicheck.sh | 2 +- 21 files changed, 24797 insertions(+), 2704 deletions(-) create mode 100644 test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-aarch64-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabi.abi create mode 100644 test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabihf.abi create mode 100644 test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64le-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi rename test/abi/{zlib-v1.2.12-x86_64-pc-linux-gnu.abi => zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi} (99%) create mode 100644 test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-aarch64-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabi.abi create mode 100644 test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabihf.abi create mode 100644 test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64le-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi create mode 100644 test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi delete mode 100644 test/abi/zlib-ng-843c16c87afd53a20bf915661012b02acdd30281-x86_64-pc-linux-gnu.abi delete mode 100644 test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi delete mode 100644 test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi diff --git a/.gitattributes b/.gitattributes index 0b0d147e62..ac21ec4592 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,8 @@ * text=auto +*.abi text eol=lf *.c text *.h text +*.sh text eol=lf crc32_braid_tbl.h hooks-max-size=1000000 Makefile text configure text eol=lf diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-aarch64-unknown-linux-gnu.abi b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-aarch64-unknown-linux-gnu.abi new file mode 100644 index 0000000000..e39b64cfb1 --- /dev/null +++ b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-aarch64-unknown-linux-gnu.abi @@ -0,0 +1,1286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabi.abi b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabi.abi new file mode 100644 index 0000000000..839c6ac9a9 --- /dev/null +++ b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabi.abi @@ -0,0 +1,1276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabihf.abi b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabihf.abi new file mode 100644 index 0000000000..fd5f2aded2 --- /dev/null +++ b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabihf.abi @@ -0,0 +1,1276 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc-unknown-linux-gnu.abi b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc-unknown-linux-gnu.abi new file mode 100644 index 0000000000..3bd1f5b169 --- /dev/null +++ b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc-unknown-linux-gnu.abi @@ -0,0 +1,1286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64-unknown-linux-gnu.abi b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64-unknown-linux-gnu.abi new file mode 100644 index 0000000000..161d088f7f --- /dev/null +++ b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64-unknown-linux-gnu.abi @@ -0,0 +1,1268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64le-unknown-linux-gnu.abi b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64le-unknown-linux-gnu.abi new file mode 100644 index 0000000000..bb67512a8e --- /dev/null +++ b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64le-unknown-linux-gnu.abi @@ -0,0 +1,1268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi new file mode 100644 index 0000000000..1f0ae6d801 --- /dev/null +++ b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi @@ -0,0 +1,1263 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-v1.2.12-x86_64-pc-linux-gnu.abi b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi similarity index 99% rename from test/abi/zlib-v1.2.12-x86_64-pc-linux-gnu.abi rename to test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi index efe7e02ac4..bae68adb72 100644 --- a/test/abi/zlib-v1.2.12-x86_64-pc-linux-gnu.abi +++ b/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi @@ -1,4 +1,4 @@ - + @@ -92,7 +92,7 @@ - + @@ -134,7 +134,7 @@ - + @@ -157,7 +157,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -716,7 +716,7 @@ - + @@ -743,7 +743,7 @@ - + @@ -834,7 +834,7 @@ - + @@ -972,7 +972,7 @@ - + @@ -1055,7 +1055,7 @@ - + @@ -1131,7 +1131,7 @@ - + @@ -1222,7 +1222,7 @@ - + @@ -1236,7 +1236,7 @@ - + @@ -1253,7 +1253,7 @@ - + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-aarch64-unknown-linux-gnu.abi b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-aarch64-unknown-linux-gnu.abi new file mode 100644 index 0000000000..9aa91cef2e --- /dev/null +++ b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-aarch64-unknown-linux-gnu.abi @@ -0,0 +1,1958 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabi.abi b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabi.abi new file mode 100644 index 0000000000..7a99d6d4d2 --- /dev/null +++ b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabi.abi @@ -0,0 +1,1943 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabihf.abi b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabihf.abi new file mode 100644 index 0000000000..b3f30ff36d --- /dev/null +++ b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabihf.abi @@ -0,0 +1,1935 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc-unknown-linux-gnu.abi b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc-unknown-linux-gnu.abi new file mode 100644 index 0000000000..81bda0d88d --- /dev/null +++ b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc-unknown-linux-gnu.abi @@ -0,0 +1,1949 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64-unknown-linux-gnu.abi b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64-unknown-linux-gnu.abi new file mode 100644 index 0000000000..4ca3102ef1 --- /dev/null +++ b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64-unknown-linux-gnu.abi @@ -0,0 +1,1948 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64le-unknown-linux-gnu.abi b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64le-unknown-linux-gnu.abi new file mode 100644 index 0000000000..2862e2a5b6 --- /dev/null +++ b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64le-unknown-linux-gnu.abi @@ -0,0 +1,1940 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi new file mode 100644 index 0000000000..aac9172f54 --- /dev/null +++ b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi @@ -0,0 +1,2076 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi new file mode 100644 index 0000000000..12e224dbc3 --- /dev/null +++ b/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi @@ -0,0 +1,2108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-843c16c87afd53a20bf915661012b02acdd30281-x86_64-pc-linux-gnu.abi b/test/abi/zlib-ng-843c16c87afd53a20bf915661012b02acdd30281-x86_64-pc-linux-gnu.abi deleted file mode 100644 index 68b313d7fb..0000000000 --- a/test/abi/zlib-ng-843c16c87afd53a20bf915661012b02acdd30281-x86_64-pc-linux-gnu.abi +++ /dev/null @@ -1,1533 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi b/test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi deleted file mode 100644 index 152a742cf9..0000000000 --- a/test/abi/zlib-v1.2.11-arm-linux-gnueabihf.abi +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi b/test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi deleted file mode 100644 index 00a520c63c..0000000000 --- a/test/abi/zlib-v1.2.11-x86_64-linux-gnu.abi +++ /dev/null @@ -1,1037 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/abicheck.sh b/test/abicheck.sh index 30cbcf5061..a759db78b9 100755 --- a/test/abicheck.sh +++ b/test/abicheck.sh @@ -73,7 +73,7 @@ then else # Reference is most recent zlib-ng develop with zlib 1.2.12 compatible api. ABI_GIT_REPO=https://github.com/zlib-ng/zlib-ng.git - ABI_GIT_COMMIT=843c16c87afd53a20bf915661012b02acdd30281 + ABI_GIT_COMMIT=1ab443812aceab6c80ccd573ecdd06f73a84eef4 fi # Test compat build for ABI compatibility with zlib From 9119de005ba215c8dbd92710fc5e4fc26b81e19c Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Thu, 2 Feb 2023 16:06:52 +0100 Subject: [PATCH 553/798] Fix typo found by codespell --- cmake/detect-intrinsics.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 3fa74b483f..92caf7abaf 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -384,7 +384,7 @@ macro(check_sse2_intrinsics) set(SSE2FLAG "-msse2") endif() endif() - # Check whether compiler supports SSE2 instrinics + # Check whether compiler supports SSE2 intrinsics set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include @@ -496,7 +496,7 @@ macro(check_sse42_intrinsics) }" HAVE_SSE42CRC_INTRIN ) - # Check whether compiler supports SSE4.2 compare string instrinics + # Check whether compiler supports SSE4.2 compare string intrinsics check_c_source_compile_or_run( "#include int main(void) { From cba1a784ab68cffbb5f5ec02653a392384238fdd Mon Sep 17 00:00:00 2001 From: Pavel P Date: Mon, 23 Jan 2023 00:48:10 +0300 Subject: [PATCH 554/798] Add temporary cmake build dirs/files to gitignore --- .gitignore | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index e5aac03292..cd4a9c3fee 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ foo.gz *.sdf *.vcxproj *.vcxproj.filters +*.vcxproj.user .vs CMakeCache.txt @@ -58,6 +59,8 @@ zconf.h.included zconf-ng.h zconf-ng.h.cmakein ztest* +/test/CTestTestfile.cmake +/test/cmake_install.cmake configure.log a.out @@ -75,7 +78,7 @@ a.out /minigzip.dir /zlib.dir /zlibstatic.dir -/win32/Debug +/test/*.dir/ /build/ /build[.-]*/ /btmp[12]/ @@ -83,3 +86,12 @@ a.out /.idea /cmake-build-debug +/x64/Debug/ +/x64/Release/ +/win32/Debug/ +/win32/Release/ +/ARM*/Debug/ +/ARM*/Release/ +MinSizeRel +RelWithDebInfo +/_deps/googletest* From 78d5883a9cc6dd96858b770b9fe1cfa675f81e6f Mon Sep 17 00:00:00 2001 From: Pavel P Date: Tue, 17 Jan 2023 04:42:24 +0300 Subject: [PATCH 555/798] Add assert for tzcnt if building with X86_NOCHECK_TZCNT --- arch/x86/x86_features.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index d1ac51c55c..4c7563eab0 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -122,4 +122,7 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_has_avx512vnni = 0; x86_cpu_has_vpclmulqdq = 0; } +#ifdef X86_NOCHECK_TZCNT + Assert(!!x86_cpu_has_tzcnt, "TZCNT is not available"); +#endif } From b892331cf74771813073e295ac4d14d2c35ea3dd Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 20 Jan 2023 23:37:36 +0200 Subject: [PATCH 556/798] Fix MinGW build * Add detection of XSAVE intrinsics --- CMakeLists.txt | 5 +++++ arch/x86/Makefile.in | 5 +++-- cmake/detect-intrinsics.cmake | 18 ++++++++++++++++++ configure | 31 +++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4400fea584..059017e16c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -883,6 +883,11 @@ if(WITH_OPTIM) set(WITH_PCLMULQDQ OFF) set(WITH_VPCLMULQDQ OFF) endif() + check_xsave_intrinsics() + if(HAVE_XSAVE_INTRIN) + add_feature_info(XSAVE 1 "Support XSAVE intrinsics using \"${XSAVEFLAG}\"") + set_property(SOURCE ${ARCHDIR}/x86_features.c PROPERTY COMPILE_FLAGS "${XSAVEFLAG}") + endif() endif() endif() diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index f9aedf82ba..a3d5283b91 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -17,6 +17,7 @@ SSE41FLAG=-msse4.1 SSE42FLAG=-msse4.2 PCLMULFLAG=-mpclmul VPCLMULFLAG=-mvpclmulqdq +XSAVEFLAG=-mxsave NOLTOFLAG= SRCDIR=. @@ -42,10 +43,10 @@ all: \ slide_hash_sse2.o slide_hash_sse2.lo x86_features.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c + $(CC) $(CFLAGS) $(XSAVEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c x86_features.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c + $(CC) $(SFLAGS) $(XSAVEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c chunkset_avx.o: $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 92caf7abaf..3e932d83b2 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -536,3 +536,21 @@ macro(check_vgfma_intrinsics) HAVE_VGFMA_INTRIN FAIL_REGEX "not supported") set(CMAKE_REQUIRED_FLAGS) endmacro() + +macro(check_xsave_intrinsics) + if(NOT NATIVEFLAG AND NOT MSVC) + set(XSAVEFLAG "-mxsave") + endif() + set(CMAKE_REQUIRED_FLAGS "${XSAVEFLAG} ${NATIVEFLAG}") + check_c_source_compiles( + "#ifdef _WIN32 + # include + #else + # include + #endif + int main(void) { + return _xgetbv(0); + }" + HAVE_XSAVE_INTRIN FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) +endmacro() diff --git a/configure b/configure index 8dae722a69..53a3a08efc 100755 --- a/configure +++ b/configure @@ -115,6 +115,7 @@ sse41flag="-msse4.1" sse42flag="-msse4.2" pclmulflag="-mpclmul" vpclmulflag="-mvpclmulqdq -mavx512f" +xsaveflag="-mxsave" acleflag= neonflag= noltoflag="-fno-lto" @@ -268,6 +269,7 @@ if test $native -eq 1; then sse42flag="" pclmulflag="" vpclmulflag="" + xsaveflag="" noltoflag="" fi @@ -1224,6 +1226,27 @@ EOF fi } +check_xsave_intrinsics() { + # Check whether compiler supports XSAVE intrinsics + cat > $test.c << EOF +#ifdef _WIN32 +# include +#else +# include +#endif +int main(void) { + return _xgetbv(0); +} +EOF + if try ${CC} ${CFLAGS} ${xsaveflag} $test.c; then + echo "Checking for XSAVE intrinsics ... Yes." | tee -a configure.log + HAVE_XSAVE_INTRIN=1 + else + echo "Checking for XSAVE intrinsics ... No." | tee -a configure.log + HAVE_XSAVE_INTRIN=0 + fi +} + check_ppc_intrinsics() { cat > $test.c << EOF #include @@ -1605,6 +1628,12 @@ case "${ARCH}" in fi fi + check_xsave_intrinsics + + if test ${HAVE_XSAVE_INTRIN} -eq 0; then + xsaveflag="" + fi + if test $forcetzcnt -eq 1; then CFLAGS="${CFLAGS} -DX86_NOCHECK_TZCNT" SFLAGS="${SFLAGS} -DX86_NOCHECK_TZCNT" @@ -2044,6 +2073,7 @@ echo sse41flag = $sse41flag >> configure.log echo sse42flag = $sse42flag >> configure.log echo pclmulflag = $pclmulflag >> configure.log echo vpclmulflag = $vpclmulflag >> configure.log +echo xsaveflag = $xsaveflag >> configure.log echo acleflag = $acleflag >> configure.log echo neonflag = $neonflag >> configure.log echo ARCHDIR = ${ARCHDIR} >> configure.log @@ -2181,6 +2211,7 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^SSE42FLAG *=/s#=.*#=$sse42flag# /^PCLMULFLAG *=/s#=.*#=$pclmulflag# /^VPCLMULFLAG *=/s#=.*#=$vpclmulflag# +/^XSAVEFLAG *=/s#=.*#=$xsaveflag# /^ACLEFLAG *=/s#=.*#=$acleflag# /^NEONFLAG *=/s#=.*#=$neonflag# /^NOLTOFLAG *=/s#=.*#=$noltoflag# From b48750ddc33bd049f10fa74ccd89f2abbe6cbf25 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 22 Jan 2023 00:57:18 +0200 Subject: [PATCH 557/798] Fix configure to use correct linker definition file when --without-gzfileops is specified. --- configure | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 53a3a08efc..3879134b8b 100755 --- a/configure +++ b/configure @@ -432,7 +432,9 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then LDSHARED=${LDSHARED-"$cc"} LDSHAREDFLAGS="-shared -Wl,--out-implib,${IMPORTLIB},--version-script,${SRCDIR}/${MAPNAME}" LDSHAREDLIBC="" - DEFFILE='win32/${LIBNAME2}.def' + if test $gzfileops -eq 0; then + DEFFILE='win32/${LIBNAME2}.def' + fi RC="${CROSS_PREFIX}windres" RCOBJS='zlibrc.o' STRIP="${CROSS_PREFIX}strip" @@ -454,7 +456,9 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then LDSHARED=${LDSHARED-"$cc"} LDSHAREDFLAGS="-shared -Wl,--out-implib,${IMPORTLIB}" LDSHAREDLIBC="" - DEFFILE='win32/${LIBNAME2}.def' + if test $gzfileops -eq 0; then + DEFFILE='win32/${LIBNAME2}.def' + fi RC="${CROSS_PREFIX}windres" RCOBJS='zlibrc.o' STRIP="${CROSS_PREFIX}strip" @@ -473,7 +477,9 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then LDSHARED=${LDSHARED-"$cc"} LDSHAREDFLAGS="-shared -Wl,--out-implib=${IMPORTLIB} -Wl,--version-script=${SRCDIR}/${MAPNAME}" LDSHAREDLIBC="" - DEFFILE='win32/${LIBNAME2}.def' + if test $gzfileops -eq 0; then + DEFFILE='win32/${LIBNAME2}.def' + fi RC="${CROSS_PREFIX}windres" if [ "$CC" == "mingw32-gcc" ]; then case $ARCH in From 5ff2b9bfca3ca757936695710022a3fe119951dc Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 22 Jan 2023 00:59:08 +0200 Subject: [PATCH 558/798] Add support for symbol prefix to linker definition files. --- configure | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configure b/configure index 3879134b8b..fa751b84ff 100755 --- a/configure +++ b/configure @@ -857,6 +857,11 @@ if test $compat -eq 1; then esac fi +if [[ ! -z $DEFFILE ]]; then + mkdir -p win32 + sed < $SRCDIR/$DEFFILE.in "s/@ZLIB_SYMBOL_PREFIX@/$symbol_prefix/g" > $DEFFILE +fi + # if --gzfileops was requested if test $gzfileops -eq 1; then CFLAGS="${CFLAGS} -DWITH_GZFILEOP" From 1cb12dcf14826d1b8c75d0a68b5dce652e29ed24 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 22 Jan 2023 01:04:55 +0200 Subject: [PATCH 559/798] Fix building resource files during out-of-tree build with configure --- Makefile.in | 4 ++-- configure | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index 88d40cb662..aebd9a7b70 100644 --- a/Makefile.in +++ b/Makefile.in @@ -212,8 +212,8 @@ maketrees.o: makecrct.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/tools/makecrct.c -zlibrc.o: win32/zlib$(SUFFIX)1.rc - $(RC) $(RCFLAGS) -o $@ win32/zlib$(SUFFIX)1.rc +zlibrc.o: $(SRCDIR)/win32/zlib$(SUFFIX)1.rc + $(RC) $(RCFLAGS) -o $@ $(SRCDIR)/win32/zlib$(SUFFIX)1.rc .SUFFIXES: .lo diff --git a/configure b/configure index fa751b84ff..89b49a4384 100755 --- a/configure +++ b/configure @@ -436,6 +436,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then DEFFILE='win32/${LIBNAME2}.def' fi RC="${CROSS_PREFIX}windres" + RCFLAGS="-I ${BUILDDIR}" RCOBJS='zlibrc.o' STRIP="${CROSS_PREFIX}strip" EXE='.exe' ;; @@ -460,6 +461,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then DEFFILE='win32/${LIBNAME2}.def' fi RC="${CROSS_PREFIX}windres" + RCFLAGS="-I ${BUILDDIR}" RCOBJS='zlibrc.o' STRIP="${CROSS_PREFIX}strip" EXE='.exe' ;; @@ -481,6 +483,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then DEFFILE='win32/${LIBNAME2}.def' fi RC="${CROSS_PREFIX}windres" + RCFLAGS="-I ${BUILDDIR}" if [ "$CC" == "mingw32-gcc" ]; then case $ARCH in i386 | i486 | i586 | i686) RCFLAGS="${RCFLAGS} -F pe-i386";; From bfbbea778cfeeab0222d4fa0f01a63f01b38646f Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 22 Jan 2023 01:12:24 +0200 Subject: [PATCH 560/798] Fix missing gzip functions when linking example and minigzip binaries. --- Makefile.in | 13 +++++++------ configure | 3 +++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Makefile.in b/Makefile.in index aebd9a7b70..98b9042eb4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -109,6 +109,7 @@ OBJG = \ gzread.o \ gzwrite.o +TESTOBJG = OBJC = $(OBJZ) $(OBJG) PIC_OBJZ = \ @@ -254,20 +255,20 @@ ifneq ($(SHAREDLIB),$(SHAREDTARGET)) endif endif -example$(EXE): example.o $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TEST_LIBS) $(LDSHAREDLIBC) +example$(EXE): example.o $(TESTOBJG) $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(TESTOBJG) $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -minigzip$(EXE): minigzip.o $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS) $(LDSHAREDLIBC) +minigzip$(EXE): minigzip.o $(TESTOBJG) $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TESTOBJG) $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -minigzipsh$(EXE): minigzip.o $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(SHAREDLIB) $(LDSHAREDLIBC) +minigzipsh$(EXE): minigzip.o $(PIC_TESTOBJG) $(SHAREDTARGET) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(PIC_TESTOBJG) $(SHAREDLIB) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif diff --git a/configure b/configure index 89b49a4384..b05a731428 100755 --- a/configure +++ b/configure @@ -872,6 +872,7 @@ if test $gzfileops -eq 1; then OBJC="${OBJC} \$(OBJG)" PIC_OBJC="${PIC_OBJC} \$(PIC_OBJG)" else + TESTOBJG="\$(OBJG)" PIC_TESTOBJG="\$(OBJG)" fi @@ -2056,6 +2057,7 @@ echo RCFLAGS = $RCFLAGS >> configure.log echo RCOBJS = $RCOBJS >> configure.log echo STRIP = $STRIP >> configure.log echo OBJC = $OBJC >> configure.log +echo TESTOBJG = $TESTOBJG >> configure.log echo PIC_TESTOBJG = $PIC_TESTOBJG >> configure.log echo PIC_OBJC = $PIC_OBJC >> configure.log echo RANLIB = $RANLIB >> configure.log @@ -2148,6 +2150,7 @@ sed < $SRCDIR/Makefile.in " /^SRCDIR *=/s#=.*#=$SRCDIR# /^INCLUDES *=/s#=.*#=$INCLUDES# /^OBJC *=/s#=.*#= $OBJC# +/^TESTOBJG *=/s#=.*#= $TESTOBJG# /^PIC_TESTOBJG *=/s#=.*#= $PIC_TESTOBJG# /^PIC_OBJC *=/s#=.*#= $PIC_OBJC# /^all: */s#:.*#: $ALL# From a02ba01ddcad7696b82e6c3b587726f423bbfe42 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 22 Jan 2023 01:16:11 +0200 Subject: [PATCH 561/798] Allow disabling visibility attribute with configure * Disable visibility check for Cygwin, MinGW and MSYS as the compiler will only issue warning instead of error for unsupported attributes. --- configure | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configure b/configure index b05a731428..59c4a7e6a7 100755 --- a/configure +++ b/configure @@ -128,6 +128,7 @@ reducedmem=0 gcc=0 warn=0 debug=0 +visibility=1 old_cc="$CC" old_cflags="$CFLAGS" OBJC='$(OBJZ)' @@ -416,6 +417,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then LDSHAREDFLAGS="-shared -Wl,-soname,${LIBNAME}.so.${VER1},--version-script,${SRCDIR}/${MAPNAME}" LDCONFIG="ldconfig -m" ;; CYGWIN* | Cygwin* | cygwin*) + visibility=0 ARFLAGS="rcs" SFLAGS="${CFLAGS}" shared_ext='.dll' @@ -441,6 +443,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then STRIP="${CROSS_PREFIX}strip" EXE='.exe' ;; MSYS* | msys*) + visibility=0 ARFLAGS="rcs" SFLAGS="${CFLAGS}" shared_ext='.dll' @@ -466,6 +469,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then STRIP="${CROSS_PREFIX}strip" EXE='.exe' ;; MINGW* | mingw*) + visibility=0 ARFLAGS="rcs" CFLAGS="${CFLAGS} -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE=1 -Wno-pedantic-ms-format" SFLAGS="${CFLAGS}" @@ -948,7 +952,7 @@ EOF fi # see if we can hide zlib internal symbols that are linked between separate source files using hidden -if test "$gcc" -eq 1; then +if test "$gcc" -eq 1 && test "$visibility" -eq 1; then echo >> configure.log cat > $test.c <> configure.log cat > $test.c < Date: Thu, 26 May 2022 08:47:51 -0700 Subject: [PATCH 562/798] Have build test report library version if it doesn't match zlib.h. --- test/example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example.c b/test/example.c index c6556ed197..8644bdce5a 100644 --- a/test/example.c +++ b/test/example.c @@ -962,7 +962,7 @@ int main(int argc, char *argv[]) { exit(1); } else if (strcmp(zVersion(), PREFIX2(VERSION)) != 0) { - fprintf(stderr, "warning: different zlib version\n"); + fprintf(stderr, "warning: different zlib version linked: %s\n", zVersion()); } printf("zlib-ng version %s = 0x%08lx, compile flags = 0x%lx\n", From 6581fb0efcdd0ef2429105dc61e3923a16db703d Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Sun, 24 Jul 2022 11:41:07 -0700 Subject: [PATCH 563/798] Have infback() deliver all of the available output up to any error. --- infback.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/infback.c b/infback.c index e57daab18d..a7af88f2e2 100644 --- a/infback.c +++ b/infback.c @@ -477,12 +477,8 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in break; case DONE: - /* inflate stream terminated properly -- write leftover output */ + /* inflate stream terminated properly */ ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } goto inf_leave; case BAD: @@ -494,8 +490,13 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in goto inf_leave; } - /* Return unused input */ + /* Write leftover output and return unused input */ inf_leave: + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left) && (ret == Z_STREAM_END)) { + ret = Z_BUF_ERROR; + } + } strm->next_in = next; strm->avail_in = have; return ret; From 5393c21955013dc5f3724800e39f1a705ac3d289 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Sat, 1 Oct 2022 19:55:29 -0700 Subject: [PATCH 564/798] Fix bug in block type selection when Z_FIXED used. A fixed block could be chosen when a stored block was smaller. Now the smaller of the two is always chosen. --- trees.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trees.c b/trees.c index 111ead01ff..5bb88389ba 100644 --- a/trees.c +++ b/trees.c @@ -670,7 +670,7 @@ void Z_INTERNAL zng_tr_flush_block(deflate_state *s, char *buf, uint32_t stored_ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, s->sym_next / 3)); - if (static_lenb <= opt_lenb) + if (static_lenb <= opt_lenb || s->strategy == Z_FIXED) opt_lenb = static_lenb; } else { @@ -688,7 +688,7 @@ void Z_INTERNAL zng_tr_flush_block(deflate_state *s, char *buf, uint32_t stored_ */ zng_tr_stored_block(s, buf, stored_len, last); - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { + } else if (static_lenb == opt_lenb) { zng_tr_emit_tree(s, STATIC_TREES, last); compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); cmpr_bits_add(s, s->static_len); From 0e49aa38b86efc61670d973265daee0981f72b7d Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Mon, 3 Oct 2022 08:47:03 -0700 Subject: [PATCH 565/798] Add WIN32_LEAN_AND_MEAN for windows.h include. --- zconf.h.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zconf.h.in b/zconf.h.in index 82ee080321..0611fac68b 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -79,6 +79,9 @@ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ #if defined(ZLIB_WINAPI) && defined(_WIN32) +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ From c671129f37fe56666dccd2427f0a280c8a6dc911 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Thu, 6 Oct 2022 01:03:18 -0700 Subject: [PATCH 566/798] Remove -pedantic from configure -w compile options. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 59c4a7e6a7..9cd5702398 100755 --- a/configure +++ b/configure @@ -396,7 +396,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then SFLAGS="${SFLAGS} ${NATIVE_FLAG}" fi if test "$warn" -eq 1; then - CFLAGS="${CFLAGS} -Wextra -Wpedantic" + CFLAGS="${CFLAGS} -Wextra" fi if test $debug -eq 1; then CFLAGS="${CFLAGS} -DZLIB_DEBUG" From 33e671b90d2847f27c237de1236a6686620cf926 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Thu, 6 Oct 2022 12:57:31 -0700 Subject: [PATCH 567/798] Remove redundant check in gz_look(). --- gzread.c.in | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gzread.c.in b/gzread.c.in index c421f9f56f..262517e4fe 100644 --- a/gzread.c.in +++ b/gzread.c.in @@ -145,11 +145,9 @@ static int gz_look(gz_state *state) { the output buffer is larger than the input buffer, which also assures space for gzungetc() */ state->x.next = state->out; - if (strm->avail_in) { - memcpy(state->x.next, strm->next_in, strm->avail_in); - state->x.have = strm->avail_in; - strm->avail_in = 0; - } + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; + strm->avail_in = 0; state->how = COPY; state->direct = 1; return 0; From 4af454bfa7d7cd8df02f0227016b9ade805d1b93 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Thu, 15 Dec 2022 09:07:13 -0800 Subject: [PATCH 568/798] Fix bug in deflateBound() for level 0 and memLevel 9. memLevel 9 would cause deflateBound() to assume the use of fixed blocks, even if the compression level was 0, which forces stored blocks. That could result in a bound less than the size of the compressed data. Now level 0 always uses the stored blocks bound. --- deflate.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/deflate.c b/deflate.c index 554aa7083b..c94e065e64 100644 --- a/deflate.c +++ b/deflate.c @@ -662,8 +662,15 @@ 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 != 15 || HASH_BITS < 15) + s->w_bits != 15 || HASH_BITS < 15) { + if (s->level == 0) { + /* upper bound for stored blocks with length 127 (memLevel == 1) -- + ~4% overhead plus a small constant */ + complen = sourceLen + (sourceLen >> 5) + (sourceLen >> 7) + (sourceLen >> 11) + 7; + } + return complen + wraplen; + } #ifndef NO_QUICK_STRATEGY return sourceLen /* The source size itself */ From e713f2f460a1b7fcf617ae837bc95b68abb3803b Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Mon, 26 Dec 2022 23:36:01 -0800 Subject: [PATCH 569/798] Fix crash when gzsetparams() attempted for transparent write. gzsetparams() now returns a Z_STREAM_ERROR in this case. --- gzwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gzwrite.c b/gzwrite.c index ba716bc20b..08e0ce9aab 100644 --- a/gzwrite.c +++ b/gzwrite.c @@ -460,7 +460,7 @@ int Z_EXPORT PREFIX(gzsetparams)(gzFile file, int level, int strategy) { strm = &(state->strm); /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) + if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct) return Z_STREAM_ERROR; /* if no change is requested, then do nothing */ From d5db5aa985dc4a882e6436f3f9273d09bf5aa89d Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Wed, 14 Dec 2022 15:12:43 +0200 Subject: [PATCH 570/798] Sync with zlib 1.2.13 and declare compatibility. --- CMakeLists.txt | 2 +- README.md | 2 +- deflate.c | 2 +- inftrees.c | 2 +- ...2a18c1281fc-aarch64-unknown-linux-gnu.abi} | 350 +++++++++--------- ...2a18c1281fc-arm-unknown-linux-gnueabi.abi} | 350 +++++++++--------- ...18c1281fc-arm-unknown-linux-gnueabihf.abi} | 350 +++++++++--------- ...2a18c1281fc-powerpc-unknown-linux-gnu.abi} | 350 +++++++++--------- ...18c1281fc-powerpc64-unknown-linux-gnu.abi} | 350 +++++++++--------- ...c1281fc-powerpc64le-unknown-linux-gnu.abi} | 350 +++++++++--------- ...6c2a18c1281fc-x86_64-pc-linux-gnu-m32.abi} | 350 +++++++++--------- ...93806c2a18c1281fc-x86_64-pc-linux-gnu.abi} | 350 +++++++++--------- test/abicheck.sh | 4 +- win32/zlib1.rc | 2 +- zlib.h.in | 8 +- 15 files changed, 1411 insertions(+), 1411 deletions(-) rename test/abi/{zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-aarch64-unknown-linux-gnu.abi => zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-aarch64-unknown-linux-gnu.abi} (92%) rename test/abi/{zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabi.abi => zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-arm-unknown-linux-gnueabi.abi} (92%) rename test/abi/{zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabihf.abi => zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-arm-unknown-linux-gnueabihf.abi} (92%) rename test/abi/{zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc-unknown-linux-gnu.abi => zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc-unknown-linux-gnu.abi} (92%) rename test/abi/{zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64-unknown-linux-gnu.abi => zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc64-unknown-linux-gnu.abi} (92%) rename test/abi/{zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64le-unknown-linux-gnu.abi => zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc64le-unknown-linux-gnu.abi} (92%) rename test/abi/{zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi => zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-x86_64-pc-linux-gnu-m32.abi} (92%) rename test/abi/{zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi => zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-x86_64-pc-linux-gnu.abi} (92%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 059017e16c..1f667e8fe8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,7 +200,7 @@ elseif(MSVC) elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") # Enable warnings in GCC and Clang set(WARNFLAGS -Wall) - set(WARNFLAGS_MAINTAINER -Wextra -Wpedantic) + set(WARNFLAGS_MAINTAINER -Wextra) set(WARNFLAGS_DISABLE) if(WITH_NATIVE_INSTRUCTIONS) if(BASEARCH_PPC_FOUND) diff --git a/README.md b/README.md index 80b921b2c7..a40980a07b 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ with zlib, then zlib-ng will temporarily be used instead by the program, without risking system-wide instability. ``` -LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.12.zlib-ng /usr/bin/program +LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.13.zlib-ng /usr/bin/program ``` ### Cmake diff --git a/deflate.c b/deflate.c index c94e065e64..9d8002b982 100644 --- a/deflate.c +++ b/deflate.c @@ -59,7 +59,7 @@ # undef deflateInit2 #endif -const char PREFIX(deflate_copyright)[] = " deflate 1.2.12 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; +const char PREFIX(deflate_copyright)[] = " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot diff --git a/inftrees.c b/inftrees.c index 7a215bd657..78f6cf174b 100644 --- a/inftrees.c +++ b/inftrees.c @@ -9,7 +9,7 @@ #define MAXBITS 15 -const char PREFIX(inflate_copyright)[] = " inflate 1.2.12 Copyright 1995-2022 Mark Adler "; +const char PREFIX(inflate_copyright)[] = " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-aarch64-unknown-linux-gnu.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-aarch64-unknown-linux-gnu.abi similarity index 92% rename from test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-aarch64-unknown-linux-gnu.abi rename to test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-aarch64-unknown-linux-gnu.abi index e39b64cfb1..c9088b86f5 100644 --- a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-aarch64-unknown-linux-gnu.abi +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-aarch64-unknown-linux-gnu.abi @@ -1,4 +1,4 @@ - + @@ -98,11 +98,11 @@ - - - - - + + + + + @@ -136,7 +136,7 @@ - + @@ -159,50 +159,50 @@ - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + @@ -230,8 +230,8 @@ - - + + @@ -580,92 +580,92 @@ - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + @@ -694,13 +694,13 @@ - + - + @@ -836,7 +836,7 @@ - + @@ -936,40 +936,40 @@ - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + @@ -991,7 +991,7 @@ - + @@ -1098,16 +1098,16 @@ - - - - - - + + + + + + - - + + @@ -1150,80 +1150,80 @@ - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + @@ -1277,8 +1277,8 @@ - - + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabi.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-arm-unknown-linux-gnueabi.abi similarity index 92% rename from test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabi.abi rename to test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-arm-unknown-linux-gnueabi.abi index 839c6ac9a9..48f8fb6bfb 100644 --- a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabi.abi +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-arm-unknown-linux-gnueabi.abi @@ -1,4 +1,4 @@ - + @@ -99,11 +99,11 @@ - - - - - + + + + + @@ -138,7 +138,7 @@ - + @@ -161,50 +161,50 @@ - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + @@ -232,8 +232,8 @@ - - + + @@ -582,92 +582,92 @@ - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + @@ -696,13 +696,13 @@ - + - + @@ -838,7 +838,7 @@ - + @@ -938,40 +938,40 @@ - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + @@ -981,7 +981,7 @@ - + @@ -1088,16 +1088,16 @@ - - - - - - + + + + + + - - + + @@ -1140,80 +1140,80 @@ - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + @@ -1267,8 +1267,8 @@ - - + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabihf.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-arm-unknown-linux-gnueabihf.abi similarity index 92% rename from test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabihf.abi rename to test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-arm-unknown-linux-gnueabihf.abi index fd5f2aded2..cee35ca46f 100644 --- a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-arm-unknown-linux-gnueabihf.abi +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-arm-unknown-linux-gnueabihf.abi @@ -1,4 +1,4 @@ - + @@ -99,11 +99,11 @@ - - - - - + + + + + @@ -138,7 +138,7 @@ - + @@ -161,50 +161,50 @@ - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + @@ -232,8 +232,8 @@ - - + + @@ -582,92 +582,92 @@ - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + @@ -696,13 +696,13 @@ - + - + @@ -838,7 +838,7 @@ - + @@ -938,40 +938,40 @@ - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + @@ -981,7 +981,7 @@ - + @@ -1088,16 +1088,16 @@ - - - - - - + + + + + + - - + + @@ -1140,80 +1140,80 @@ - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + @@ -1267,8 +1267,8 @@ - - + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc-unknown-linux-gnu.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc-unknown-linux-gnu.abi similarity index 92% rename from test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc-unknown-linux-gnu.abi rename to test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc-unknown-linux-gnu.abi index 3bd1f5b169..3d7ca82c18 100644 --- a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc-unknown-linux-gnu.abi +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc-unknown-linux-gnu.abi @@ -1,4 +1,4 @@ - + @@ -98,11 +98,11 @@ - - - - - + + + + + @@ -137,7 +137,7 @@ - + @@ -160,50 +160,50 @@ - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + @@ -231,8 +231,8 @@ - - + + @@ -581,92 +581,92 @@ - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + @@ -695,13 +695,13 @@ - + - + @@ -837,7 +837,7 @@ - + @@ -937,40 +937,40 @@ - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + @@ -992,7 +992,7 @@ - + @@ -1098,16 +1098,16 @@ - - - - - - + + + + + + - - + + @@ -1150,80 +1150,80 @@ - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + @@ -1277,8 +1277,8 @@ - - + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64-unknown-linux-gnu.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc64-unknown-linux-gnu.abi similarity index 92% rename from test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64-unknown-linux-gnu.abi rename to test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc64-unknown-linux-gnu.abi index 161d088f7f..ad037fd6ae 100644 --- a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64-unknown-linux-gnu.abi +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc64-unknown-linux-gnu.abi @@ -1,4 +1,4 @@ - + @@ -97,11 +97,11 @@ - - - - - + + + + + @@ -135,7 +135,7 @@ - + @@ -158,50 +158,50 @@ - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + @@ -229,8 +229,8 @@ - - + + @@ -579,92 +579,92 @@ - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + @@ -693,13 +693,13 @@ - + - + @@ -835,7 +835,7 @@ - + @@ -935,45 +935,45 @@ - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1080,16 +1080,16 @@ - - - - - - + + + + + + - - + + @@ -1132,80 +1132,80 @@ - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + @@ -1259,8 +1259,8 @@ - - + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64le-unknown-linux-gnu.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc64le-unknown-linux-gnu.abi similarity index 92% rename from test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64le-unknown-linux-gnu.abi rename to test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc64le-unknown-linux-gnu.abi index bb67512a8e..5ef350b4de 100644 --- a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-powerpc64le-unknown-linux-gnu.abi +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-powerpc64le-unknown-linux-gnu.abi @@ -1,4 +1,4 @@ - + @@ -97,11 +97,11 @@ - - - - - + + + + + @@ -135,7 +135,7 @@ - + @@ -158,50 +158,50 @@ - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + @@ -229,8 +229,8 @@ - - + + @@ -579,92 +579,92 @@ - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + @@ -693,13 +693,13 @@ - + - + @@ -835,7 +835,7 @@ - + @@ -935,45 +935,45 @@ - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1080,16 +1080,16 @@ - - - - - - + + + + + + - - + + @@ -1132,80 +1132,80 @@ - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + @@ -1259,8 +1259,8 @@ - - + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-x86_64-pc-linux-gnu-m32.abi similarity index 92% rename from test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi rename to test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-x86_64-pc-linux-gnu-m32.abi index 1f0ae6d801..569d084b98 100644 --- a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu-m32.abi +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-x86_64-pc-linux-gnu-m32.abi @@ -1,4 +1,4 @@ - + @@ -98,11 +98,11 @@ - - - - - + + + + + @@ -137,7 +137,7 @@ - + @@ -160,50 +160,50 @@ - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + @@ -231,8 +231,8 @@ - - + + @@ -581,92 +581,92 @@ - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + @@ -695,13 +695,13 @@ - + - + @@ -837,7 +837,7 @@ - + @@ -930,45 +930,45 @@ - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1075,16 +1075,16 @@ - - - - - - + + + + + + - - + + @@ -1127,80 +1127,80 @@ - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + @@ -1254,8 +1254,8 @@ - - + + diff --git a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-x86_64-pc-linux-gnu.abi similarity index 92% rename from test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi rename to test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-x86_64-pc-linux-gnu.abi index bae68adb72..b2a63a4bd1 100644 --- a/test/abi/zlib-ec3df00224d4b396e2ac6586ab5d25f673caa4c2-x86_64-pc-linux-gnu.abi +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-x86_64-pc-linux-gnu.abi @@ -1,4 +1,4 @@ - + @@ -97,11 +97,11 @@ - - - - - + + + + + @@ -135,7 +135,7 @@ - + @@ -158,50 +158,50 @@ - + - + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - - + + + + @@ -229,8 +229,8 @@ - - + + @@ -579,92 +579,92 @@ - - - - - + + + + + - - - - - - - - - + + + + + + + + + - - - - + + + + - - - - + + + + - - + + - - + + - - - + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - + + + + + + - - - + + + - - - + + + - - + + - - - + + + @@ -693,13 +693,13 @@ - + - + @@ -835,7 +835,7 @@ - + @@ -935,40 +935,40 @@ - - - - + + + + - - - - - + + + + + - - + + - - + + - - - + + + - - - - + + + + - - + + @@ -987,7 +987,7 @@ - + @@ -1093,16 +1093,16 @@ - - - - - - + + + + + + - - + + @@ -1145,80 +1145,80 @@ - - - - - + + + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + @@ -1272,8 +1272,8 @@ - - + + diff --git a/test/abicheck.sh b/test/abicheck.sh index a759db78b9..96cb50722d 100755 --- a/test/abicheck.sh +++ b/test/abicheck.sh @@ -67,9 +67,9 @@ done # Choose reference repo and commit if test "$suffix" = "" then - # Reference is zlib 1.2.12 develop due to errors compiling shared library in the 1.2.12 tag. + # Reference is zlib 1.2.13. ABI_GIT_REPO=https://github.com/madler/zlib.git - ABI_GIT_COMMIT=ec3df00224d4b396e2ac6586ab5d25f673caa4c2 + ABI_GIT_COMMIT=04f42ceca40f73e2978b50e93806c2a18c1281fc else # Reference is most recent zlib-ng develop with zlib 1.2.12 compatible api. ABI_GIT_REPO=https://github.com/zlib-ng/zlib-ng.git diff --git a/win32/zlib1.rc b/win32/zlib1.rc index 82e5934c2b..73bc4389c0 100644 --- a/win32/zlib1.rc +++ b/win32/zlib1.rc @@ -22,7 +22,7 @@ BEGIN VALUE "FileDescription", "zlib data compression library\0" VALUE "FileVersion", ZLIB_VERSION "\0" VALUE "InternalName", "zlib1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2022 Jean-loup Gailly & Mark Adler\0" VALUE "OriginalFilename", "zlib1.dll\0" VALUE "ProductName", "zlib\0" VALUE "ProductVersion", ZLIB_VERSION "\0" diff --git a/zlib.h.in b/zlib.h.in index 96f76b2f9a..311cd34e8c 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -1,7 +1,7 @@ #ifndef ZLIB_H_ #define ZLIB_H_ /* zlib.h -- interface of the 'zlib-ng' compression library - Forked from and compatible with zlib 1.2.12 + Forked from and compatible with zlib 1.2.13 Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler @@ -57,11 +57,11 @@ extern "C" { #define ZLIBNG_VER_STATUS 0 /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ -#define ZLIB_VERSION "1.2.12.zlib-ng" -#define ZLIB_VERNUM 0x12cf +#define ZLIB_VERSION "1.2.13.zlib-ng" +#define ZLIB_VERNUM 0x12df #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 12 +#define ZLIB_VER_REVISION 13 #define ZLIB_VER_SUBREVISION 15 /* 15=fork (0xf) */ /* From fecb03a1a17459cafcd50e326b9d7bb967b80b30 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 13 Jan 2023 21:34:32 +0300 Subject: [PATCH 571/798] Avoid `functable` redefinition in functable.c `functable` is already declared by functable.h which is included by functable.c --- functable.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/functable.c b/functable.c index 260d52f2f3..b902c2a318 100644 --- a/functable.c +++ b/functable.c @@ -13,8 +13,6 @@ #include "cpu_features.h" -Z_INTERNAL Z_TLS struct functable_s functable; - /* stub functions */ Z_INTERNAL uint32_t update_hash_stub(deflate_state *const s, uint32_t h, uint32_t val) { // Initialize default From df60007e8e71555b272bf99dc0525aad84186a5c Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 13 Jan 2023 22:27:45 +0300 Subject: [PATCH 572/798] Move initialization of functable to `init_functable` function --- functable.c | 446 +++++++++++++++++++++++++++++----------------------- 1 file changed, 248 insertions(+), 198 deletions(-) diff --git a/functable.c b/functable.c index b902c2a318..bbfbd8e7ad 100644 --- a/functable.c +++ b/functable.c @@ -8,445 +8,495 @@ #include "crc32_braid_p.h" #include "deflate.h" #include "deflate_p.h" - #include "functable.h" - #include "cpu_features.h" -/* stub functions */ -Z_INTERNAL uint32_t update_hash_stub(deflate_state *const s, uint32_t h, uint32_t val) { - // Initialize default +static void init_functable(void) { + uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, uint64_t len); + uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); + uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, uint64_t len); + uint32_t (* crc32_fold_reset) (struct crc32_fold_s *crc); + void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, uint64_t len); + void (* crc32_fold) (struct crc32_fold_s *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); + uint32_t (* crc32_fold_final) (struct crc32_fold_s *crc); + uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); + uint32_t (* chunksize) (void); + uint8_t* (* chunkcopy) (uint8_t *out, uint8_t const *from, unsigned len); + uint8_t* (* chunkunroll) (uint8_t *out, unsigned *dist, unsigned *len); + uint8_t* (* chunkmemset) (uint8_t *out, unsigned dist, unsigned len); + uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); + void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); + uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); + uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); + Pos (* quick_insert_string)(deflate_state *const s, uint32_t str); + void (* slide_hash) (deflate_state *s); + uint32_t (* update_hash) (deflate_state *const s, uint32_t h, uint32_t val); - functable.update_hash = &update_hash_c; cpu_check_features(); + // update_hash_stub: + update_hash = &update_hash_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - functable.update_hash = &update_hash_sse4; + update_hash = &update_hash_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - functable.update_hash = &update_hash_acle; + update_hash = &update_hash_acle; #endif - return functable.update_hash(s, h, val); -} - -Z_INTERNAL void insert_string_stub(deflate_state *const s, uint32_t str, uint32_t count) { - // Initialize default - - functable.insert_string = &insert_string_c; - cpu_check_features(); - + // insert_string_stub: + insert_string = &insert_string_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - functable.insert_string = &insert_string_sse4; + insert_string = &insert_string_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - functable.insert_string = &insert_string_acle; + insert_string = &insert_string_acle; #endif - functable.insert_string(s, str, count); -} - -Z_INTERNAL Pos quick_insert_string_stub(deflate_state *const s, const uint32_t str) { - functable.quick_insert_string = &quick_insert_string_c; - + // quick_insert_string_stub: + quick_insert_string = &quick_insert_string_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - functable.quick_insert_string = &quick_insert_string_sse4; + quick_insert_string = &quick_insert_string_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - functable.quick_insert_string = &quick_insert_string_acle; + quick_insert_string = &quick_insert_string_acle; #endif - return functable.quick_insert_string(s, str); -} - -Z_INTERNAL void slide_hash_stub(deflate_state *s) { - - functable.slide_hash = &slide_hash_c; - cpu_check_features(); - + // slide_hash_stub: + slide_hash = &slide_hash_c; #ifdef X86_SSE2 # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.slide_hash = &slide_hash_sse2; + slide_hash = &slide_hash_sse2; #elif defined(ARM_NEON_SLIDEHASH) # ifndef ARM_NOCHECK_NEON if (arm_cpu_has_neon) # endif - functable.slide_hash = &slide_hash_neon; + slide_hash = &slide_hash_neon; #endif #ifdef X86_AVX2 if (x86_cpu_has_avx2) - functable.slide_hash = &slide_hash_avx2; + slide_hash = &slide_hash_avx2; #endif #ifdef PPC_VMX_SLIDEHASH if (power_cpu_has_altivec) - functable.slide_hash = &slide_hash_vmx; + slide_hash = &slide_hash_vmx; #endif #ifdef POWER8_VSX_SLIDEHASH if (power_cpu_has_arch_2_07) - functable.slide_hash = &slide_hash_power8; + slide_hash = &slide_hash_power8; #endif - functable.slide_hash(s); -} - -Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { - + // longest_match_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.longest_match = &longest_match_unaligned_64; + longest_match = &longest_match_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - functable.longest_match = &longest_match_unaligned_32; + longest_match = &longest_match_unaligned_32; # else - functable.longest_match = &longest_match_unaligned_16; + longest_match = &longest_match_unaligned_16; # endif #else - functable.longest_match = &longest_match_c; + longest_match = &longest_match_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - functable.longest_match = &longest_match_sse2; + longest_match = &longest_match_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - functable.longest_match = &longest_match_avx2; + longest_match = &longest_match_avx2; #endif #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) if (arm_cpu_has_neon) - functable.longest_match = &longest_match_neon; + longest_match = &longest_match_neon; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - functable.longest_match = &longest_match_power9; + longest_match = &longest_match_power9; #endif - return functable.longest_match(s, cur_match); -} - -Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_match) { - + // longest_match_slow_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.longest_match_slow = &longest_match_slow_unaligned_64; + longest_match_slow = &longest_match_slow_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - functable.longest_match_slow = &longest_match_slow_unaligned_32; + longest_match_slow = &longest_match_slow_unaligned_32; # else - functable.longest_match_slow = &longest_match_slow_unaligned_16; + longest_match_slow = &longest_match_slow_unaligned_16; # endif #else - functable.longest_match_slow = &longest_match_slow_c; + longest_match_slow = &longest_match_slow_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - functable.longest_match_slow = &longest_match_slow_sse2; + longest_match_slow = &longest_match_slow_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - functable.longest_match_slow = &longest_match_slow_avx2; + longest_match_slow = &longest_match_slow_avx2; #endif #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) if (arm_cpu_has_neon) - functable.longest_match_slow = &longest_match_slow_neon; + longest_match_slow = &longest_match_slow_neon; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - functable.longest_match_slow = &longest_match_slow_power9; + longest_match_slow = &longest_match_slow_power9; #endif - return functable.longest_match_slow(s, cur_match); -} - -Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const uint8_t *buf, size_t len) { - // Initialize default - functable.adler32 = &adler32_c; - cpu_check_features(); - + // adler32_stub: + adler32 = &adler32_c; #ifdef ARM_NEON_ADLER32 # ifndef ARM_NOCHECK_NEON if (arm_cpu_has_neon) # endif - functable.adler32 = &adler32_neon; + adler32 = &adler32_neon; #endif #ifdef X86_SSSE3_ADLER32 if (x86_cpu_has_ssse3) - functable.adler32 = &adler32_ssse3; + adler32 = &adler32_ssse3; #endif #ifdef X86_AVX2_ADLER32 if (x86_cpu_has_avx2) - functable.adler32 = &adler32_avx2; + adler32 = &adler32_avx2; #endif #ifdef X86_AVX512_ADLER32 if (x86_cpu_has_avx512) - functable.adler32 = &adler32_avx512; + adler32 = &adler32_avx512; #endif #ifdef X86_AVX512VNNI_ADLER32 - if (x86_cpu_has_avx512vnni) { - functable.adler32 = &adler32_avx512_vnni; - } + if (x86_cpu_has_avx512vnni) + adler32 = &adler32_avx512_vnni; #endif #ifdef PPC_VMX_ADLER32 if (power_cpu_has_altivec) - functable.adler32 = &adler32_vmx; + adler32 = &adler32_vmx; #endif #ifdef POWER8_VSX_ADLER32 if (power_cpu_has_arch_2_07) - functable.adler32 = &adler32_power8; + adler32 = &adler32_power8; #endif - return functable.adler32(adler, buf, len); -} - -Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { - functable.adler32_fold_copy = &adler32_fold_copy_c; -#if (defined X86_SSE42_ADLER32) + // adler32_fold_copy_stub: + adler32_fold_copy = &adler32_fold_copy_c; +#ifdef X86_SSE42_ADLER32 if (x86_cpu_has_sse42) - functable.adler32_fold_copy = &adler32_fold_copy_sse42; + adler32_fold_copy = &adler32_fold_copy_sse42; #endif #ifdef X86_AVX2_ADLER32 if (x86_cpu_has_avx2) - functable.adler32_fold_copy = &adler32_fold_copy_avx2; + adler32_fold_copy = &adler32_fold_copy_avx2; #endif #ifdef X86_AVX512_ADLER32 if (x86_cpu_has_avx512) - functable.adler32_fold_copy = &adler32_fold_copy_avx512; + adler32_fold_copy = &adler32_fold_copy_avx512; #endif #ifdef X86_AVX512VNNI_ADLER32 if (x86_cpu_has_avx512vnni) - functable.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; + adler32_fold_copy = &adler32_fold_copy_avx512_vnni; #endif - return functable.adler32_fold_copy(adler, dst, src, len); -} -Z_INTERNAL uint32_t crc32_fold_reset_stub(crc32_fold *crc) { - functable.crc32_fold_reset = &crc32_fold_reset_c; - cpu_check_features(); + // crc32_fold_reset_stub: + crc32_fold_reset = &crc32_fold_reset_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; + crc32_fold_reset = &crc32_fold_pclmulqdq_reset; #endif - return functable.crc32_fold_reset(crc); -} -Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { - functable.crc32_fold_copy = &crc32_fold_copy_c; - cpu_check_features(); + // crc32_fold_copy_stub: + crc32_fold_copy = &crc32_fold_copy_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; + crc32_fold_copy = &crc32_fold_pclmulqdq_copy; #endif - functable.crc32_fold_copy(crc, dst, src, len); -} -Z_INTERNAL void crc32_fold_stub(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { - functable.crc32_fold = &crc32_fold_c; - cpu_check_features(); + // crc32_fold_stub: + crc32_fold = &crc32_fold_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold = &crc32_fold_pclmulqdq; + crc32_fold = &crc32_fold_pclmulqdq; #endif - functable.crc32_fold(crc, src, len, init_crc); -} -Z_INTERNAL uint32_t crc32_fold_final_stub(crc32_fold *crc) { - functable.crc32_fold_final = &crc32_fold_final_c; - cpu_check_features(); + // crc32_fold_final_stub: + crc32_fold_final = &crc32_fold_final_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_final = &crc32_fold_pclmulqdq_final; + crc32_fold_final = &crc32_fold_pclmulqdq_final; #endif - return functable.crc32_fold_final(crc); -} - -Z_INTERNAL uint32_t chunksize_stub(void) { - // Initialize default - functable.chunksize = &chunksize_c; - cpu_check_features(); + //chunksize_stub: + chunksize = &chunksize_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunksize = &chunksize_sse2; + chunksize = &chunksize_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunksize = &chunksize_avx; + chunksize = &chunksize_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunksize = &chunksize_neon; + chunksize = &chunksize_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunksize = &chunksize_power8; + chunksize = &chunksize_power8; #endif - return functable.chunksize(); -} - -Z_INTERNAL uint8_t* chunkcopy_stub(uint8_t *out, uint8_t const *from, unsigned len) { - // Initialize default - functable.chunkcopy = &chunkcopy_c; - + // chunkcopy_stub: + chunkcopy = &chunkcopy_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunkcopy = &chunkcopy_sse2; + chunkcopy = &chunkcopy_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunkcopy = &chunkcopy_avx; + chunkcopy = &chunkcopy_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunkcopy = &chunkcopy_neon; + chunkcopy = &chunkcopy_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunkcopy = &chunkcopy_power8; + chunkcopy = &chunkcopy_power8; #endif - return functable.chunkcopy(out, from, len); -} - -Z_INTERNAL uint8_t* chunkunroll_stub(uint8_t *out, unsigned *dist, unsigned *len) { - // Initialize default - functable.chunkunroll = &chunkunroll_c; - + // chunkunroll_stub: + chunkunroll = &chunkunroll_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunkunroll = &chunkunroll_sse2; + chunkunroll = &chunkunroll_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunkunroll = &chunkunroll_avx; + chunkunroll = &chunkunroll_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunkunroll = &chunkunroll_neon; + chunkunroll = &chunkunroll_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunkunroll = &chunkunroll_power8; + chunkunroll = &chunkunroll_power8; #endif - return functable.chunkunroll(out, dist, len); -} - -Z_INTERNAL uint8_t* chunkmemset_stub(uint8_t *out, unsigned dist, unsigned len) { - // Initialize default - functable.chunkmemset = &chunkmemset_c; - + // chunkmemset_stub: + chunkmemset = &chunkmemset_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunkmemset = &chunkmemset_sse2; + chunkmemset = &chunkmemset_sse2; #endif #if defined(X86_SSE41) && defined(X86_SSE2) if (x86_cpu_has_sse41) - functable.chunkmemset = &chunkmemset_sse41; + chunkmemset = &chunkmemset_sse41; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunkmemset = &chunkmemset_avx; + chunkmemset = &chunkmemset_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunkmemset = &chunkmemset_neon; + chunkmemset = &chunkmemset_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunkmemset = &chunkmemset_power8; + chunkmemset = &chunkmemset_power8; #endif - - return functable.chunkmemset(out, dist, len); -} - -Z_INTERNAL uint8_t* chunkmemset_safe_stub(uint8_t *out, unsigned dist, unsigned len, unsigned left) { - // Initialize default - functable.chunkmemset_safe = &chunkmemset_safe_c; - + // chunkmemset_safe_stub: + chunkmemset_safe = &chunkmemset_safe_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunkmemset_safe = &chunkmemset_safe_sse2; + chunkmemset_safe = &chunkmemset_safe_sse2; #endif #if defined(X86_SSE41) && defined(X86_SSE2) if (x86_cpu_has_sse41) - functable.chunkmemset_safe = &chunkmemset_safe_sse41; + chunkmemset_safe = &chunkmemset_safe_sse41; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunkmemset_safe = &chunkmemset_safe_avx; + chunkmemset_safe = &chunkmemset_safe_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunkmemset_safe = &chunkmemset_safe_neon; + chunkmemset_safe = &chunkmemset_safe_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunkmemset_safe = &chunkmemset_safe_power8; + chunkmemset_safe = &chunkmemset_safe_power8; #endif - return functable.chunkmemset_safe(out, dist, len, left); -} - -Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const uint8_t *buf, size_t len) { - functable.crc32 = &PREFIX(crc32_braid); - cpu_check_features(); + // crc32_stub: + crc32 = &PREFIX(crc32_braid); #ifdef ARM_ACLE_CRC_HASH if (arm_cpu_has_crc32) - functable.crc32 = &crc32_acle; + crc32 = &crc32_acle; #elif defined(POWER8_VSX_CRC32) if (power_cpu_has_arch_2_07) - functable.crc32 = &crc32_power8; + crc32 = &crc32_power8; #elif defined(S390_CRC32_VX) if (PREFIX(s390_cpu_has_vx)) - functable.crc32 = &PREFIX(s390_crc32_vx); + crc32 = &PREFIX(s390_crc32_vx); #elif defined(X86_PCLMULQDQ_CRC) if (x86_cpu_has_pclmulqdq) - functable.crc32 = &crc32_pclmulqdq; + crc32 = &crc32_pclmulqdq; #endif - return functable.crc32(crc, buf, len); -} - -Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { - + // compare256_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.compare256 = &compare256_unaligned_64; + compare256 = &compare256_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - functable.compare256 = &compare256_unaligned_32; + compare256 = &compare256_unaligned_32; # else - functable.compare256 = &compare256_unaligned_16; + compare256 = &compare256_unaligned_16; # endif #else - functable.compare256 = &compare256_c; + compare256 = &compare256_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - functable.compare256 = &compare256_sse2; + compare256 = &compare256_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - functable.compare256 = &compare256_avx2; + compare256 = &compare256_avx2; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - functable.compare256 = &compare256_power9; -#endif + compare256 = &compare256_power9; +#endif + + + functable.adler32 = adler32; + functable.adler32_fold_copy = adler32_fold_copy; + functable.crc32 = crc32; + functable.crc32_fold_reset = crc32_fold_reset; + functable.crc32_fold_copy = crc32_fold_copy; + functable.crc32_fold = crc32_fold; + functable.crc32_fold_final = crc32_fold_final; + functable.compare256 = compare256; + functable.chunksize = chunksize; + functable.chunkcopy = chunkcopy; + functable.chunkunroll = chunkunroll; + functable.chunkmemset = chunkmemset; + functable.chunkmemset_safe = chunkmemset_safe; + functable.insert_string = insert_string; + functable.longest_match = longest_match; + functable.longest_match_slow = longest_match_slow; + functable.quick_insert_string = quick_insert_string; + functable.slide_hash = slide_hash; + functable.update_hash = update_hash; +} + +/* stub functions */ +static uint32_t update_hash_stub(deflate_state* const s, uint32_t h, uint32_t val) { + init_functable(); + return functable.update_hash(s, h, val); +} + +static void insert_string_stub(deflate_state* const s, uint32_t str, uint32_t count) { + init_functable(); + functable.insert_string(s, str, count); +} + +static Pos quick_insert_string_stub(deflate_state* const s, const uint32_t str) { + init_functable(); + return functable.quick_insert_string(s, str); +} + +static void slide_hash_stub(deflate_state* s) { + init_functable(); + functable.slide_hash(s); +} + +static uint32_t longest_match_stub(deflate_state* const s, Pos cur_match) { + init_functable(); + return functable.longest_match(s, cur_match); +} + +static uint32_t longest_match_slow_stub(deflate_state* const s, Pos cur_match) { + init_functable(); + return functable.longest_match_slow(s, cur_match); +} + +static uint32_t adler32_stub(uint32_t adler, const uint8_t* buf, size_t len) { + init_functable(); + return functable.adler32(adler, buf, len); +} + +static uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t* dst, const uint8_t* src, size_t len) { + init_functable(); + return functable.adler32_fold_copy(adler, dst, src, len); +} + +static uint32_t crc32_fold_reset_stub(crc32_fold* crc) { + init_functable(); + return functable.crc32_fold_reset(crc); +} + +static void crc32_fold_copy_stub(crc32_fold* crc, uint8_t* dst, const uint8_t* src, size_t len) { + init_functable(); + functable.crc32_fold_copy(crc, dst, src, len); +} + +static void crc32_fold_stub(crc32_fold* crc, const uint8_t* src, size_t len, uint32_t init_crc) { + init_functable(); + functable.crc32_fold(crc, src, len, init_crc); +} + +static uint32_t crc32_fold_final_stub(crc32_fold* crc) { + init_functable(); + return functable.crc32_fold_final(crc); +} + +static uint32_t chunksize_stub(void) { + init_functable(); + return functable.chunksize(); +} + +static uint8_t* chunkcopy_stub(uint8_t* out, uint8_t const* from, unsigned len) { + init_functable(); + return functable.chunkcopy(out, from, len); +} + +static uint8_t* chunkunroll_stub(uint8_t* out, unsigned* dist, unsigned* len) { + init_functable(); + return functable.chunkunroll(out, dist, len); +} + +static uint8_t* chunkmemset_stub(uint8_t* out, unsigned dist, unsigned len) { + init_functable(); + return functable.chunkmemset(out, dist, len); +} + +static uint8_t* chunkmemset_safe_stub(uint8_t* out, unsigned dist, unsigned len, unsigned left) { + init_functable(); + return functable.chunkmemset_safe(out, dist, len, left); +} + +static uint32_t crc32_stub(uint32_t crc, const uint8_t* buf, size_t len) { + init_functable(); + return functable.crc32(crc, buf, len); +} +static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) { + init_functable(); return functable.compare256(src0, src1); } From 709a710f6fb98426bb6f7dea6b505f0fcab3eb99 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sun, 22 Jan 2023 13:50:04 +0300 Subject: [PATCH 573/798] Use local functable variable instead of standalone function pointers --- functable.c | 248 ++++++++++++++++++++++++---------------------------- 1 file changed, 116 insertions(+), 132 deletions(-) diff --git a/functable.c b/functable.c index bbfbd8e7ad..28d7d214a5 100644 --- a/functable.c +++ b/functable.c @@ -12,396 +12,380 @@ #include "cpu_features.h" static void init_functable(void) { - uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, uint64_t len); - uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, uint64_t len); - uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, uint64_t len); - uint32_t (* crc32_fold_reset) (struct crc32_fold_s *crc); - void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, uint64_t len); - void (* crc32_fold) (struct crc32_fold_s *crc, const uint8_t *src, uint64_t len, uint32_t init_crc); - uint32_t (* crc32_fold_final) (struct crc32_fold_s *crc); - uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); - uint32_t (* chunksize) (void); - uint8_t* (* chunkcopy) (uint8_t *out, uint8_t const *from, unsigned len); - uint8_t* (* chunkunroll) (uint8_t *out, unsigned *dist, unsigned *len); - uint8_t* (* chunkmemset) (uint8_t *out, unsigned dist, unsigned len); - uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); - void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); - uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); - uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); - Pos (* quick_insert_string)(deflate_state *const s, uint32_t str); - void (* slide_hash) (deflate_state *s); - uint32_t (* update_hash) (deflate_state *const s, uint32_t h, uint32_t val); + struct functable_s* functable_ptr = &functable; + struct functable_s functable; + Assert(functable_ptr != &functable, + "functable_ptr has to point to global functable"); cpu_check_features(); // update_hash_stub: - update_hash = &update_hash_c; + functable.update_hash = &update_hash_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - update_hash = &update_hash_sse4; + functable.update_hash = &update_hash_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - update_hash = &update_hash_acle; + functable.update_hash = &update_hash_acle; #endif // insert_string_stub: - insert_string = &insert_string_c; + functable.insert_string = &insert_string_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - insert_string = &insert_string_sse4; + functable.insert_string = &insert_string_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - insert_string = &insert_string_acle; + functable.insert_string = &insert_string_acle; #endif // quick_insert_string_stub: - quick_insert_string = &quick_insert_string_c; + functable.quick_insert_string = &quick_insert_string_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - quick_insert_string = &quick_insert_string_sse4; + functable.quick_insert_string = &quick_insert_string_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - quick_insert_string = &quick_insert_string_acle; + functable.quick_insert_string = &quick_insert_string_acle; #endif // slide_hash_stub: - slide_hash = &slide_hash_c; + functable.slide_hash = &slide_hash_c; #ifdef X86_SSE2 # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - slide_hash = &slide_hash_sse2; + functable.slide_hash = &slide_hash_sse2; #elif defined(ARM_NEON_SLIDEHASH) # ifndef ARM_NOCHECK_NEON if (arm_cpu_has_neon) # endif - slide_hash = &slide_hash_neon; + functable.slide_hash = &slide_hash_neon; #endif #ifdef X86_AVX2 if (x86_cpu_has_avx2) - slide_hash = &slide_hash_avx2; + functable.slide_hash = &slide_hash_avx2; #endif #ifdef PPC_VMX_SLIDEHASH if (power_cpu_has_altivec) - slide_hash = &slide_hash_vmx; + functable.slide_hash = &slide_hash_vmx; #endif #ifdef POWER8_VSX_SLIDEHASH if (power_cpu_has_arch_2_07) - slide_hash = &slide_hash_power8; + functable.slide_hash = &slide_hash_power8; #endif // longest_match_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - longest_match = &longest_match_unaligned_64; + functable.longest_match = &longest_match_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - longest_match = &longest_match_unaligned_32; + functable.longest_match = &longest_match_unaligned_32; # else - longest_match = &longest_match_unaligned_16; + functable.longest_match = &longest_match_unaligned_16; # endif #else - longest_match = &longest_match_c; + functable.longest_match = &longest_match_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - longest_match = &longest_match_sse2; + functable.longest_match = &longest_match_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - longest_match = &longest_match_avx2; + functable.longest_match = &longest_match_avx2; #endif #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) if (arm_cpu_has_neon) - longest_match = &longest_match_neon; + functable.longest_match = &longest_match_neon; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - longest_match = &longest_match_power9; + functable.longest_match = &longest_match_power9; #endif // longest_match_slow_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - longest_match_slow = &longest_match_slow_unaligned_64; + functable.longest_match_slow = &longest_match_slow_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - longest_match_slow = &longest_match_slow_unaligned_32; + functable.longest_match_slow = &longest_match_slow_unaligned_32; # else - longest_match_slow = &longest_match_slow_unaligned_16; + functable.longest_match_slow = &longest_match_slow_unaligned_16; # endif #else - longest_match_slow = &longest_match_slow_c; + functable.longest_match_slow = &longest_match_slow_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - longest_match_slow = &longest_match_slow_sse2; + functable.longest_match_slow = &longest_match_slow_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - longest_match_slow = &longest_match_slow_avx2; + functable.longest_match_slow = &longest_match_slow_avx2; #endif #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) if (arm_cpu_has_neon) - longest_match_slow = &longest_match_slow_neon; + functable.longest_match_slow = &longest_match_slow_neon; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - longest_match_slow = &longest_match_slow_power9; + functable.longest_match_slow = &longest_match_slow_power9; #endif // adler32_stub: - adler32 = &adler32_c; + functable.adler32 = &adler32_c; #ifdef ARM_NEON_ADLER32 # ifndef ARM_NOCHECK_NEON if (arm_cpu_has_neon) # endif - adler32 = &adler32_neon; + functable.adler32 = &adler32_neon; #endif #ifdef X86_SSSE3_ADLER32 if (x86_cpu_has_ssse3) - adler32 = &adler32_ssse3; + functable.adler32 = &adler32_ssse3; #endif #ifdef X86_AVX2_ADLER32 if (x86_cpu_has_avx2) - adler32 = &adler32_avx2; + functable.adler32 = &adler32_avx2; #endif #ifdef X86_AVX512_ADLER32 if (x86_cpu_has_avx512) - adler32 = &adler32_avx512; + functable.adler32 = &adler32_avx512; #endif #ifdef X86_AVX512VNNI_ADLER32 if (x86_cpu_has_avx512vnni) - adler32 = &adler32_avx512_vnni; + functable.adler32 = &adler32_avx512_vnni; #endif #ifdef PPC_VMX_ADLER32 if (power_cpu_has_altivec) - adler32 = &adler32_vmx; + functable.adler32 = &adler32_vmx; #endif #ifdef POWER8_VSX_ADLER32 if (power_cpu_has_arch_2_07) - adler32 = &adler32_power8; + functable.adler32 = &adler32_power8; #endif // adler32_fold_copy_stub: - adler32_fold_copy = &adler32_fold_copy_c; + functable.adler32_fold_copy = &adler32_fold_copy_c; #ifdef X86_SSE42_ADLER32 if (x86_cpu_has_sse42) - adler32_fold_copy = &adler32_fold_copy_sse42; + functable.adler32_fold_copy = &adler32_fold_copy_sse42; #endif #ifdef X86_AVX2_ADLER32 if (x86_cpu_has_avx2) - adler32_fold_copy = &adler32_fold_copy_avx2; + functable.adler32_fold_copy = &adler32_fold_copy_avx2; #endif #ifdef X86_AVX512_ADLER32 if (x86_cpu_has_avx512) - adler32_fold_copy = &adler32_fold_copy_avx512; + functable.adler32_fold_copy = &adler32_fold_copy_avx512; #endif #ifdef X86_AVX512VNNI_ADLER32 if (x86_cpu_has_avx512vnni) - adler32_fold_copy = &adler32_fold_copy_avx512_vnni; + functable.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; #endif // crc32_fold_reset_stub: - crc32_fold_reset = &crc32_fold_reset_c; + functable.crc32_fold_reset = &crc32_fold_reset_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - crc32_fold_reset = &crc32_fold_pclmulqdq_reset; + functable.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; #endif // crc32_fold_copy_stub: - crc32_fold_copy = &crc32_fold_copy_c; + functable.crc32_fold_copy = &crc32_fold_copy_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - crc32_fold_copy = &crc32_fold_pclmulqdq_copy; + functable.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; #endif // crc32_fold_stub: - crc32_fold = &crc32_fold_c; + functable.crc32_fold = &crc32_fold_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - crc32_fold = &crc32_fold_pclmulqdq; + functable.crc32_fold = &crc32_fold_pclmulqdq; #endif // crc32_fold_final_stub: - crc32_fold_final = &crc32_fold_final_c; + functable.crc32_fold_final = &crc32_fold_final_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - crc32_fold_final = &crc32_fold_pclmulqdq_final; + functable.crc32_fold_final = &crc32_fold_pclmulqdq_final; #endif //chunksize_stub: - chunksize = &chunksize_c; + functable.chunksize = &chunksize_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - chunksize = &chunksize_sse2; + functable.chunksize = &chunksize_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - chunksize = &chunksize_avx; + functable.chunksize = &chunksize_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - chunksize = &chunksize_neon; + functable.chunksize = &chunksize_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - chunksize = &chunksize_power8; + functable.chunksize = &chunksize_power8; #endif // chunkcopy_stub: - chunkcopy = &chunkcopy_c; + functable.chunkcopy = &chunkcopy_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - chunkcopy = &chunkcopy_sse2; + functable.chunkcopy = &chunkcopy_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - chunkcopy = &chunkcopy_avx; + functable.chunkcopy = &chunkcopy_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - chunkcopy = &chunkcopy_neon; + functable.chunkcopy = &chunkcopy_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - chunkcopy = &chunkcopy_power8; + functable.chunkcopy = &chunkcopy_power8; #endif // chunkunroll_stub: - chunkunroll = &chunkunroll_c; + functable.chunkunroll = &chunkunroll_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - chunkunroll = &chunkunroll_sse2; + functable.chunkunroll = &chunkunroll_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - chunkunroll = &chunkunroll_avx; + functable.chunkunroll = &chunkunroll_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - chunkunroll = &chunkunroll_neon; + functable.chunkunroll = &chunkunroll_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - chunkunroll = &chunkunroll_power8; + functable.chunkunroll = &chunkunroll_power8; #endif // chunkmemset_stub: - chunkmemset = &chunkmemset_c; + functable.chunkmemset = &chunkmemset_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - chunkmemset = &chunkmemset_sse2; + functable.chunkmemset = &chunkmemset_sse2; #endif #if defined(X86_SSE41) && defined(X86_SSE2) if (x86_cpu_has_sse41) - chunkmemset = &chunkmemset_sse41; + functable.chunkmemset = &chunkmemset_sse41; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - chunkmemset = &chunkmemset_avx; + functable.chunkmemset = &chunkmemset_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - chunkmemset = &chunkmemset_neon; + functable.chunkmemset = &chunkmemset_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - chunkmemset = &chunkmemset_power8; + functable.chunkmemset = &chunkmemset_power8; #endif // chunkmemset_safe_stub: - chunkmemset_safe = &chunkmemset_safe_c; + functable.chunkmemset_safe = &chunkmemset_safe_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - chunkmemset_safe = &chunkmemset_safe_sse2; + functable.chunkmemset_safe = &chunkmemset_safe_sse2; #endif #if defined(X86_SSE41) && defined(X86_SSE2) if (x86_cpu_has_sse41) - chunkmemset_safe = &chunkmemset_safe_sse41; + functable.chunkmemset_safe = &chunkmemset_safe_sse41; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - chunkmemset_safe = &chunkmemset_safe_avx; + functable.chunkmemset_safe = &chunkmemset_safe_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - chunkmemset_safe = &chunkmemset_safe_neon; + functable.chunkmemset_safe = &chunkmemset_safe_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - chunkmemset_safe = &chunkmemset_safe_power8; + functable.chunkmemset_safe = &chunkmemset_safe_power8; #endif // crc32_stub: - crc32 = &PREFIX(crc32_braid); + functable.crc32 = &PREFIX(crc32_braid); #ifdef ARM_ACLE_CRC_HASH if (arm_cpu_has_crc32) - crc32 = &crc32_acle; + functable.crc32 = &crc32_acle; #elif defined(POWER8_VSX_CRC32) if (power_cpu_has_arch_2_07) - crc32 = &crc32_power8; + functable.crc32 = &crc32_power8; #elif defined(S390_CRC32_VX) if (PREFIX(s390_cpu_has_vx)) - crc32 = &PREFIX(s390_crc32_vx); + functable.crc32 = &PREFIX(s390_crc32_vx); #elif defined(X86_PCLMULQDQ_CRC) if (x86_cpu_has_pclmulqdq) - crc32 = &crc32_pclmulqdq; + functable.crc32 = &crc32_pclmulqdq; #endif // compare256_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - compare256 = &compare256_unaligned_64; + functable.compare256 = &compare256_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - compare256 = &compare256_unaligned_32; + functable.compare256 = &compare256_unaligned_32; # else - compare256 = &compare256_unaligned_16; + functable.compare256 = &compare256_unaligned_16; # endif #else - compare256 = &compare256_c; + functable.compare256 = &compare256_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - compare256 = &compare256_sse2; + functable.compare256 = &compare256_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - compare256 = &compare256_avx2; + functable.compare256 = &compare256_avx2; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - compare256 = &compare256_power9; -#endif - - - functable.adler32 = adler32; - functable.adler32_fold_copy = adler32_fold_copy; - functable.crc32 = crc32; - functable.crc32_fold_reset = crc32_fold_reset; - functable.crc32_fold_copy = crc32_fold_copy; - functable.crc32_fold = crc32_fold; - functable.crc32_fold_final = crc32_fold_final; - functable.compare256 = compare256; - functable.chunksize = chunksize; - functable.chunkcopy = chunkcopy; - functable.chunkunroll = chunkunroll; - functable.chunkmemset = chunkmemset; - functable.chunkmemset_safe = chunkmemset_safe; - functable.insert_string = insert_string; - functable.longest_match = longest_match; - functable.longest_match_slow = longest_match_slow; - functable.quick_insert_string = quick_insert_string; - functable.slide_hash = slide_hash; - functable.update_hash = update_hash; + functable.compare256 = &compare256_power9; +#endif + + functable_ptr->adler32 = functable.adler32; + functable_ptr->adler32_fold_copy = functable.adler32_fold_copy; + functable_ptr->crc32 = functable.crc32; + functable_ptr->crc32_fold_reset = functable.crc32_fold_reset; + functable_ptr->crc32_fold_copy = functable.crc32_fold_copy; + functable_ptr->crc32_fold = functable.crc32_fold; + functable_ptr->crc32_fold_final = functable.crc32_fold_final; + functable_ptr->compare256 = functable.compare256; + functable_ptr->chunksize = functable.chunksize; + functable_ptr->chunkcopy = functable.chunkcopy; + functable_ptr->chunkunroll = functable.chunkunroll; + functable_ptr->chunkmemset = functable.chunkmemset; + functable_ptr->chunkmemset_safe = functable.chunkmemset_safe; + functable_ptr->insert_string = functable.insert_string; + functable_ptr->longest_match = functable.longest_match; + functable_ptr->longest_match_slow = functable.longest_match_slow; + functable_ptr->quick_insert_string = functable.quick_insert_string; + functable_ptr->slide_hash = functable.slide_hash; + functable_ptr->update_hash = functable.update_hash; } /* stub functions */ From d144fc06bfa575ddfa8143cedd0873f36a2c7568 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Sun, 22 Jan 2023 14:27:16 +0300 Subject: [PATCH 574/798] Rename local `functable` variable to `ft` --- functable.c | 230 ++++++++++++++++++++++++++-------------------------- 1 file changed, 114 insertions(+), 116 deletions(-) diff --git a/functable.c b/functable.c index 28d7d214a5..35474878d5 100644 --- a/functable.c +++ b/functable.c @@ -12,380 +12,378 @@ #include "cpu_features.h" static void init_functable(void) { - struct functable_s* functable_ptr = &functable; - struct functable_s functable; - Assert(functable_ptr != &functable, - "functable_ptr has to point to global functable"); + struct functable_s ft; cpu_check_features(); // update_hash_stub: - functable.update_hash = &update_hash_c; + ft.update_hash = &update_hash_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - functable.update_hash = &update_hash_sse4; + ft.update_hash = &update_hash_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - functable.update_hash = &update_hash_acle; + ft.update_hash = &update_hash_acle; #endif // insert_string_stub: - functable.insert_string = &insert_string_c; + ft.insert_string = &insert_string_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - functable.insert_string = &insert_string_sse4; + ft.insert_string = &insert_string_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - functable.insert_string = &insert_string_acle; + ft.insert_string = &insert_string_acle; #endif // quick_insert_string_stub: - functable.quick_insert_string = &quick_insert_string_c; + ft.quick_insert_string = &quick_insert_string_c; #ifdef X86_SSE42_CRC_HASH if (x86_cpu_has_sse42) - functable.quick_insert_string = &quick_insert_string_sse4; + ft.quick_insert_string = &quick_insert_string_sse4; #elif defined(ARM_ACLE_CRC_HASH) if (arm_cpu_has_crc32) - functable.quick_insert_string = &quick_insert_string_acle; + ft.quick_insert_string = &quick_insert_string_acle; #endif // slide_hash_stub: - functable.slide_hash = &slide_hash_c; + ft.slide_hash = &slide_hash_c; #ifdef X86_SSE2 # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.slide_hash = &slide_hash_sse2; + ft.slide_hash = &slide_hash_sse2; #elif defined(ARM_NEON_SLIDEHASH) # ifndef ARM_NOCHECK_NEON if (arm_cpu_has_neon) # endif - functable.slide_hash = &slide_hash_neon; + ft.slide_hash = &slide_hash_neon; #endif #ifdef X86_AVX2 if (x86_cpu_has_avx2) - functable.slide_hash = &slide_hash_avx2; + ft.slide_hash = &slide_hash_avx2; #endif #ifdef PPC_VMX_SLIDEHASH if (power_cpu_has_altivec) - functable.slide_hash = &slide_hash_vmx; + ft.slide_hash = &slide_hash_vmx; #endif #ifdef POWER8_VSX_SLIDEHASH if (power_cpu_has_arch_2_07) - functable.slide_hash = &slide_hash_power8; + ft.slide_hash = &slide_hash_power8; #endif // longest_match_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.longest_match = &longest_match_unaligned_64; + ft.longest_match = &longest_match_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - functable.longest_match = &longest_match_unaligned_32; + ft.longest_match = &longest_match_unaligned_32; # else - functable.longest_match = &longest_match_unaligned_16; + ft.longest_match = &longest_match_unaligned_16; # endif #else - functable.longest_match = &longest_match_c; + ft.longest_match = &longest_match_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - functable.longest_match = &longest_match_sse2; + ft.longest_match = &longest_match_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - functable.longest_match = &longest_match_avx2; + ft.longest_match = &longest_match_avx2; #endif #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) if (arm_cpu_has_neon) - functable.longest_match = &longest_match_neon; + ft.longest_match = &longest_match_neon; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - functable.longest_match = &longest_match_power9; + ft.longest_match = &longest_match_power9; #endif // longest_match_slow_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.longest_match_slow = &longest_match_slow_unaligned_64; + ft.longest_match_slow = &longest_match_slow_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - functable.longest_match_slow = &longest_match_slow_unaligned_32; + ft.longest_match_slow = &longest_match_slow_unaligned_32; # else - functable.longest_match_slow = &longest_match_slow_unaligned_16; + ft.longest_match_slow = &longest_match_slow_unaligned_16; # endif #else - functable.longest_match_slow = &longest_match_slow_c; + ft.longest_match_slow = &longest_match_slow_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - functable.longest_match_slow = &longest_match_slow_sse2; + ft.longest_match_slow = &longest_match_slow_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - functable.longest_match_slow = &longest_match_slow_avx2; + ft.longest_match_slow = &longest_match_slow_avx2; #endif #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) if (arm_cpu_has_neon) - functable.longest_match_slow = &longest_match_slow_neon; + ft.longest_match_slow = &longest_match_slow_neon; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - functable.longest_match_slow = &longest_match_slow_power9; + ft.longest_match_slow = &longest_match_slow_power9; #endif // adler32_stub: - functable.adler32 = &adler32_c; + ft.adler32 = &adler32_c; #ifdef ARM_NEON_ADLER32 # ifndef ARM_NOCHECK_NEON if (arm_cpu_has_neon) # endif - functable.adler32 = &adler32_neon; + ft.adler32 = &adler32_neon; #endif #ifdef X86_SSSE3_ADLER32 if (x86_cpu_has_ssse3) - functable.adler32 = &adler32_ssse3; + ft.adler32 = &adler32_ssse3; #endif #ifdef X86_AVX2_ADLER32 if (x86_cpu_has_avx2) - functable.adler32 = &adler32_avx2; + ft.adler32 = &adler32_avx2; #endif #ifdef X86_AVX512_ADLER32 if (x86_cpu_has_avx512) - functable.adler32 = &adler32_avx512; + ft.adler32 = &adler32_avx512; #endif #ifdef X86_AVX512VNNI_ADLER32 if (x86_cpu_has_avx512vnni) - functable.adler32 = &adler32_avx512_vnni; + ft.adler32 = &adler32_avx512_vnni; #endif #ifdef PPC_VMX_ADLER32 if (power_cpu_has_altivec) - functable.adler32 = &adler32_vmx; + ft.adler32 = &adler32_vmx; #endif #ifdef POWER8_VSX_ADLER32 if (power_cpu_has_arch_2_07) - functable.adler32 = &adler32_power8; + ft.adler32 = &adler32_power8; #endif // adler32_fold_copy_stub: - functable.adler32_fold_copy = &adler32_fold_copy_c; + ft.adler32_fold_copy = &adler32_fold_copy_c; #ifdef X86_SSE42_ADLER32 if (x86_cpu_has_sse42) - functable.adler32_fold_copy = &adler32_fold_copy_sse42; + ft.adler32_fold_copy = &adler32_fold_copy_sse42; #endif #ifdef X86_AVX2_ADLER32 if (x86_cpu_has_avx2) - functable.adler32_fold_copy = &adler32_fold_copy_avx2; + ft.adler32_fold_copy = &adler32_fold_copy_avx2; #endif #ifdef X86_AVX512_ADLER32 if (x86_cpu_has_avx512) - functable.adler32_fold_copy = &adler32_fold_copy_avx512; + ft.adler32_fold_copy = &adler32_fold_copy_avx512; #endif #ifdef X86_AVX512VNNI_ADLER32 if (x86_cpu_has_avx512vnni) - functable.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; + ft.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; #endif // crc32_fold_reset_stub: - functable.crc32_fold_reset = &crc32_fold_reset_c; + ft.crc32_fold_reset = &crc32_fold_reset_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; + ft.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; #endif // crc32_fold_copy_stub: - functable.crc32_fold_copy = &crc32_fold_copy_c; + ft.crc32_fold_copy = &crc32_fold_copy_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; + ft.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; #endif // crc32_fold_stub: - functable.crc32_fold = &crc32_fold_c; + ft.crc32_fold = &crc32_fold_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold = &crc32_fold_pclmulqdq; + ft.crc32_fold = &crc32_fold_pclmulqdq; #endif // crc32_fold_final_stub: - functable.crc32_fold_final = &crc32_fold_final_c; + ft.crc32_fold_final = &crc32_fold_final_c; #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_final = &crc32_fold_pclmulqdq_final; + ft.crc32_fold_final = &crc32_fold_pclmulqdq_final; #endif //chunksize_stub: - functable.chunksize = &chunksize_c; + ft.chunksize = &chunksize_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunksize = &chunksize_sse2; + ft.chunksize = &chunksize_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunksize = &chunksize_avx; + ft.chunksize = &chunksize_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunksize = &chunksize_neon; + ft.chunksize = &chunksize_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunksize = &chunksize_power8; + ft.chunksize = &chunksize_power8; #endif // chunkcopy_stub: - functable.chunkcopy = &chunkcopy_c; + ft.chunkcopy = &chunkcopy_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunkcopy = &chunkcopy_sse2; + ft.chunkcopy = &chunkcopy_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunkcopy = &chunkcopy_avx; + ft.chunkcopy = &chunkcopy_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunkcopy = &chunkcopy_neon; + ft.chunkcopy = &chunkcopy_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunkcopy = &chunkcopy_power8; + ft.chunkcopy = &chunkcopy_power8; #endif // chunkunroll_stub: - functable.chunkunroll = &chunkunroll_c; + ft.chunkunroll = &chunkunroll_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunkunroll = &chunkunroll_sse2; + ft.chunkunroll = &chunkunroll_sse2; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunkunroll = &chunkunroll_avx; + ft.chunkunroll = &chunkunroll_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunkunroll = &chunkunroll_neon; + ft.chunkunroll = &chunkunroll_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunkunroll = &chunkunroll_power8; + ft.chunkunroll = &chunkunroll_power8; #endif // chunkmemset_stub: - functable.chunkmemset = &chunkmemset_c; + ft.chunkmemset = &chunkmemset_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunkmemset = &chunkmemset_sse2; + ft.chunkmemset = &chunkmemset_sse2; #endif #if defined(X86_SSE41) && defined(X86_SSE2) if (x86_cpu_has_sse41) - functable.chunkmemset = &chunkmemset_sse41; + ft.chunkmemset = &chunkmemset_sse41; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunkmemset = &chunkmemset_avx; + ft.chunkmemset = &chunkmemset_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunkmemset = &chunkmemset_neon; + ft.chunkmemset = &chunkmemset_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunkmemset = &chunkmemset_power8; + ft.chunkmemset = &chunkmemset_power8; #endif // chunkmemset_safe_stub: - functable.chunkmemset_safe = &chunkmemset_safe_c; + ft.chunkmemset_safe = &chunkmemset_safe_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - functable.chunkmemset_safe = &chunkmemset_safe_sse2; + ft.chunkmemset_safe = &chunkmemset_safe_sse2; #endif #if defined(X86_SSE41) && defined(X86_SSE2) if (x86_cpu_has_sse41) - functable.chunkmemset_safe = &chunkmemset_safe_sse41; + ft.chunkmemset_safe = &chunkmemset_safe_sse41; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - functable.chunkmemset_safe = &chunkmemset_safe_avx; + ft.chunkmemset_safe = &chunkmemset_safe_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - functable.chunkmemset_safe = &chunkmemset_safe_neon; + ft.chunkmemset_safe = &chunkmemset_safe_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - functable.chunkmemset_safe = &chunkmemset_safe_power8; + ft.chunkmemset_safe = &chunkmemset_safe_power8; #endif // crc32_stub: - functable.crc32 = &PREFIX(crc32_braid); + ft.crc32 = &PREFIX(crc32_braid); #ifdef ARM_ACLE_CRC_HASH if (arm_cpu_has_crc32) - functable.crc32 = &crc32_acle; + ft.crc32 = &crc32_acle; #elif defined(POWER8_VSX_CRC32) if (power_cpu_has_arch_2_07) - functable.crc32 = &crc32_power8; + ft.crc32 = &crc32_power8; #elif defined(S390_CRC32_VX) if (PREFIX(s390_cpu_has_vx)) - functable.crc32 = &PREFIX(s390_crc32_vx); + ft.crc32 = &PREFIX(s390_crc32_vx); #elif defined(X86_PCLMULQDQ_CRC) if (x86_cpu_has_pclmulqdq) - functable.crc32 = &crc32_pclmulqdq; + ft.crc32 = &crc32_pclmulqdq; #endif // compare256_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.compare256 = &compare256_unaligned_64; + ft.compare256 = &compare256_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - functable.compare256 = &compare256_unaligned_32; + ft.compare256 = &compare256_unaligned_32; # else - functable.compare256 = &compare256_unaligned_16; + ft.compare256 = &compare256_unaligned_16; # endif #else - functable.compare256 = &compare256_c; + ft.compare256 = &compare256_c; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - functable.compare256 = &compare256_sse2; + ft.compare256 = &compare256_sse2; #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - functable.compare256 = &compare256_avx2; + ft.compare256 = &compare256_avx2; #endif #ifdef POWER9 if (power_cpu_has_arch_3_00) - functable.compare256 = &compare256_power9; -#endif - - functable_ptr->adler32 = functable.adler32; - functable_ptr->adler32_fold_copy = functable.adler32_fold_copy; - functable_ptr->crc32 = functable.crc32; - functable_ptr->crc32_fold_reset = functable.crc32_fold_reset; - functable_ptr->crc32_fold_copy = functable.crc32_fold_copy; - functable_ptr->crc32_fold = functable.crc32_fold; - functable_ptr->crc32_fold_final = functable.crc32_fold_final; - functable_ptr->compare256 = functable.compare256; - functable_ptr->chunksize = functable.chunksize; - functable_ptr->chunkcopy = functable.chunkcopy; - functable_ptr->chunkunroll = functable.chunkunroll; - functable_ptr->chunkmemset = functable.chunkmemset; - functable_ptr->chunkmemset_safe = functable.chunkmemset_safe; - functable_ptr->insert_string = functable.insert_string; - functable_ptr->longest_match = functable.longest_match; - functable_ptr->longest_match_slow = functable.longest_match_slow; - functable_ptr->quick_insert_string = functable.quick_insert_string; - functable_ptr->slide_hash = functable.slide_hash; - functable_ptr->update_hash = functable.update_hash; + ft.compare256 = &compare256_power9; +#endif + + // Assign function pointers individually for atomic operation + functable.adler32 = ft.adler32; + functable.adler32_fold_copy = ft.adler32_fold_copy; + functable.crc32 = ft.crc32; + functable.crc32_fold_reset = ft.crc32_fold_reset; + functable.crc32_fold_copy = ft.crc32_fold_copy; + functable.crc32_fold = ft.crc32_fold; + functable.crc32_fold_final = ft.crc32_fold_final; + functable.compare256 = ft.compare256; + functable.chunksize = ft.chunksize; + functable.chunkcopy = ft.chunkcopy; + functable.chunkunroll = ft.chunkunroll; + functable.chunkmemset = ft.chunkmemset; + functable.chunkmemset_safe = ft.chunkmemset_safe; + functable.insert_string = ft.insert_string; + functable.longest_match = ft.longest_match; + functable.longest_match_slow = ft.longest_match_slow; + functable.quick_insert_string = ft.quick_insert_string; + functable.slide_hash = ft.slide_hash; + functable.update_hash = ft.update_hash; } /* stub functions */ From 941ce547cc5e17d01bba861d3edc1f6b27e42a43 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 4 Feb 2023 01:06:47 +0500 Subject: [PATCH 575/798] Pin Google Benchmark to v1.7.1 to fix the upstream issue https://github.com/google/benchmark/issues/1454. Signed-off-by: Vladislav Shchapov --- test/benchmarks/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index cfcb360b5c..ebc6acb78a 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -18,7 +18,7 @@ if(NOT benchmark_FOUND) set(GBENCHMARK_REPOSITORY https://github.com/google/benchmark.git) endif() if(NOT DEFINED GBENCHMARK_TAG) - set(GBENCHMARK_TAG v1.7.0) + set(GBENCHMARK_TAG v1.7.1) endif() FetchContent_Declare(benchmark From aa1109bb2ee79680b0ac966b1de8724ba5083093 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 28 Aug 2022 20:27:37 -0700 Subject: [PATCH 576/798] Use arch-specific versions of inflate_fast. This should reduce the cost of indirection that occurs when calling functable chunk copying functions inside inflate_fast. It should also allow the compiler to optimize the inflate fast path for the specific architecture. --- CMakeLists.txt | 3 +-- Makefile.in | 2 -- arch/arm/chunkset_neon.c | 4 ++++ arch/power/chunkset_power8.c | 4 ++++ arch/x86/chunkset_avx.c | 4 ++++ arch/x86/chunkset_sse2.c | 4 ++++ arch/x86/chunkset_sse41.c | 4 ++++ chunkset.c | 4 ++++ cpu_features.h | 18 ++++++++++++++++++ functable.c | 30 ++++++++++++++++++++++++++++++ functable.h | 1 + infback.c | 3 +-- inffast.h | 18 ------------------ inffast.c => inffast_tpl.h | 23 ++++++----------------- inflate.c | 3 +-- inflate_p.h | 15 +++++++++++++++ win32/Makefile.a64 | 6 ++---- win32/Makefile.arm | 6 ++---- win32/Makefile.msc | 6 ++---- 19 files changed, 103 insertions(+), 55 deletions(-) delete mode 100644 inffast.h rename inffast.c => inffast_tpl.h (95%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f667e8fe8..48e09d5213 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -967,7 +967,7 @@ set(ZLIB_PRIVATE_HDRS deflate.h deflate_p.h functable.h - inffast.h + inffast_tpl.h inffixed_tbl.h inflate.h inflate_p.h @@ -1001,7 +1001,6 @@ set(ZLIB_SRCS deflate_stored.c functable.c infback.c - inffast.c inflate.c inftrees.c insert_string.c diff --git a/Makefile.in b/Makefile.in index 98b9042eb4..4bfb6313e2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -93,7 +93,6 @@ OBJZ = \ deflate_stored.o \ functable.o \ infback.o \ - inffast.o \ inflate.o \ inftrees.o \ insert_string.o \ @@ -132,7 +131,6 @@ PIC_OBJZ = \ deflate_stored.lo \ functable.lo \ infback.lo \ - inffast.lo \ inflate.lo \ inftrees.lo \ insert_string.lo \ diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 2c64ce59e3..b119f21245 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -94,4 +94,8 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t #include "chunkset_tpl.h" +#define INFLATE_FAST inflate_fast_neon + +#include "inffast_tpl.h" + #endif diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index 83928308d6..abc5f5e214 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -48,4 +48,8 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { #include "chunkset_tpl.h" +#define INFLATE_FAST inflate_fast_power8 + +#include "inffast_tpl.h" + #endif diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index c4a4d9b052..e128e8f708 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -128,4 +128,8 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t #include "chunkset_tpl.h" +#define INFLATE_FAST inflate_fast_avx + +#include "inffast_tpl.h" + #endif diff --git a/arch/x86/chunkset_sse2.c b/arch/x86/chunkset_sse2.c index eddf5d9895..c402c0ee18 100644 --- a/arch/x86/chunkset_sse2.c +++ b/arch/x86/chunkset_sse2.c @@ -49,4 +49,8 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { #include "chunkset_tpl.h" +#define INFLATE_FAST inflate_fast_sse2 + +#include "inffast_tpl.h" + #endif diff --git a/arch/x86/chunkset_sse41.c b/arch/x86/chunkset_sse41.c index c148db0924..9a9558856c 100644 --- a/arch/x86/chunkset_sse41.c +++ b/arch/x86/chunkset_sse41.c @@ -95,4 +95,8 @@ extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); #include "chunkset_tpl.h" +#define INFLATE_FAST inflate_fast_sse41 + +#include "inffast_tpl.h" + #endif diff --git a/chunkset.c b/chunkset.c index 169e411233..7b2bb7ba36 100644 --- a/chunkset.c +++ b/chunkset.c @@ -36,3 +36,7 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { #define CHUNKMEMSET_SAFE chunkmemset_safe_c #include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_c + +#include "inffast_tpl.h" diff --git a/cpu_features.h b/cpu_features.h index 72e40a1652..d211cb112e 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -110,6 +110,24 @@ extern uint8_t* chunkmemset_power8(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif +/* inflate fast loop */ +extern void inflate_fast_c(void *strm, uint32_t start); +#ifdef X86_SSE2_CHUNKSET +extern void inflate_fast_sse2(void *strm, uint32_t start); +#endif +#ifdef X86_SSE41 +extern void inflate_fast_sse41(void *strm, uint32_t start); +#endif +#ifdef X86_AVX_CHUNKSET +extern void inflate_fast_avx(void *strm, uint32_t start); +#endif +#ifdef ARM_NEON_CHUNKSET +extern void inflate_fast_neon(void *strm, uint32_t start); +#endif +#ifdef POWER8_VSX_CHUNKSET +extern void inflate_fast_power8(void *strm, uint32_t start); +#endif + /* CRC32 */ typedef uint32_t (*crc32_func)(uint32_t crc32, const uint8_t *buf, size_t len); diff --git a/functable.c b/functable.c index 35474878d5..1bdba15390 100644 --- a/functable.c +++ b/functable.c @@ -482,6 +482,35 @@ static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) { return functable.compare256(src0, src1); } +Z_INTERNAL void inflate_fast_stub(void *strm, uint32_t start) { + functable.inflate_fast = &inflate_fast_c; + +#ifdef X86_SSE2_CHUNKSET +# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) + if (x86_cpu_has_sse2) +# endif + functable.inflate_fast = &inflate_fast_sse2; +#endif +#if defined(X86_SSE41) && defined(X86_SSE2) + if (x86_cpu_has_sse41) + functable.inflate_fast = &inflate_fast_sse41; +#endif +#ifdef X86_AVX_CHUNKSET + if (x86_cpu_has_avx2) + functable.inflate_fast = &inflate_fast_avx; +#endif +#ifdef ARM_NEON_CHUNKSET + if (arm_cpu_has_neon) + functable.inflate_fast = &inflate_fast_neon; +#endif +#ifdef POWER8_VSX_CHUNKSET + if (power_cpu_has_arch_2_07) + functable.inflate_fast = &inflate_fast_power8; +#endif + + functable.inflate_fast(strm, start); +} + /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { adler32_stub, @@ -497,6 +526,7 @@ Z_INTERNAL Z_TLS struct functable_s functable = { chunkunroll_stub, chunkmemset_stub, chunkmemset_safe_stub, + inflate_fast_stub, insert_string_stub, longest_match_stub, longest_match_slow_stub, diff --git a/functable.h b/functable.h index 531f3a1cef..4319b4c11b 100644 --- a/functable.h +++ b/functable.h @@ -24,6 +24,7 @@ struct functable_s { uint8_t* (* chunkunroll) (uint8_t *out, unsigned *dist, unsigned *len); uint8_t* (* chunkmemset) (uint8_t *out, unsigned dist, unsigned len); uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); + void (* inflate_fast) (void *strm, uint32_t start); void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); diff --git a/infback.c b/infback.c index a7af88f2e2..7d4d88920e 100644 --- a/infback.c +++ b/infback.c @@ -14,7 +14,6 @@ #include "zutil.h" #include "inftrees.h" #include "inflate.h" -#include "inffast.h" #include "inflate_p.h" #include "functable.h" @@ -358,7 +357,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in RESTORE(); if (state->whave < state->wsize) state->whave = state->wsize - left; - zng_inflate_fast(strm, state->wsize); + functable.inflate_fast(strm, state->wsize); LOAD(); break; } diff --git a/inffast.h b/inffast.h deleted file mode 100644 index 179a65da60..0000000000 --- a/inffast.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef INFFAST_H_ -#define INFFAST_H_ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003, 2010 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start); - -#define INFLATE_FAST_MIN_HAVE 8 -#define INFLATE_FAST_MIN_LEFT 258 - -#endif /* INFFAST_H_ */ diff --git a/inffast.c b/inffast_tpl.h similarity index 95% rename from inffast.c rename to inffast_tpl.h index bfb1c83134..6977a560a2 100644 --- a/inffast.c +++ b/inffast_tpl.h @@ -4,24 +4,13 @@ */ #include "zbuild.h" +#include "zendian.h" #include "zutil.h" #include "inftrees.h" #include "inflate.h" -#include "inffast.h" #include "inflate_p.h" #include "functable.h" -/* Load 64 bits from IN and place the bytes at offset BITS in the result. */ -static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { - uint64_t chunk; - memcpy(&chunk, in, sizeof(chunk)); - -#if BYTE_ORDER == LITTLE_ENDIAN - return chunk << bits; -#else - return ZSWAP64(chunk) << bits; -#endif -} /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is @@ -61,7 +50,7 @@ static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ -void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { +void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { /* start: inflate()'s starting value for strm->avail_out */ struct inflate_state *state; z_const unsigned char *in; /* local strm->next_in */ @@ -259,7 +248,7 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { if (op < len) { /* still need some from output */ len -= op; out = chunkcopy_safe(out, from, op, safe); - out = functable.chunkunroll(out, &dist, &len); + out = CHUNKUNROLL(out, &dist, &len); out = chunkcopy_safe(out, out - dist, len, safe); } else { out = chunkcopy_safe(out, from, len, safe); @@ -269,7 +258,7 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { if (dist >= len || dist >= state->chunksize) out = chunkcopy_safe(out, out - dist, len, safe); else - out = functable.chunkmemset_safe(out, dist, len, (unsigned)((safe - out) + 1)); + out = CHUNKMEMSET_SAFE(out, dist, len, (unsigned)((safe - out) + 1)); } else { /* Whole reference is in range of current output. No range checks are necessary because we start with room for at least 258 bytes of output, @@ -277,9 +266,9 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { as they stay within 258 bytes of `out`. */ if (dist >= len || dist >= state->chunksize) - out = functable.chunkcopy(out, out - dist, len); + out = CHUNKCOPY(out, out - dist, len); else - out = functable.chunkmemset(out, dist, len); + out = CHUNKMEMSET(out, dist, len); } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode + here->val + BITS(op); diff --git a/inflate.c b/inflate.c index 7949120997..eaf78ebfb1 100644 --- a/inflate.c +++ b/inflate.c @@ -8,7 +8,6 @@ #include "cpu_features.h" #include "inftrees.h" #include "inflate.h" -#include "inffast.h" #include "inflate_p.h" #include "inffixed_tbl.h" #include "functable.h" @@ -866,7 +865,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* use inflate_fast() if we have enough input and output */ if (have >= INFLATE_FAST_MIN_HAVE && left >= INFLATE_FAST_MIN_LEFT) { RESTORE(); - zng_inflate_fast(strm, out); + functable.inflate_fast(strm, out); LOAD(); if (state->mode == TYPE) state->back = -1; diff --git a/inflate_p.h b/inflate_p.h index 27b6102778..2b57b317e7 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -132,6 +132,21 @@ strm->msg = (char *)errmsg; \ } while (0) +#define INFLATE_FAST_MIN_HAVE 8 +#define INFLATE_FAST_MIN_LEFT 258 + +/* Load 64 bits from IN and place the bytes at offset BITS in the result. */ +static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { + uint64_t chunk; + memcpy(&chunk, in, sizeof(chunk)); + +#if BYTE_ORDER == LITTLE_ENDIAN + return chunk << bits; +#else + return ZSWAP64(chunk) << bits; +#endif +} + /* Behave like chunkcopy, but avoid writing beyond of legal output. */ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, uint64_t len, uint8_t *safe) { uint64_t safelen = (safe - out) + 1; diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index efcb0a64cc..8537bd5fe9 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -64,7 +64,6 @@ OBJS = \ infback.obj \ inflate.obj \ inftrees.obj \ - inffast.obj \ insert_string.obj \ insert_string_roll.obj \ slide_hash.obj \ @@ -200,9 +199,8 @@ deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/defl deflate_rle.obj: $(SRCDIR)/deflate_rle.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_stored.obj: $(SRCDIR)/deflate_stored.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h -inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h -inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h +infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inflate_p.h $(SRCDIR)/functable.h +inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h slide_hash_neon.obj: $(SRCDIR)/arch/arm/slide_hash_neon.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 34dff1a700..58a7fc8661 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -68,7 +68,6 @@ OBJS = \ infback.obj \ inflate.obj \ inftrees.obj \ - inffast.obj \ insert_string.obj \ insert_string_roll.obj \ slide_hash.obj \ @@ -213,9 +212,8 @@ deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflat deflate_rle.obj: $(SRCDIR)/deflate_rle.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_stored.obj: $(SRCDIR)/deflate_stored.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h -inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h -inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h +infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inflate_p.h $(SRCDIR)/functable.h +inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 445b673bc3..9c00737a8f 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -81,7 +81,6 @@ OBJS = \ infback.obj \ inflate.obj \ inftrees.obj \ - inffast.obj \ insert_string.obj \ insert_string_roll.obj \ insert_string_sse42.obj \ @@ -220,9 +219,8 @@ deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflat deflate_rle.obj: $(SRCDIR)/deflate_rle.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_stored.obj: $(SRCDIR)/deflate_stored.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h -inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h -inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h +infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inflate_p.h $(SRCDIR)/functable.h +inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h slide_hash_avx2.obj: $(SRCDIR)/arch/x86/slide_hash_avx2.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h From c72cd309cafae5d7e5eed42b9c4f36a53414362d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 27 Aug 2022 19:34:30 -0700 Subject: [PATCH 577/798] Remove unused chunk memory functions from functable. --- arch/power/chunkset_power8.c | 12 ++-- arch/x86/chunkset_sse41.c | 11 ++-- cpu_features.h | 16 ----- functable.c | 124 ++++++----------------------------- functable.h | 3 - 5 files changed, 31 insertions(+), 135 deletions(-) diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index abc5f5e214..389be08171 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -32,12 +32,6 @@ static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { *chunk = (vector unsigned char)vec_splats(tmp); } -#define CHUNKSIZE chunksize_power8 -#define CHUNKCOPY chunkcopy_power8 -#define CHUNKUNROLL chunkunroll_power8 -#define CHUNKMEMSET chunkmemset_power8 -#define CHUNKMEMSET_SAFE chunkmemset_safe_power8 - static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { *chunk = vec_xl(0, s); } @@ -46,6 +40,12 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { vec_xst(*chunk, 0, out); } +#define CHUNKSIZE chunksize_power8 +#define CHUNKCOPY chunkcopy_power8 +#define CHUNKUNROLL chunkunroll_power8 +#define CHUNKMEMSET chunkmemset_power8 +#define CHUNKMEMSET_SAFE chunkmemset_safe_power8 + #include "chunkset_tpl.h" #define INFLATE_FAST inflate_fast_power8 diff --git a/arch/x86/chunkset_sse41.c b/arch/x86/chunkset_sse41.c index 9a9558856c..4b7396bcac 100644 --- a/arch/x86/chunkset_sse41.c +++ b/arch/x86/chunkset_sse41.c @@ -86,12 +86,13 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t } extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); +extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); -#define CHUNKSIZE chunksize_sse41 -#define CHUNKMEMSET chunkmemset_sse41 -#define CHUNKMEMSET_SAFE chunkmemset_safe_sse41 -#define CHUNKCOPY(a, b, c) chunkcopy_sse2(a, b, c) -#define CHUNKUNROLL(a, b, c) chunkunroll_sse2(a, b, c) +#define CHUNKSIZE chunksize_sse41 +#define CHUNKMEMSET chunkmemset_sse41 +#define CHUNKMEMSET_SAFE chunkmemset_safe_sse41 +#define CHUNKCOPY chunkcopy_sse2 +#define CHUNKUNROLL chunkunroll_sse2 #include "chunkset_tpl.h" diff --git a/cpu_features.h b/cpu_features.h index d211cb112e..696b152210 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -73,40 +73,24 @@ extern uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len); /* memory chunking */ extern uint32_t chunksize_c(void); -extern uint8_t* chunkcopy_c(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkunroll_c(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_c(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_c(uint8_t *out, unsigned dist, unsigned len, unsigned left); #ifdef X86_SSE2_CHUNKSET extern uint32_t chunksize_sse2(void); -extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_sse2(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif #ifdef X86_SSE41 -extern uint8_t* chunkmemset_sse41(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_sse41(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif #ifdef X86_AVX_CHUNKSET extern uint32_t chunksize_avx(void); -extern uint8_t* chunkcopy_avx(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkunroll_avx(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_avx(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_avx(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif #ifdef ARM_NEON_CHUNKSET extern uint32_t chunksize_neon(void); -extern uint8_t* chunkcopy_neon(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkunroll_neon(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_neon(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif #ifdef POWER8_VSX_CHUNKSET extern uint32_t chunksize_power8(void); -extern uint8_t* chunkcopy_power8(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkunroll_power8(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_power8(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif diff --git a/functable.c b/functable.c index 1bdba15390..7f3bc6e034 100644 --- a/functable.c +++ b/functable.c @@ -231,96 +231,54 @@ static void init_functable(void) { ft.chunksize = &chunksize_power8; #endif - // chunkcopy_stub: - ft.chunkcopy = &chunkcopy_c; -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - ft.chunkcopy = &chunkcopy_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - ft.chunkcopy = &chunkcopy_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - ft.chunkcopy = &chunkcopy_neon; -#endif -#ifdef POWER8_VSX_CHUNKSET - if (power_cpu_has_arch_2_07) - ft.chunkcopy = &chunkcopy_power8; -#endif - - // chunkunroll_stub: - ft.chunkunroll = &chunkunroll_c; -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - ft.chunkunroll = &chunkunroll_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - ft.chunkunroll = &chunkunroll_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - ft.chunkunroll = &chunkunroll_neon; -#endif -#ifdef POWER8_VSX_CHUNKSET - if (power_cpu_has_arch_2_07) - ft.chunkunroll = &chunkunroll_power8; -#endif - - // chunkmemset_stub: - ft.chunkmemset = &chunkmemset_c; + // chunkmemset_safe_stub: + ft.chunkmemset_safe = &chunkmemset_safe_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - ft.chunkmemset = &chunkmemset_sse2; + ft.chunkmemset_safe = &chunkmemset_safe_sse2; #endif #if defined(X86_SSE41) && defined(X86_SSE2) if (x86_cpu_has_sse41) - ft.chunkmemset = &chunkmemset_sse41; + ft.chunkmemset_safe = &chunkmemset_safe_sse41; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - ft.chunkmemset = &chunkmemset_avx; + ft.chunkmemset_safe = &chunkmemset_safe_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - ft.chunkmemset = &chunkmemset_neon; + ft.chunkmemset_safe = &chunkmemset_safe_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - ft.chunkmemset = &chunkmemset_power8; + ft.chunkmemset_safe = &chunkmemset_safe_power8; #endif - // chunkmemset_safe_stub: - ft.chunkmemset_safe = &chunkmemset_safe_c; + // inflate_fast_stub: + ft.inflate_fast = &inflate_fast_c; #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif - ft.chunkmemset_safe = &chunkmemset_safe_sse2; + ft.inflate_fast = &inflate_fast_sse2; #endif #if defined(X86_SSE41) && defined(X86_SSE2) if (x86_cpu_has_sse41) - ft.chunkmemset_safe = &chunkmemset_safe_sse41; + ft.inflate_fast = &inflate_fast_sse41; #endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) - ft.chunkmemset_safe = &chunkmemset_safe_avx; + ft.inflate_fast = &inflate_fast_avx; #endif #ifdef ARM_NEON_CHUNKSET if (arm_cpu_has_neon) - ft.chunkmemset_safe = &chunkmemset_safe_neon; + ft.inflate_fast = &inflate_fast_neon; #endif #ifdef POWER8_VSX_CHUNKSET if (power_cpu_has_arch_2_07) - ft.chunkmemset_safe = &chunkmemset_safe_power8; + ft.inflate_fast = &inflate_fast_power8; #endif // crc32_stub: @@ -374,10 +332,8 @@ static void init_functable(void) { functable.crc32_fold_final = ft.crc32_fold_final; functable.compare256 = ft.compare256; functable.chunksize = ft.chunksize; - functable.chunkcopy = ft.chunkcopy; - functable.chunkunroll = ft.chunkunroll; - functable.chunkmemset = ft.chunkmemset; functable.chunkmemset_safe = ft.chunkmemset_safe; + functable.inflate_fast = ft.inflate_fast; functable.insert_string = ft.insert_string; functable.longest_match = ft.longest_match; functable.longest_match_slow = ft.longest_match_slow; @@ -452,24 +408,14 @@ static uint32_t chunksize_stub(void) { return functable.chunksize(); } -static uint8_t* chunkcopy_stub(uint8_t* out, uint8_t const* from, unsigned len) { - init_functable(); - return functable.chunkcopy(out, from, len); -} - -static uint8_t* chunkunroll_stub(uint8_t* out, unsigned* dist, unsigned* len) { - init_functable(); - return functable.chunkunroll(out, dist, len); -} - -static uint8_t* chunkmemset_stub(uint8_t* out, unsigned dist, unsigned len) { +static uint8_t* chunkmemset_safe_stub(uint8_t* out, unsigned dist, unsigned len, unsigned left) { init_functable(); - return functable.chunkmemset(out, dist, len); + return functable.chunkmemset_safe(out, dist, len, left); } -static uint8_t* chunkmemset_safe_stub(uint8_t* out, unsigned dist, unsigned len, unsigned left) { +static void inflate_fast_stub(void *strm, uint32_t start) { init_functable(); - return functable.chunkmemset_safe(out, dist, len, left); + functable.inflate_fast(strm, start); } static uint32_t crc32_stub(uint32_t crc, const uint8_t* buf, size_t len) { @@ -482,35 +428,6 @@ static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) { return functable.compare256(src0, src1); } -Z_INTERNAL void inflate_fast_stub(void *strm, uint32_t start) { - functable.inflate_fast = &inflate_fast_c; - -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.inflate_fast = &inflate_fast_sse2; -#endif -#if defined(X86_SSE41) && defined(X86_SSE2) - if (x86_cpu_has_sse41) - functable.inflate_fast = &inflate_fast_sse41; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - functable.inflate_fast = &inflate_fast_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - functable.inflate_fast = &inflate_fast_neon; -#endif -#ifdef POWER8_VSX_CHUNKSET - if (power_cpu_has_arch_2_07) - functable.inflate_fast = &inflate_fast_power8; -#endif - - functable.inflate_fast(strm, start); -} - /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { adler32_stub, @@ -522,9 +439,6 @@ Z_INTERNAL Z_TLS struct functable_s functable = { crc32_fold_final_stub, compare256_stub, chunksize_stub, - chunkcopy_stub, - chunkunroll_stub, - chunkmemset_stub, chunkmemset_safe_stub, inflate_fast_stub, insert_string_stub, diff --git a/functable.h b/functable.h index 4319b4c11b..51acf45789 100644 --- a/functable.h +++ b/functable.h @@ -20,9 +20,6 @@ struct functable_s { uint32_t (* crc32_fold_final) (struct crc32_fold_s *crc); uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* chunksize) (void); - uint8_t* (* chunkcopy) (uint8_t *out, uint8_t const *from, unsigned len); - uint8_t* (* chunkunroll) (uint8_t *out, unsigned *dist, unsigned *len); - uint8_t* (* chunkmemset) (uint8_t *out, unsigned dist, unsigned len); uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); void (* inflate_fast) (void *strm, uint32_t start); void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); From 17331431e085e535094e3fe29e1a5a473c466f23 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 4 Feb 2023 21:54:09 +0100 Subject: [PATCH 578/798] Replace __builtin_ctz[ll] fallback functions with branchless implementations. Added debug assert check for value = 0. Added more details to the comment to avoid future confusion. Added fallback logic for older MSVC versions, just in case. --- fallback_builtins.h | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/fallback_builtins.h b/fallback_builtins.h index 5b49205ec6..0ceecc8dd1 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -9,36 +9,37 @@ # include "arch/x86/x86_features.h" #endif -/* This is not a general purpose replacement for __builtin_ctz. The function expects that value is != 0 - * Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward is not checked +/* This is not a general purpose replacement for __builtin_ctz. The function expects that value is != 0. + * Because of that assumption trailing_zero is not initialized and the return value is not checked. + * Tzcnt and bsf give identical results except when input value is 0, therefore this can not be allowed. + * If tzcnt instruction is not supported, the cpu will itself execute bsf instead. + * Performance tzcnt/bsf is identical on Intel cpu, tzcnt is faster than bsf on AMD cpu. */ static __forceinline int __builtin_ctz(unsigned int value) { -#ifdef X86_FEATURES -# ifndef X86_NOCHECK_TZCNT - if (x86_cpu_has_tzcnt) -# endif - return (int)_tzcnt_u32(value); -#endif + Assert(value != 0, "Invalid input value: 0"); +# if defined(X86_FEATURES) && !(_MSC_VER < 1700) + return (int)_tzcnt_u32(value); +# else unsigned long trailing_zero; _BitScanForward(&trailing_zero, value); return (int)trailing_zero; +# endif } #define HAVE_BUILTIN_CTZ #ifdef _M_AMD64 -/* This is not a general purpose replacement for __builtin_ctzll. The function expects that value is != 0 - * Because of that assumption trailing_zero is not initialized and the return value of _BitScanForward64 is not checked +/* This is not a general purpose replacement for __builtin_ctzll. The function expects that value is != 0. + * Because of that assumption trailing_zero is not initialized and the return value is not checked. */ static __forceinline int __builtin_ctzll(unsigned long long value) { -#ifdef X86_FEATURES -# ifndef X86_NOCHECK_TZCNT - if (x86_cpu_has_tzcnt) -# endif - return (int)_tzcnt_u64(value); -#endif + Assert(value != 0, "Invalid input value: 0"); +# if defined(X86_FEATURES) && !(_MSC_VER < 1700) + return (int)_tzcnt_u64(value); +# else unsigned long trailing_zero; _BitScanForward64(&trailing_zero, value); return (int)trailing_zero; +# endif } #define HAVE_BUILTIN_CTZLL #endif // Microsoft AMD64 From 17d98072a97d5b29c7b8f24133f2abf263fa93b4 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 4 Feb 2023 22:19:40 +0100 Subject: [PATCH 579/798] Remove FORCE_TZCNT/X86_NOCHECK_TZCNT --- CMakeLists.txt | 5 ----- README.md | 1 - arch/x86/x86_features.c | 3 --- configure | 8 -------- 4 files changed, 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 48e09d5213..27ce9f477c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,7 +112,6 @@ elseif(BASEARCH_S360_FOUND) option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF) option(WITH_CRC32_VX "Build with vectorized CRC32 on IBM Z" ON) elseif(BASEARCH_X86_FOUND) - option(FORCE_TZCNT "Always assume CPU is TZCNT capable" OFF) option(WITH_AVX2 "Build with AVX2" ON) option(WITH_AVX512 "Build with AVX512" ON) option(WITH_AVX512VNNI "Build with AVX512 VNNI extensions" ON) @@ -819,10 +818,6 @@ if(WITH_OPTIM) set(WITH_SSE4 OFF) endif() endif() - if(FORCE_TZCNT) - add_definitions(-DX86_NOCHECK_TZCNT) - endif() - add_feature_info(FORCE_TZCNT FORCE_TZCNT "Assume CPU is TZCNT capable") if(WITH_SSE2) check_sse2_intrinsics() if(HAVE_SSE2_INTRIN) diff --git a/README.md b/README.md index a40980a07b..5b8e8ccdc2 100644 --- a/README.md +++ b/README.md @@ -209,7 +209,6 @@ Advanced Build Options | CMake | configure | Description | Default | |:--------------------------------|:----------------------|:--------------------------------------------------------------------|------------------------| | FORCE_SSE2 | --force-sse2 | Skip runtime check for SSE2 instructions (Always on for x86_64) | OFF (x86) | -| FORCE_TZCNT | --force-tzcnt | Skip runtime check for TZCNT instructions | OFF | | WITH_AVX2 | | Build with AVX2 intrinsics | ON | | WITH_AVX512 | | Build with AVX512 intrinsics | ON | | WITH_AVX512VNNI | | Build with AVX512VNNI intrinsics | ON | diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index 4c7563eab0..d1ac51c55c 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -122,7 +122,4 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_has_avx512vnni = 0; x86_cpu_has_vpclmulqdq = 0; } -#ifdef X86_NOCHECK_TZCNT - Assert(!!x86_cpu_has_tzcnt, "TZCNT is not available"); -#endif } diff --git a/configure b/configure index 9cd5702398..c0f9524b5f 100755 --- a/configure +++ b/configure @@ -103,7 +103,6 @@ buildcrc32vx=1 floatabi= native=0 forcesse2=0 -forcetzcnt=0 # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal # instruction scheduling unless you specify a reasonable -mtune= target avx512flag="-mavx512f -mavx512dq -mavx512bw -mavx512vl -mtune=cascadelake" @@ -177,7 +176,6 @@ case "$1" in echo ' [--without-crc32-vx] Build without vectorized CRC32 on IBM Z' | tee -a configure.log echo ' [--with-reduced-mem] Reduced memory usage for special cases (reduces performance)' | tee -a configure.log echo ' [--force-sse2] Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log - echo ' [--force-tzcnt] Assume TZCNT instructions are always available (disabled by default)' | tee -a configure.log echo ' [--native] Compiles with full instruction set supported on this host' | tee -a configure.log exit 0 ;; -p*=* | --prefix=*) prefix=$(echo $1 | sed 's/.*=//'); shift ;; @@ -211,7 +209,6 @@ case "$1" in --without-crc32-vx) buildcrc32vx=0; shift ;; --with-reduced-mem) reducedmem=1; shift ;; --force-sse2) forcesse2=1; shift ;; - --force-tzcnt) forcetzcnt=1; shift ;; -n | --native) native=1; shift ;; -a*=* | --archs=*) ARCHS=$(echo $1 | sed 's/.*=//'); shift ;; --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; @@ -1652,11 +1649,6 @@ case "${ARCH}" in if test ${HAVE_XSAVE_INTRIN} -eq 0; then xsaveflag="" fi - - if test $forcetzcnt -eq 1; then - CFLAGS="${CFLAGS} -DX86_NOCHECK_TZCNT" - SFLAGS="${SFLAGS} -DX86_NOCHECK_TZCNT" - fi fi ;; From a395e80d73ed4e221d9cd233f39385e1774b4236 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 5 Feb 2023 12:55:39 +0100 Subject: [PATCH 580/798] Remove x86 cpu feature detection for tzcnt --- arch/x86/x86_features.c | 3 --- arch/x86/x86_features.h | 1 - 2 files changed, 4 deletions(-) diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index d1ac51c55c..2c5cb54c65 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -27,7 +27,6 @@ Z_INTERNAL int x86_cpu_has_sse41; Z_INTERNAL int x86_cpu_has_sse42; Z_INTERNAL int x86_cpu_has_pclmulqdq; Z_INTERNAL int x86_cpu_has_vpclmulqdq; -Z_INTERNAL int x86_cpu_has_tzcnt; Z_INTERNAL int x86_cpu_has_os_save_ymm; Z_INTERNAL int x86_cpu_has_os_save_zmm; @@ -97,7 +96,6 @@ void Z_INTERNAL x86_check_features(void) { // check BMI1 bit // Reference: https://software.intel.com/sites/default/files/article/405250/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf - x86_cpu_has_tzcnt = ebx & 0x8; x86_cpu_has_vpclmulqdq = ecx & 0x400; // check AVX2 bit if the OS supports saving YMM registers @@ -116,7 +114,6 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_has_avx512vnni = 0; } } else { - x86_cpu_has_tzcnt = 0; x86_cpu_has_avx2 = 0; x86_cpu_has_avx512 = 0; x86_cpu_has_avx512vnni = 0; diff --git a/arch/x86/x86_features.h b/arch/x86/x86_features.h index 3e0d17f063..06677b2e12 100644 --- a/arch/x86/x86_features.h +++ b/arch/x86/x86_features.h @@ -15,7 +15,6 @@ extern int x86_cpu_has_sse41; extern int x86_cpu_has_sse42; extern int x86_cpu_has_pclmulqdq; extern int x86_cpu_has_vpclmulqdq; -extern int x86_cpu_has_tzcnt; extern int x86_cpu_has_os_save_ymm; extern int x86_cpu_has_os_save_zmm; From 3359879383d0dcd4559c2853c53be8b3a0910606 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 17:10:06 +0100 Subject: [PATCH 581/798] Update to actions/upload-artifact@v3 --- .github/workflows/configure.yml | 2 +- .github/workflows/fuzz.yml | 2 +- .github/workflows/link.yml | 4 ++-- .github/workflows/pigz.yml | 2 +- .github/workflows/pkgcheck.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index c2927f73b3..634ba98a1a 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -220,7 +220,7 @@ jobs: working-directory: ${{ matrix.build-dir }} - name: Upload build errors - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: ${{ matrix.name }} (configure) diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index b108461033..95d64e67ae 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -29,7 +29,7 @@ jobs: dry-run: false - name: Upload Crash - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v3 if: failure() with: name: artifacts diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml index 0ac4f5cff4..918720f517 100644 --- a/.github/workflows/link.yml +++ b/.github/workflows/link.yml @@ -27,7 +27,7 @@ jobs: run: cmake --build native --config Release - name: Upload build errors - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: Link zlib (CMake Logs) @@ -56,7 +56,7 @@ jobs: run: cmake --build native --config Release - name: Upload build errors - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: Link zlib-ng compat (CMake Logs) diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 4400892440..15108a2feb 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -111,7 +111,7 @@ jobs: CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}} - name: Upload build errors - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: ${{ matrix.name }} (cmake) diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 180c2433ba..0bb97fd843 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -153,7 +153,7 @@ jobs: LDFLAGS: ${{ matrix.ldflags }} - name: Upload build errors - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: ${{ matrix.name }} From 39fdb09cdeefe7e689a2e41f338a08c550fd0e59 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 17:18:54 +0100 Subject: [PATCH 582/798] Update codecov uploader --- .github/workflows/cmake.yml | 4 ++-- .github/workflows/pigz.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 11ed5311a1..adb9db7994 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -548,7 +548,7 @@ jobs: --xml --output coverage.xml - name: Upload coverage report - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: matrix.codecov && (env.CODECOV_TOKEN != '' || github.repository == 'zlib-ng/zlib-ng') with: token: ${{ secrets.CODECOV_TOKEN || 'e4fdf847-f541-4ab1-9d50-3d27e5913906' }} @@ -561,7 +561,7 @@ jobs: CODECOV_TOKEN: "${{secrets.CODECOV_TOKEN}}" - name: Upload build errors - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: failure() with: name: ${{ matrix.name }} (cmake) diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 15108a2feb..6a505a119e 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -99,7 +99,7 @@ jobs: --xml --output coverage.xml - name: Upload coverage report - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 if: matrix.codecov && (env.CODECOV_TOKEN != '' || github.repository == 'zlib-ng/zlib-ng') with: token: ${{ secrets.CODECOV_TOKEN || 'e4fdf847-f541-4ab1-9d50-3d27e5913906' }} From 40d97698f1745bab7b3e09f70bf49f76295ff646 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 17:19:05 +0100 Subject: [PATCH 583/798] Update release uploader --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a3327b479..768cf48bcb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -88,7 +88,7 @@ jobs: working-directory: out - name: Upload release (Windows) - uses: svenstaro/upload-release-action@v1-release + uses: svenstaro/upload-release-action@v2 if: runner.os == 'Windows' with: asset_name: zlib-ng-${{ matrix.deploy-name }}.zip From 9b84e1ba9de539b498b9686abae8ab38d040a6bc Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 17:20:24 +0100 Subject: [PATCH 584/798] Update ilammy/msvc-dev-cmd --- .github/workflows/nmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index f8c61af009..38e6690933 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -51,7 +51,7 @@ jobs: uses: actions/checkout@v3 - name: Setup development environment - uses: ilammy/msvc-dev-cmd@v1.10.0 + uses: ilammy/msvc-dev-cmd@v1.12.1 with: arch: ${{ matrix.arch }} From b49c84bc99bb508789781f4b055a0e48996aa97f Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 17:23:06 +0100 Subject: [PATCH 585/798] Update mymindstorm/setup-emsdk --- .github/workflows/cmake.yml | 2 +- .github/workflows/configure.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index adb9db7994..4878038acc 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -482,7 +482,7 @@ jobs: - name: Install Emscripten if: contains(matrix.name, 'WASM32') - uses: mymindstorm/setup-emsdk@v11 + uses: mymindstorm/setup-emsdk@v12 - name: Initialize Wine # Prevent parallel test jobs from initializing Wine at the same time diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 634ba98a1a..7f2a8683b5 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -196,7 +196,7 @@ jobs: - name: Install Emscripten if: contains(matrix.name, 'WASM32') - uses: mymindstorm/setup-emsdk@v11 + uses: mymindstorm/setup-emsdk@v12 - name: Generate project files run: | From f96a7dce50066fb490971d49d2bf826b21f7f8a7 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 23:18:31 +0100 Subject: [PATCH 586/798] Ubuntu 18.04 is being removed shortly, update workflows to use 20.04. Clang-6.0 is still supported according to Ubuntu package list website. --- .github/workflows/cmake.yml | 8 ++++---- .github/workflows/configure.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 4878038acc..1d0eeeb246 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -12,8 +12,8 @@ jobs: fail-fast: false matrix: include: - - name: Ubuntu 18.04 GCC - os: ubuntu-18.04 + - name: Ubuntu 20.04 GCC + os: ubuntu-20.04 compiler: gcc cxx-compiler: g++ @@ -281,8 +281,8 @@ jobs: # Limit parallel test jobs to prevent wine errors parallels-jobs: 1 - - name: Ubuntu 18.04 Clang - os: ubuntu-18.04 + - name: Ubuntu 20.04 Clang + os: ubuntu-20.04 compiler: clang-6.0 cxx-compiler: clang++-6.0 packages: clang-6.0 diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 7f2a8683b5..e0dde6f9be 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -13,8 +13,8 @@ jobs: compiler: gcc configure-args: --warn - - name: Ubuntu 18.04 GCC - os: ubuntu-18.04 + - name: Ubuntu 20.04 GCC + os: ubuntu-20.04 compiler: gcc configure-args: --warn From a21d2bcbc0699d8c6c3cb322433cde80c8daee00 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 6 Feb 2023 15:36:15 +0100 Subject: [PATCH 587/798] Add official Ubuntu mirror list as fallback for Actions caching proxy --- .github/workflows/analyze.yml | 7 +++++++ .github/workflows/cmake.yml | 8 ++++++++ .github/workflows/configure.yml | 8 ++++++++ .github/workflows/pigz.yml | 8 ++++++++ .github/workflows/pkgcheck.yml | 8 ++++++++ 5 files changed, 39 insertions(+) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 3a38edd93f..17333d244c 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -8,6 +8,13 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 + - name: Add ubuntu mirrors + run: | + # Github Actions caching proxy is at times unreliable + echo -e 'http://azure.archive.ubuntu.com/ubuntu\tpriority:1\n' | sudo tee /etc/apt/mirrors.txt + curl http://mirrors.ubuntu.com/mirrors.txt | sudo tee --append /etc/apt/mirrors.txt + sudo sed -i 's#http://azure.archive.ubuntu.com/ubuntu/#mirror+file:/etc/apt/mirrors.txt#' /etc/apt/sources.list + - name: Install packages (Ubuntu) run: sudo apt-get install -y gcc-10 diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 1d0eeeb246..102cef08a0 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -460,6 +460,14 @@ jobs: if: contains(matrix.packages, 'wine') run: sudo dpkg --add-architecture i386 + - name: Add ubuntu mirrors + if: runner.os == 'Linux' && matrix.packages + run: | + # Github Actions caching proxy is at times unreliable + echo -e 'http://azure.archive.ubuntu.com/ubuntu\tpriority:1\n' | sudo tee /etc/apt/mirrors.txt + curl http://mirrors.ubuntu.com/mirrors.txt | sudo tee --append /etc/apt/mirrors.txt + sudo sed -i 's#http://azure.archive.ubuntu.com/ubuntu/#mirror+file:/etc/apt/mirrors.txt#' /etc/apt/sources.list + - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages run: | diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index e0dde6f9be..51861533e0 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -188,6 +188,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 + - name: Add ubuntu mirrors + if: runner.os == 'Linux' && matrix.packages + run: | + # Github Actions caching proxy is at times unreliable + echo -e 'http://azure.archive.ubuntu.com/ubuntu\tpriority:1\n' | sudo tee /etc/apt/mirrors.txt + curl http://mirrors.ubuntu.com/mirrors.txt | sudo tee --append /etc/apt/mirrors.txt + sudo sed -i 's#http://azure.archive.ubuntu.com/ubuntu/#mirror+file:/etc/apt/mirrors.txt#' /etc/apt/sources.list + - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages run: | diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 6a505a119e..e90cb63ab2 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -59,6 +59,14 @@ jobs: repository: zlib-ng/corpora path: test/data/corpora + - name: Add ubuntu mirrors + if: runner.os == 'Linux' && matrix.packages + run: | + # Github Actions caching proxy is at times unreliable + echo -e 'http://azure.archive.ubuntu.com/ubuntu\tpriority:1\n' | sudo tee /etc/apt/mirrors.txt + curl http://mirrors.ubuntu.com/mirrors.txt | sudo tee --append /etc/apt/mirrors.txt + sudo sed -i 's#http://azure.archive.ubuntu.com/ubuntu/#mirror+file:/etc/apt/mirrors.txt#' /etc/apt/sources.list + - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages run: | diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 0bb97fd843..8888cf37e0 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -78,6 +78,14 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 + - name: Add ubuntu mirrors + if: runner.os == 'Linux' && matrix.packages + run: | + # Github Actions caching proxy is at times unreliable + echo -e 'http://azure.archive.ubuntu.com/ubuntu\tpriority:1\n' | sudo tee /etc/apt/mirrors.txt + curl http://mirrors.ubuntu.com/mirrors.txt | sudo tee --append /etc/apt/mirrors.txt + sudo sed -i 's#http://azure.archive.ubuntu.com/ubuntu/#mirror+file:/etc/apt/mirrors.txt#' /etc/apt/sources.list + - name: Install packages (Ubuntu) if: runner.os == 'Linux' run: | From f43f4ddb908dc6fc2541ab5c8d8b8fe08da9a460 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Wed, 8 Feb 2023 00:38:33 +0200 Subject: [PATCH 588/798] Fix ambiguous shift warning in inflateCopy. --- inflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inflate.c b/inflate.c index eaf78ebfb1..6ddb78828f 100644 --- a/inflate.c +++ b/inflate.c @@ -1352,7 +1352,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou } copy->next = copy->codes + (state->next - state->codes); if (window != NULL) { - ZCOPY_WINDOW(window, state->window, 1U << state->wbits); + ZCOPY_WINDOW(window, state->window, (size_t)1U << state->wbits); } copy->window = window; dest->state = (struct internal_state *)copy; From 3e75a5c981ae4b9f798cb72ff145f180b13b4b8a Mon Sep 17 00:00:00 2001 From: Pavel P Date: Mon, 6 Feb 2023 18:06:30 +0300 Subject: [PATCH 589/798] Correct inflate_fast function signature --- cpu_features.h | 18 ++++++++++++------ functable.c | 2 +- functable.h | 8 +++++++- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/cpu_features.h b/cpu_features.h index 696b152210..f71372dd69 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -94,22 +94,28 @@ extern uint32_t chunksize_power8(void); extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif +#ifdef ZLIB_COMPAT +typedef struct z_stream_s z_stream; +#else +typedef struct zng_stream_s zng_stream; +#endif + /* inflate fast loop */ -extern void inflate_fast_c(void *strm, uint32_t start); +extern void inflate_fast_c(PREFIX3(stream) *strm, uint32_t start); #ifdef X86_SSE2_CHUNKSET -extern void inflate_fast_sse2(void *strm, uint32_t start); +extern void inflate_fast_sse2(PREFIX3(stream) *strm, uint32_t start); #endif #ifdef X86_SSE41 -extern void inflate_fast_sse41(void *strm, uint32_t start); +extern void inflate_fast_sse41(PREFIX3(stream) *strm, uint32_t start); #endif #ifdef X86_AVX_CHUNKSET -extern void inflate_fast_avx(void *strm, uint32_t start); +extern void inflate_fast_avx(PREFIX3(stream) *strm, uint32_t start); #endif #ifdef ARM_NEON_CHUNKSET -extern void inflate_fast_neon(void *strm, uint32_t start); +extern void inflate_fast_neon(PREFIX3(stream) *strm, uint32_t start); #endif #ifdef POWER8_VSX_CHUNKSET -extern void inflate_fast_power8(void *strm, uint32_t start); +extern void inflate_fast_power8(PREFIX3(stream) *strm, uint32_t start); #endif /* CRC32 */ diff --git a/functable.c b/functable.c index 7f3bc6e034..7ecc43fa31 100644 --- a/functable.c +++ b/functable.c @@ -413,7 +413,7 @@ static uint8_t* chunkmemset_safe_stub(uint8_t* out, unsigned dist, unsigned len, return functable.chunkmemset_safe(out, dist, len, left); } -static void inflate_fast_stub(void *strm, uint32_t start) { +static void inflate_fast_stub(PREFIX3(stream) *strm, uint32_t start) { init_functable(); functable.inflate_fast(strm, start); } diff --git a/functable.h b/functable.h index 51acf45789..6c277f50aa 100644 --- a/functable.h +++ b/functable.h @@ -10,6 +10,12 @@ #include "crc32_fold.h" #include "adler32_fold.h" +#ifdef ZLIB_COMPAT +typedef struct z_stream_s z_stream; +#else +typedef struct zng_stream_s zng_stream; +#endif + struct functable_s { uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, size_t len); uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); @@ -21,7 +27,7 @@ struct functable_s { uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* chunksize) (void); uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); - void (* inflate_fast) (void *strm, uint32_t start); + void (* inflate_fast) (PREFIX3(stream) *strm, uint32_t start); void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); From d8808f50d57aa7dce163c475477c354003d3d7e4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 7 Feb 2023 18:20:44 -0800 Subject: [PATCH 590/798] Added CI tests for checking undefined symbols in version scripts. --- .github/workflows/cmake.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 102cef08a0..b214288261 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -295,6 +295,24 @@ jobs: gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang + # Check for undefined symbols in the version script for the modern api + - name: Ubuntu Clang Undefined Symbols + os: ubuntu-latest + compiler: clang-11 + cxx-compiler: clang++-11 + cmake-args: -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=lld -Wl,--no-undefined-version" -DZLIBNG_ENABLE_TESTS=OFF + build-shared: ON + packages: clang-11 llvm-11 lld + + # Check for undefined symbols in the version script for the compat api + - name: Ubuntu Clang Undefined Symbols Compat + os: ubuntu-latest + compiler: clang-11 + cxx-compiler: clang++-11 + cmake-args: -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=lld -Wl,--no-undefined-version" -DZLIBNG_ENABLE_TESTS=OFF -DZLIB_COMPAT=ON + build-shared: ON + packages: clang-11 llvm-11 lld + - name: Ubuntu Clang Inflate Strict os: ubuntu-latest compiler: clang-11 @@ -518,7 +536,7 @@ jobs: run: | cmake -S ${{ matrix.build-src-dir || '.' }} -B ${{ matrix.build-dir || '.' }} ${{ matrix.cmake-args }} \ -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} \ - -DBUILD_SHARED_LIBS=OFF \ + -DBUILD_SHARED_LIBS=${{ matrix.build-shared || 'OFF' }} \ -DWITH_FUZZERS=ON \ -DWITH_MAINTAINER_WARNINGS=ON \ ${{ matrix.codecov && '-DWITH_CODE_COVERAGE=ON' }} From 38675bea4ec760ef65bbc37af90b8562fbd93182 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 8 Feb 2023 00:32:54 -0800 Subject: [PATCH 591/798] Disable zlib-ng internal tests when BUILD_SHARED_LIBS=ON. When BUILD_SHARED_LIBS=ON some zlib-ng internal functions are not exported, which are used by gtest_zlib and benchmark_zlib. Therefore, we must disable those tests/projects. --- CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 27ce9f477c..8aad597f98 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1179,6 +1179,19 @@ option(ZLIB_ENABLE_TESTS "Build test binaries" ON) if(ZLIB_ENABLE_TESTS) enable_testing() + if(BUILD_SHARED_LIBS) + if(ZLIBNG_ENABLE_TESTS) + message(STATUS "Disabling zlib-ng tests because shared libraries are enabled") + set(ZLIBNG_ENABLE_TESTS OFF) + endif() + + if(WITH_BENCHMARKS OR WITH_BENCHMARK_APPS) + message(STATUS "Disabling benchmarks because shared libraries are enabled") + set(WITH_BENCHMARKS OFF) + set(WITH_BENCHMARK_APPS OFF) + endif() + endif() + add_subdirectory(test) endif() From 10238c8824e7a714a2a4cf37fd8c27fc52656f64 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 7 Feb 2023 22:08:55 -0800 Subject: [PATCH 592/798] Simplify linking gtest_zlib with zlib target based on BUILD_SHARED_LIBS. Since we turn ZLIBNG_ENABLE_TESTS on or off based on BUILD_SHARED_LIBS, then we don't have to worry about it when linking against zlib. --- test/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 11cf73175e..e8819899ed 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -230,12 +230,15 @@ if(WITH_GTEST) target_link_libraries(gtest_zlib external_zlib) endif() - if((NOT ZLIBNG_ENABLE_TESTS) AND ZLIB_COMPAT AND (NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS)) - # Link dynamically in order to be able to substitute zlib-ng with zlib. - target_link_libraries(gtest_zlib zlib GTest::Main) - else() + if(NOT DEFINED BUILD_SHARED_LIBS) # Link statically in order to test internal zlib-ng functions. target_link_libraries(gtest_zlib zlibstatic) + else() + target_link_libraries(gtest_zlib zlib) + endif() + + if(BUILD_SHARED_LIBS) + target_link_libraries(gtest_zlib GTest::Main) endif() target_link_libraries(gtest_zlib GTest::GTest) From ee978be320b49ad8af09b243b3e5c201fba70f3c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 7 Feb 2023 22:27:37 -0800 Subject: [PATCH 593/798] Fixed link fuzzers against zlib when BUILD_SHARED_LIBS=ON. --- test/fuzz/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt index 9f14637425..27a04c0e74 100644 --- a/test/fuzz/CMakeLists.txt +++ b/test/fuzz/CMakeLists.txt @@ -31,7 +31,12 @@ foreach(FUZZER ${FUZZERS}) target_sources(${FUZZER} PRIVATE standalone_fuzz_target_runner.c) endif() - target_link_libraries(${FUZZER} zlibstatic) + if(NOT DEFINED BUILD_SHARED_LIBS) + target_link_libraries(${FUZZER} zlibstatic) + else() + target_link_libraries(${FUZZER} zlib) + endif() + if(FUZZING_ENGINE_FOUND) target_link_libraries(${FUZZER} ${FUZZING_ENGINE}) endif() From 596f6c2f37eca68db8a9ee7c658dfdf8f15d2a81 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 5 Feb 2023 12:14:18 -0800 Subject: [PATCH 594/798] Use memcpy instead of memcmp for unaligned memory comparisons. Use memcpy because it is better supported for compilers that support unaligned access than memcmp. --- compare256.c | 12 ++++++++---- deflate_quick.c | 3 ++- match_tpl.h | 13 +++++++------ zbuild.h | 19 ------------------- zutil_p.h | 29 +++++++++++++++++++++++++++++ 5 files changed, 46 insertions(+), 30 deletions(-) diff --git a/compare256.c b/compare256.c index b11ac24ee0..94b88e756f 100644 --- a/compare256.c +++ b/compare256.c @@ -4,6 +4,7 @@ */ #include "zbuild.h" +#include "zutil_p.h" #include "fallback_builtins.h" /* ALIGNED, byte comparison */ @@ -61,16 +62,19 @@ static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const uint32_t len = 0; do { - if (zmemcmp_2(src0, src1) != 0) + if (zng_memcmp_2(src0, src1) != 0) return len + (*src0 == *src1); src0 += 2, src1 += 2, len += 2; - if (zmemcmp_2(src0, src1) != 0) + + if (zng_memcmp_2(src0, src1) != 0) return len + (*src0 == *src1); src0 += 2, src1 += 2, len += 2; - if (zmemcmp_2(src0, src1) != 0) + + if (zng_memcmp_2(src0, src1) != 0) return len + (*src0 == *src1); src0 += 2, src1 += 2, len += 2; - if (zmemcmp_2(src0, src1) != 0) + + if (zng_memcmp_2(src0, src1) != 0) return len + (*src0 == *src1); src0 += 2, src1 += 2, len += 2; } while (len < 256); diff --git a/deflate_quick.c b/deflate_quick.c index 4d8013e710..d616677c5f 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -18,6 +18,7 @@ */ #include "zbuild.h" +#include "zutil_p.h" #include "deflate.h" #include "deflate_p.h" #include "functable.h" @@ -92,7 +93,7 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { const uint8_t *str_start = s->window + s->strstart; const uint8_t *match_start = s->window + hash_head; - if (zmemcmp_2(str_start, match_start) == 0) { + if (zng_memcmp_2(str_start, match_start) == 0) { match_len = functable.compare256(str_start+2, match_start+2) + 2; if (match_len >= WANT_MIN_MATCH) { diff --git a/match_tpl.h b/match_tpl.h index fbd34e58a5..d076798520 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -9,6 +9,7 @@ */ #include "zbuild.h" +#include "zutil_p.h" #include "deflate.h" #include "functable.h" @@ -145,24 +146,24 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #ifdef UNALIGNED_OK if (best_len < sizeof(uint32_t)) { for (;;) { - if (zmemcmp_2(mbase_end+cur_match, scan_end) == 0 && - zmemcmp_2(mbase_start+cur_match, scan_start) == 0) + if (zng_memcmp_2(mbase_end+cur_match, scan_end) == 0 && + zng_memcmp_2(mbase_start+cur_match, scan_start) == 0) break; GOTO_NEXT_CHAIN; } # ifdef UNALIGNED64_OK } else if (best_len >= sizeof(uint64_t)) { for (;;) { - if (zmemcmp_8(mbase_end+cur_match, scan_end) == 0 && - zmemcmp_8(mbase_start+cur_match, scan_start) == 0) + if (zng_memcmp_8(mbase_end+cur_match, scan_end) == 0 && + zng_memcmp_8(mbase_start+cur_match, scan_start) == 0) break; GOTO_NEXT_CHAIN; } # endif } else { for (;;) { - if (zmemcmp_4(mbase_end+cur_match, scan_end) == 0 && - zmemcmp_4(mbase_start+cur_match, scan_start) == 0) + if (zng_memcmp_4(mbase_end+cur_match, scan_end) == 0 && + zng_memcmp_4(mbase_start+cur_match, scan_start) == 0) break; GOTO_NEXT_CHAIN; } diff --git a/zbuild.h b/zbuild.h index 901111cd79..c7df4b1e69 100644 --- a/zbuild.h +++ b/zbuild.h @@ -243,25 +243,6 @@ # endif #endif -/* Force compiler to emit unaligned memory comparisons if unaligned access is supported - on the architecture, otherwise don't assume unaligned access is supported. Older - compilers don't optimize memcmp calls for all integer types to unaligned access instructions - when it is supported on the architecture resulting in significant performance impact. */ -#ifdef UNALIGNED_OK -# define zmemcmp_2(str1, str2) (*((uint16_t *)(str1)) != *((uint16_t *)(str2))) -# define zmemcmp_4(str1, str2) (*((uint32_t *)(str1)) != *((uint32_t *)(str2))) -# if defined(UNALIGNED64_OK) && (UINTPTR_MAX == UINT64_MAX) -# define zmemcmp_8(str1, str2) (*((uint64_t *)(str1)) != *((uint64_t *)(str2))) -# else -# define zmemcmp_8(str1, str2) (((uint32_t *)(str1))[0] != ((uint32_t *)(str2))[0] || \ - ((uint32_t *)(str1))[1] != ((uint32_t *)(str2))[1]) -# endif -#else -# define zmemcmp_2(str1, str2) memcmp(str1, str2, 2) -# define zmemcmp_4(str1, str2) memcmp(str1, str2, 4) -# define zmemcmp_8(str1, str2) memcmp(str1, str2, 8) -#endif - #if defined(__has_feature) # if __has_feature(memory_sanitizer) # define Z_MEMORY_SANITIZER 1 diff --git a/zutil_p.h b/zutil_p.h index 318b4d9011..caec91d50d 100644 --- a/zutil_p.h +++ b/zutil_p.h @@ -39,4 +39,33 @@ static inline void zng_free(void *ptr) { #endif } +/* Use memcpy instead of memcmp to avoid older compilers not converting memcmp calls to + unaligned comparisons when unaligned access is supported. */ +static inline int32_t zng_memcmp_2(const void *src0, const void *src1) { + uint16_t src0_cmp, src1_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + + return src0_cmp != src1_cmp; +} + +static inline int32_t zng_memcmp_4(const void *src0, const void *src1) { + uint32_t src0_cmp, src1_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + + return src0_cmp != src1_cmp; +} + +static inline int32_t zng_memcmp_8(const void *src0, const void *src1) { + uint64_t src0_cmp, src1_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + + return src0_cmp != src1_cmp; +} + #endif From 6c09fa26136e352a22d77d3a5a61a4f88f60471c Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 5 Feb 2023 18:01:48 +0100 Subject: [PATCH 595/798] Add missing Z_INTERNAL to some functions that should not be exported. --- arch/arm/adler32_neon.c | 2 +- arch/arm/crc32_acle.c | 2 +- arch/power/adler32_power8.c | 2 +- arch/power/adler32_vmx.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index c8871cc0cd..7f898d18a7 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -141,7 +141,7 @@ static void NEON_handle_tail(uint32_t *pair, const uint8_t *buf, size_t len) { } } -uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len) { +Z_INTERNAL uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len) { /* split Adler-32 into component sums */ uint32_t sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index 701c9925cd..445c370aa8 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -13,7 +13,7 @@ #endif #include "../../zbuild.h" -uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { +Z_INTERNAL uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { Z_REGISTER uint32_t c; Z_REGISTER const uint16_t *buf2; Z_REGISTER const uint32_t *buf4; diff --git a/arch/power/adler32_power8.c b/arch/power/adler32_power8.c index 497e2f92c8..737c6f2fbc 100644 --- a/arch/power/adler32_power8.c +++ b/arch/power/adler32_power8.c @@ -52,7 +52,7 @@ static inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsi return __a; } -uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len) { +Z_INTERNAL uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len) { uint32_t s1 = adler & 0xffff; uint32_t s2 = (adler >> 16) & 0xffff; diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index 1b648820d0..47193286a7 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -113,7 +113,7 @@ static void vmx_accum32(uint32_t *s, const uint8_t *buf, size_t len) { vec_ste(s2acc, 0, s+1); } -uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len) { +Z_INTERNAL uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len) { uint32_t sum2; uint32_t pair[16] ALIGNED_(16); memset(&pair[2], 0, 14); From cf5bb01da9bbd4e3d06607e2c42fd2b1e53add5c Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 10:05:19 +0100 Subject: [PATCH 596/798] Fix prefixing for internal functions calloc/cfree --- deflate.c | 4 ++-- infback.c | 4 ++-- inflate.c | 4 ++-- zlib_name_mangling-ng.h.in | 8 ++------ zlib_name_mangling.h.in | 2 -- zutil.c | 12 ++++++------ zutil.h | 4 ++-- 7 files changed, 16 insertions(+), 22 deletions(-) diff --git a/deflate.c b/deflate.c index 9d8002b982..78b19e26a3 100644 --- a/deflate.c +++ b/deflate.c @@ -202,11 +202,11 @@ int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level strm->msg = NULL; if (strm->zalloc == NULL) { - strm->zalloc = PREFIX3(calloc); + strm->zalloc = PREFIX(zcalloc); strm->opaque = NULL; } if (strm->zfree == NULL) - strm->zfree = PREFIX3(cfree); + strm->zfree = PREFIX(zcfree); if (level == Z_DEFAULT_COMPRESSION) level = 6; diff --git a/infback.c b/infback.c index 7d4d88920e..179cea737b 100644 --- a/infback.c +++ b/infback.c @@ -38,11 +38,11 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateBackInit)(PREFIX3(stream) *strm, int32_t wi return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ if (strm->zalloc == NULL) { - strm->zalloc = PREFIX3(calloc); + strm->zalloc = PREFIX(zcalloc); strm->opaque = NULL; } if (strm->zfree == NULL) - strm->zfree = PREFIX3(cfree); + strm->zfree = PREFIX(zcfree); state = ZALLOC_INFLATE_STATE(strm); if (state == NULL) return Z_MEM_ERROR; diff --git a/inflate.c b/inflate.c index 6ddb78828f..497b12d667 100644 --- a/inflate.c +++ b/inflate.c @@ -146,11 +146,11 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateInit2)(PREFIX3(stream) *strm, int32_t windo return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ if (strm->zalloc == NULL) { - strm->zalloc = PREFIX3(calloc); + strm->zalloc = PREFIX(zcalloc); strm->opaque = NULL; } if (strm->zfree == NULL) - strm->zfree = PREFIX3(cfree); + strm->zfree = PREFIX(zcfree); state = ZALLOC_INFLATE_STATE(strm); if (state == NULL) return Z_MEM_ERROR; diff --git a/zlib_name_mangling-ng.h.in b/zlib_name_mangling-ng.h.in index 58f0728c6c..de69824109 100644 --- a/zlib_name_mangling-ng.h.in +++ b/zlib_name_mangling-ng.h.in @@ -125,10 +125,8 @@ # define zng_uncompress2 @ZLIB_SYMBOL_PREFIX@zng_uncompress2 #endif #define zng_zError @ZLIB_SYMBOL_PREFIX@zng_zError -#ifndef Z_SOLO -# define zng_zcalloc @ZLIB_SYMBOL_PREFIX@zng_zcalloc -# define zng_zcfree @ZLIB_SYMBOL_PREFIX@zng_zcfree -#endif +#define zng_zcalloc @ZLIB_SYMBOL_PREFIX@zng_zcalloc +#define zng_zcfree @ZLIB_SYMBOL_PREFIX@zng_zcfree #define zng_zlibCompileFlags @ZLIB_SYMBOL_PREFIX@zng_zlibCompileFlags #define zng_zlibVersion @ZLIB_SYMBOL_PREFIX@zng_zlibVersion @@ -171,8 +169,6 @@ #define zng_zError @ZLIB_SYMBOL_PREFIX@zng_zError #define zng_alloc_aligned @ZLIB_SYMBOL_PREFIX@zng_alloc_aligned -#define zng_calloc @ZLIB_SYMBOL_PREFIX@zng_calloc -#define zng_cfree @ZLIB_SYMBOL_PREFIX@zng_cfree #define zng_free_aligned @ZLIB_SYMBOL_PREFIX@zng_free_aligned #define zng_get_crc_table @ZLIB_SYMBOL_PREFIX@zng_get_crc_table #define zng_inflateSyncPoint @ZLIB_SYMBOL_PREFIX@zng_inflateSyncPoint diff --git a/zlib_name_mangling.h.in b/zlib_name_mangling.h.in index 4b150eaa77..c4d23a05c9 100644 --- a/zlib_name_mangling.h.in +++ b/zlib_name_mangling.h.in @@ -165,8 +165,6 @@ /* zlib-ng specific symbols */ #define zng_alloc_aligned @ZLIB_SYMBOL_PREFIX@zng_alloc_aligned -#define zng_calloc @ZLIB_SYMBOL_PREFIX@zng_calloc -#define zng_cfree @ZLIB_SYMBOL_PREFIX@zng_cfree #define zng_free_aligned @ZLIB_SYMBOL_PREFIX@zng_free_aligned #endif /* ZLIB_NAME_MANGLING_H */ diff --git a/zutil.c b/zutil.c index cd67cf435e..5432b9c003 100644 --- a/zutil.c +++ b/zutil.c @@ -100,12 +100,12 @@ const char * Z_EXPORT PREFIX(zError)(int err) { return ERR_MSG(err); } -void Z_INTERNAL *PREFIX3(calloc)(void *opaque, unsigned items, unsigned size) { +void Z_INTERNAL *PREFIX(zcalloc)(void *opaque, unsigned items, unsigned size) { Z_UNUSED(opaque); return zng_alloc((size_t)items * (size_t)size); } -void Z_INTERNAL PREFIX3(cfree)(void *opaque, void *ptr) { +void Z_INTERNAL PREFIX(zcfree)(void *opaque, void *ptr) { Z_UNUSED(opaque); zng_free(ptr); } @@ -118,8 +118,8 @@ void Z_INTERNAL *PREFIX3(alloc_aligned)(zng_calloc_func zalloc, void *opaque, un void *ptr; /* If no custom calloc function used then call zlib-ng's aligned calloc */ - if (zalloc == PREFIX3(calloc)) - return PREFIX3(calloc)(opaque, items, size); + if (zalloc == PREFIX(zcalloc)) + return PREFIX(zcalloc)(opaque, items, size); /* Allocate enough memory for proper alignment and to store the original memory pointer */ alloc_size = sizeof(void *) + (items * size) + align; @@ -143,8 +143,8 @@ void Z_INTERNAL *PREFIX3(alloc_aligned)(zng_calloc_func zalloc, void *opaque, un void Z_INTERNAL PREFIX3(free_aligned)(zng_cfree_func zfree, void *opaque, void *ptr) { /* If no custom cfree function used then call zlib-ng's aligned cfree */ - if (zfree == PREFIX3(cfree)) { - PREFIX3(cfree)(opaque, ptr); + if (zfree == PREFIX(zcfree)) { + PREFIX(zcfree)(opaque, ptr); return; } if (!ptr) diff --git a/zutil.h b/zutil.h index 7f177ef1f0..3dd548d38b 100644 --- a/zutil.h +++ b/zutil.h @@ -126,8 +126,8 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ /* memory allocation functions */ -void Z_INTERNAL *PREFIX3(calloc)(void *opaque, unsigned items, unsigned size); -void Z_INTERNAL PREFIX3(cfree)(void *opaque, void *ptr); +void Z_INTERNAL *PREFIX(zcalloc)(void *opaque, unsigned items, unsigned size); +void Z_INTERNAL PREFIX(zcfree)(void *opaque, void *ptr); typedef void *zng_calloc_func(void *opaque, unsigned items, unsigned size); typedef void zng_cfree_func(void *opaque, void *ptr); From 0ba881e3c1aba7dd5f6323709300f4dedb465896 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 10:17:27 +0100 Subject: [PATCH 597/798] Fix wrong names and invalid entries in zlib.map and zlib-ng.map --- zlib-ng.map | 17 +++++++---------- zlib.map | 2 -- zutil.c | 6 +++--- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/zlib-ng.map b/zlib-ng.map index aa29a54ef6..64411ab105 100644 --- a/zlib-ng.map +++ b/zlib-ng.map @@ -5,12 +5,12 @@ ZLIB_NG_2.1.0 { zng_inflateBackInit; zng_inflateInit; zng_inflateInit2; + zlibng_version; }; ZLIB_NG_2.0.0 { global: zng_adler32; - zng_adler32_c; zng_adler32_combine; zng_adler32_z; zng_compress; @@ -64,17 +64,14 @@ ZLIB_NG_2.0.0 { zng_uncompress2; zng_zError; zng_zlibCompileFlags; - zng_zlibng_string; - zng_version; + zng_vstring; local: zng_deflate_copyright; zng_inflate_copyright; - zng_inflate_fast; - zng_inflate_table; zng_zcalloc; zng_zcfree; zng_z_errmsg; - zng_gz_error; + gz_error; _*; }; @@ -95,20 +92,20 @@ ZLIB_NG_GZ_2.0.0 { zng_gzgetc; zng_gzgets; zng_gzoffset; - zng_gzoffset64; zng_gzopen; - zng_gzopen64; zng_gzprintf; zng_gzputc; zng_gzputs; zng_gzread; zng_gzrewind; zng_gzseek; - zng_gzseek64; zng_gzsetparams; zng_gztell; - zng_gztell64; zng_gzungetc; zng_gzvprintf; zng_gzwrite; }; + +FAIL { + local: *; +}; diff --git a/zlib.map b/zlib.map index fccc0e129d..ebca10d351 100644 --- a/zlib.map +++ b/zlib.map @@ -9,8 +9,6 @@ ZLIB_1.2.0 { local: deflate_copyright; inflate_copyright; - inflate_fast; - inflate_table; zcalloc; zcfree; z_errmsg; diff --git a/zutil.c b/zutil.c index 5432b9c003..742c33ac3d 100644 --- a/zutil.c +++ b/zutil.c @@ -20,14 +20,14 @@ z_const char * const PREFIX(z_errmsg)[10] = { (z_const char *)"" }; +const char PREFIX3(vstring)[] = + " zlib-ng 2.1.0.devel forked from zlib"; + #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { return ZLIB_VERSION; } #else -const char zlibng_string[] = - " zlib-ng 2.1.0.devel forked from zlib"; - const char * Z_EXPORT zlibng_version(void) { return ZLIBNG_VERSION; } From ccfcb356f5b1a24913b90bc65959f27730b1aeb9 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 13:57:56 +0100 Subject: [PATCH 598/798] Fix various incorrect name mangling --- zlib_name_mangling-ng.h.in | 22 ++++++++-------------- zlib_name_mangling.h.in | 6 +++--- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/zlib_name_mangling-ng.h.in b/zlib_name_mangling-ng.h.in index de69824109..e90904a737 100644 --- a/zlib_name_mangling-ng.h.in +++ b/zlib_name_mangling-ng.h.in @@ -18,11 +18,9 @@ #define zng_adler32_combine @ZLIB_SYMBOL_PREFIX@zng_adler32_combine #define zng_adler32_combine64 @ZLIB_SYMBOL_PREFIX@zng_adler32_combine64 #define zng_adler32_z @ZLIB_SYMBOL_PREFIX@zng_adler32_z -#ifndef Z_SOLO -# define zng_compress @ZLIB_SYMBOL_PREFIX@zng_compress -# define zng_compress2 @ZLIB_SYMBOL_PREFIX@zng_compress2 -# define zng_compressBound @ZLIB_SYMBOL_PREFIX@zng_compressBound -#endif +#define zng_compress @ZLIB_SYMBOL_PREFIX@zng_compress +#define zng_compress2 @ZLIB_SYMBOL_PREFIX@zng_compress2 +#define zng_compressBound @ZLIB_SYMBOL_PREFIX@zng_compressBound #define zng_crc32 @ZLIB_SYMBOL_PREFIX@zng_crc32 #define zng_crc32_combine @ZLIB_SYMBOL_PREFIX@zng_crc32_combine #define zng_crc32_combine64 @ZLIB_SYMBOL_PREFIX@zng_crc32_combine64 @@ -52,7 +50,7 @@ #define zng_fixedtables @ZLIB_SYMBOL_PREFIX@zng_fixedtables #define zng_flush_pending @ZLIB_SYMBOL_PREFIX@zng_flush_pending #define zng_get_crc_table @ZLIB_SYMBOL_PREFIX@zng_get_crc_table -#ifndef Z_SOLO +#ifdef WITH_GZFILEOP # define zng_gz_error @ZLIB_SYMBOL_PREFIX@zng_gz_error # define zng_gz_strwinerror @ZLIB_SYMBOL_PREFIX@zng_gz_strwinerror # define zng_gzbuffer @ZLIB_SYMBOL_PREFIX@zng_gzbuffer @@ -120,10 +118,8 @@ #define zng_inflate_fast @ZLIB_SYMBOL_PREFIX@zng_inflate_fast #define zng_inflate_table @ZLIB_SYMBOL_PREFIX@zng_inflate_table #define zng_read_buf @ZLIB_SYMBOL_PREFIX@zng_read_buf -#ifndef Z_SOLO -# define zng_uncompress @ZLIB_SYMBOL_PREFIX@zng_uncompress -# define zng_uncompress2 @ZLIB_SYMBOL_PREFIX@zng_uncompress2 -#endif +#define zng_uncompress @ZLIB_SYMBOL_PREFIX@zng_uncompress +#define zng_uncompress2 @ZLIB_SYMBOL_PREFIX@zng_uncompress2 #define zng_zError @ZLIB_SYMBOL_PREFIX@zng_zError #define zng_zcalloc @ZLIB_SYMBOL_PREFIX@zng_zcalloc #define zng_zcfree @ZLIB_SYMBOL_PREFIX@zng_zcfree @@ -136,7 +132,7 @@ #define alloc_func @ZLIB_SYMBOL_PREFIX@alloc_func #define charf @ZLIB_SYMBOL_PREFIX@charf #define free_func @ZLIB_SYMBOL_PREFIX@free_func -#ifndef Z_SOLO +#ifdef WITH_GZFILEOP # define gzFile @ZLIB_SYMBOL_PREFIX@gzFile #endif #define gz_header @ZLIB_SYMBOL_PREFIX@gz_header @@ -156,9 +152,6 @@ #define zng_gz_header_s @ZLIB_SYMBOL_PREFIX@zng_gz_header_s #define internal_state @ZLIB_SYMBOL_PREFIX@internal_state -/* all zlib structs in zutil.h */ -#define zlibng_string @ZLIB_SYMBOL_PREFIX@zlibng_string - /* zlib-ng specific symbols */ #define zng_deflate_param @ZLIB_SYMBOL_PREFIX@zng_deflate_param #define zng_deflate_param_value @ZLIB_SYMBOL_PREFIX@zng_deflate_param_value @@ -166,6 +159,7 @@ #define zng_deflateGetParams @ZLIB_SYMBOL_PREFIX@zng_deflateGetParams #define zlibng_version @ZLIB_SYMBOL_PREFIX@zlibng_version +#define zng_vstring @ZLIB_SYMBOL_PREFIX@zng_vstring #define zng_zError @ZLIB_SYMBOL_PREFIX@zng_zError #define zng_alloc_aligned @ZLIB_SYMBOL_PREFIX@zng_alloc_aligned diff --git a/zlib_name_mangling.h.in b/zlib_name_mangling.h.in index c4d23a05c9..f496158181 100644 --- a/zlib_name_mangling.h.in +++ b/zlib_name_mangling.h.in @@ -160,11 +160,11 @@ /* all zlib structs in zutil.h */ #define z_errmsg @ZLIB_SYMBOL_PREFIX@z_errmsg -#define zlibng_string @ZLIB_SYMBOL_PREFIX@zlibng_string +#define z_vstring @ZLIB_SYMBOL_PREFIX@z_vstring #define zlibng_version @ZLIB_SYMBOL_PREFIX@zlibng_version /* zlib-ng specific symbols */ -#define zng_alloc_aligned @ZLIB_SYMBOL_PREFIX@zng_alloc_aligned -#define zng_free_aligned @ZLIB_SYMBOL_PREFIX@zng_free_aligned +#define zng_alloc_aligned @ZLIB_SYMBOL_PREFIX@zng_alloc_aligned +#define zng_free_aligned @ZLIB_SYMBOL_PREFIX@zng_free_aligned #endif /* ZLIB_NAME_MANGLING_H */ From d07a427467e3abc191dd3575d3241ba302f1f098 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 9 Feb 2023 01:51:09 +0100 Subject: [PATCH 599/798] Adjust thread counts for compiles and tests to avoid under-utilization and congestion. The free Github Actions VMs have 2 cores, the dedicated s390x VM has 4 cores. --- .github/workflows/analyze.yml | 4 ++-- .github/workflows/cmake.yml | 16 +++++++++++++--- .github/workflows/libpng.yml | 6 +++--- .github/workflows/link.yml | 8 ++++---- .github/workflows/pigz.yml | 4 ++-- .github/workflows/release.yml | 2 +- test/pkgcheck.sh | 2 +- 7 files changed, 26 insertions(+), 16 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 17333d244c..cbdea0e504 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -49,7 +49,7 @@ jobs: CI: true - name: Compile source code - run: cmake --build . --config Release > /dev/null + run: cmake --build . -j2 --config Release > /dev/null Clang: runs-on: ubuntu-latest @@ -75,4 +75,4 @@ jobs: - name: Compile source code run: | scan-build --status-bugs \ - cmake --build . --config Release > /dev/null + cmake --build . -j2 --config Release > /dev/null diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index b214288261..b0cde4246f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -231,6 +231,8 @@ jobs: packages: qemu qemu-user gcc-s390x-linux-gnu g++-s390x-linux-gnu libc-dev-s390x-cross ldflags: -static codecov: ubuntu_gcc_s390x + # The dedicated test VM has 4 cores + parallels-jobs: 4 - name: Ubuntu GCC S390X No vectorized CRC32 ASAN os: ubuntu-latest @@ -239,6 +241,8 @@ jobs: packages: qemu qemu-user gcc-s390x-linux-gnu g++-s390x-linux-gnu libc-dev-s390x-cross ldflags: -static codecov: ubuntu_gcc_s390x_no_crc32 + # The dedicated test VM has 4 cores + parallels-jobs: 4 - name: Ubuntu GCC S390X DFLTCC ASAN os: z15 @@ -248,6 +252,8 @@ jobs: asan-options: detect_leaks=0 ldflags: -static codecov: ubuntu_gcc_s390x_dfltcc + # The dedicated test VM has 4 cores + parallels-jobs: 4 - name: Ubuntu GCC S390X DFLTCC Compat UBSAN os: z15 @@ -256,12 +262,16 @@ jobs: cmake-args: -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined ldflags: -static codecov: ubuntu_gcc_s390x_dfltcc_compat + # The dedicated test VM has 4 cores + parallels-jobs: 4 - name: Ubuntu Clang S390X DFLTCC MSAN os: z15 compiler: clang-11 cxx-compiler: clang++-11 cmake-args: -GNinja -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Memory + # The dedicated test VM has 4 cores + parallels-jobs: 4 - name: Ubuntu MinGW i686 os: ubuntu-22.04 @@ -524,7 +534,7 @@ jobs: -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" \ -DLLVM_USE_SANITIZER=MemoryWithOrigins \ -DLLVM_LIBC_ENABLE_LINTING=OFF - cmake --build llvm-project/build -- cxx cxxabi + cmake --build llvm-project/build -j2 -- cxx cxxabi echo "LLVM_BUILD_DIR=`pwd`/llvm-project/build" >> $GITHUB_ENV env: CC: ${{ matrix.compiler }} @@ -548,12 +558,12 @@ jobs: CI: true - name: Compile source code - run: cmake --build ${{ matrix.build-dir || '.' }} --config ${{ matrix.build-config || 'Release' }} + run: cmake --build ${{ matrix.build-dir || '.' }} -j2 --config ${{ matrix.build-config || 'Release' }} - name: Run test cases # Don't run tests on Windows ARM if: runner.os != 'Windows' || contains(matrix.name, 'ARM') == false - run: ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '6' }} + run: ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '3' }} working-directory: ${{ matrix.build-dir || '.' }} env: ASAN_OPTIONS: ${{ matrix.asan-options || 'verbosity=0' }}:abort_on_error=1:halt_on_error=1 diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index 9118a96c81..c5fea574fe 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -21,7 +21,7 @@ jobs: CI: true - name: Compile source code (zlib-ng) - run: cmake --build . --config Release + run: cmake --build . -j2 --config Release - name: Checkout repository (libpng) uses: actions/checkout@v3 @@ -43,9 +43,9 @@ jobs: CI: true - name: Compile source code (libpng) - run: cmake --build . --config Release + run: cmake --build . -j2 --config Release working-directory: libpng - name: Run test cases (libpng) - run: ctest -C Release --output-on-failure --max-width 120 + run: ctest -j2 -C Release --output-on-failure --max-width 120 working-directory: libpng diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml index 918720f517..5de669840f 100644 --- a/.github/workflows/link.yml +++ b/.github/workflows/link.yml @@ -18,13 +18,13 @@ jobs: run: cmake -S zlib -B zlib/build -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF - name: Compile source code (zlib) - run: cmake --build zlib/build --config Release + run: cmake --build zlib/build -j2 --config Release - name: Generate project files (native) run: cmake -S . -B native -DZLIB_COMPAT=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_LIBRARIES=../zlib/build/libz.a -DZLIB_INCLUDE_DIR="../zlib/build;../zlib" - name: Compile source code (native) - run: cmake --build native --config Release + run: cmake --build native -j2 --config Release - name: Upload build errors uses: actions/upload-artifact@v3 @@ -47,13 +47,13 @@ jobs: run: cmake -S . -B compat -DZLIB_COMPAT=ON -DZLIB_ENABLE_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWITH_MAINTAINER_WARNINGS=ON - name: Compile source code (compat) - run: cmake --build compat --config Release + run: cmake --build compat -j2 --config Release - name: Generate project files (native) run: cmake -S . -B native -DZLIB_COMPAT=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DZLIB_LIBRARIES=../compat/libz.a -DZLIB_INCLUDE_DIR=../compat - name: Compile source code (native) - run: cmake --build native --config Release + run: cmake --build native -j2 --config Release - name: Upload build errors uses: actions/upload-artifact@v3 diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index e90cb63ab2..be4e1ce507 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -89,11 +89,11 @@ jobs: CI: true - name: Compile source code - run: cmake --build . --config ${{ matrix.build-config || 'Release' }} + run: cmake --build . -j2 --config ${{ matrix.build-config || 'Release' }} working-directory: test/pigz - name: Run test cases - run: ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '2' }} + run: ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '3' }} working-directory: test/pigz - name: Generate coverage report diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 768cf48bcb..b64933cc7c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -80,7 +80,7 @@ jobs: CI: true - name: Compile source code - run: cmake --build . --config Release --target install + run: cmake --build . -j2 --config Release --target install - name: Package release (Windows) if: runner.os == 'Windows' diff --git a/test/pkgcheck.sh b/test/pkgcheck.sh index 4c757dff10..832df8dbef 100644 --- a/test/pkgcheck.sh +++ b/test/pkgcheck.sh @@ -125,7 +125,7 @@ cd btmp1 ;; esac ../configure $CONFIGURE_ARGS - make + make -j2 make install cd .. From 4dedec7e3b81b220c7d3b1c8a9ff05f53db0c6ee Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Mon, 6 Feb 2023 05:50:05 +0200 Subject: [PATCH 600/798] Update zlib-ng ABI files. --- ...baf80882311-aarch64-unknown-linux-gnu.abi} | 658 +++++++-------- ...baf80882311-arm-unknown-linux-gnueabi.abi} | 662 +++++++-------- ...f80882311-arm-unknown-linux-gnueabihf.abi} | 662 +++++++-------- ...baf80882311-powerpc-unknown-linux-gnu.abi} | 658 +++++++-------- ...f80882311-powerpc64-unknown-linux-gnu.abi} | 656 +++++++-------- ...0882311-powerpc64le-unknown-linux-gnu.abi} | 656 +++++++-------- ...e4baf80882311-x86_64-pc-linux-gnu-m32.abi} | 756 +++++++++--------- ...c155e4baf80882311-x86_64-pc-linux-gnu.abi} | 756 +++++++++--------- test/abicheck.sh | 2 +- 9 files changed, 2527 insertions(+), 2939 deletions(-) rename test/abi/{zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-aarch64-unknown-linux-gnu.abi => zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-aarch64-unknown-linux-gnu.abi} (87%) rename test/abi/{zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabi.abi => zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-arm-unknown-linux-gnueabi.abi} (87%) rename test/abi/{zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabihf.abi => zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-arm-unknown-linux-gnueabihf.abi} (87%) rename test/abi/{zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc-unknown-linux-gnu.abi => zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc-unknown-linux-gnu.abi} (87%) rename test/abi/{zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64-unknown-linux-gnu.abi => zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc64-unknown-linux-gnu.abi} (87%) rename test/abi/{zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64le-unknown-linux-gnu.abi => zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc64le-unknown-linux-gnu.abi} (87%) rename test/abi/{zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi => zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-x86_64-pc-linux-gnu-m32.abi} (87%) rename test/abi/{zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi => zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-x86_64-pc-linux-gnu.abi} (87%) diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-aarch64-unknown-linux-gnu.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-aarch64-unknown-linux-gnu.abi similarity index 87% rename from test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-aarch64-unknown-linux-gnu.abi rename to test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-aarch64-unknown-linux-gnu.abi index 9aa91cef2e..cfc0eddc62 100644 --- a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-aarch64-unknown-linux-gnu.abi +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-aarch64-unknown-linux-gnu.abi @@ -4,9 +4,7 @@ - - - + @@ -95,7 +93,7 @@ - + @@ -790,21 +788,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -826,13 +824,13 @@ - + - + @@ -896,81 +894,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -984,7 +973,7 @@ - + @@ -993,239 +982,200 @@ - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + + + + + + - - - + + + @@ -1236,64 +1186,64 @@ - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -1323,7 +1273,7 @@ - + @@ -1340,10 +1290,10 @@ - - + + - + @@ -1352,38 +1302,38 @@ - + - + - + - + - + - + - + - + @@ -1392,20 +1342,20 @@ - + - - + + - - + + - - + + - + @@ -1440,13 +1390,13 @@ - - + + - + @@ -1506,10 +1456,10 @@ - + - + @@ -1530,16 +1480,16 @@ - + - + - + - + @@ -1554,7 +1504,7 @@ - + @@ -1565,208 +1515,204 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + - - + + - - - + + + - + - + - + - - + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + @@ -1785,16 +1731,16 @@ - - + + - - + + - - - - + + + + @@ -1804,13 +1750,13 @@ - + - + @@ -1823,9 +1769,9 @@ - + - + @@ -1888,44 +1834,44 @@ - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1935,10 +1881,10 @@ - + - + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabi.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-arm-unknown-linux-gnueabi.abi similarity index 87% rename from test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabi.abi rename to test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-arm-unknown-linux-gnueabi.abi index 7a99d6d4d2..414f8a96ec 100644 --- a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabi.abi +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-arm-unknown-linux-gnueabi.abi @@ -4,9 +4,7 @@ - - - + @@ -95,7 +93,7 @@ - + @@ -778,21 +776,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -814,13 +812,13 @@ - + - + @@ -892,81 +890,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -980,7 +969,7 @@ - + @@ -989,239 +978,200 @@ - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + + + + + + - - - + + + @@ -1232,64 +1182,64 @@ - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -1319,15 +1269,15 @@ - + - - + + - + @@ -1336,38 +1286,38 @@ - + - + - + - + - + - + - + - + @@ -1376,20 +1326,20 @@ - + - - + + - - + + - - + + - + @@ -1424,13 +1374,13 @@ - - + + - + @@ -1490,10 +1440,10 @@ - + - + @@ -1514,16 +1464,16 @@ - + - + - + - + @@ -1538,7 +1488,7 @@ - + @@ -1549,209 +1499,205 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + - - + + - - - + + + - + - + - + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + @@ -1770,16 +1716,16 @@ - - + + - - + + - - - - + + + + @@ -1789,13 +1735,13 @@ - + - + @@ -1808,9 +1754,9 @@ - + - + @@ -1873,44 +1819,44 @@ - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1920,10 +1866,10 @@ - + - + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabihf.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-arm-unknown-linux-gnueabihf.abi similarity index 87% rename from test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabihf.abi rename to test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-arm-unknown-linux-gnueabihf.abi index b3f30ff36d..f5b3aa7737 100644 --- a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-arm-unknown-linux-gnueabihf.abi +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-arm-unknown-linux-gnueabihf.abi @@ -4,9 +4,7 @@ - - - + @@ -95,7 +93,7 @@ - + @@ -778,21 +776,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -814,13 +812,13 @@ - + - + @@ -884,81 +882,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -972,7 +961,7 @@ - + @@ -981,239 +970,200 @@ - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + + + + + + - - - + + + @@ -1224,64 +1174,64 @@ - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -1311,15 +1261,15 @@ - + - - + + - + @@ -1328,38 +1278,38 @@ - + - + - + - + - + - + - + - + @@ -1368,20 +1318,20 @@ - + - - + + - - + + - - + + - + @@ -1416,13 +1366,13 @@ - - + + - + @@ -1482,10 +1432,10 @@ - + - + @@ -1506,16 +1456,16 @@ - + - + - + - + @@ -1530,7 +1480,7 @@ - + @@ -1541,209 +1491,205 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + - - + + - - - + + + - + - + - + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + @@ -1762,16 +1708,16 @@ - - + + - - + + - - - - + + + + @@ -1781,13 +1727,13 @@ - + - + @@ -1800,9 +1746,9 @@ - + - + @@ -1865,44 +1811,44 @@ - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1912,10 +1858,10 @@ - + - + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc-unknown-linux-gnu.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc-unknown-linux-gnu.abi similarity index 87% rename from test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc-unknown-linux-gnu.abi rename to test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc-unknown-linux-gnu.abi index 81bda0d88d..3164f07e71 100644 --- a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc-unknown-linux-gnu.abi +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc-unknown-linux-gnu.abi @@ -4,9 +4,7 @@ - - - + @@ -95,7 +93,7 @@ - + @@ -778,21 +776,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -814,13 +812,13 @@ - + - + @@ -892,81 +890,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -980,13 +969,13 @@ - + - + @@ -995,225 +984,186 @@ - + - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - + + + + - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + + + + + + - - - + + + @@ -1224,64 +1174,64 @@ - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -1311,7 +1261,7 @@ - + @@ -1328,9 +1278,9 @@ - + - + @@ -1339,38 +1289,38 @@ - + - + - + - + - + - + - + - + @@ -1379,20 +1329,20 @@ - + - - + + - - + + - - + + - + @@ -1427,13 +1377,13 @@ - - + + - + @@ -1493,10 +1443,10 @@ - + - + @@ -1517,16 +1467,16 @@ - + - + - + - + @@ -1541,7 +1491,7 @@ - + @@ -1552,209 +1502,205 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + - - + + - - - + + + - + - + - + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + @@ -1773,16 +1719,16 @@ - - + + - - + + - - - - + + + + @@ -1792,13 +1738,13 @@ - + - + @@ -1814,9 +1760,9 @@ - + - + @@ -1879,44 +1825,44 @@ - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1926,10 +1872,10 @@ - + - + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64-unknown-linux-gnu.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc64-unknown-linux-gnu.abi similarity index 87% rename from test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64-unknown-linux-gnu.abi rename to test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc64-unknown-linux-gnu.abi index 4ca3102ef1..1d97902bc5 100644 --- a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64-unknown-linux-gnu.abi +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc64-unknown-linux-gnu.abi @@ -4,9 +4,7 @@ - - - + @@ -95,7 +93,7 @@ - + @@ -788,21 +786,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -824,13 +822,13 @@ - + - + @@ -902,81 +900,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -990,13 +979,13 @@ - + - + @@ -1005,231 +994,192 @@ - + - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - + + + + - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + + + + + + - - - + + + @@ -1240,64 +1190,64 @@ - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -1327,10 +1277,10 @@ - - + + - + @@ -1339,38 +1289,38 @@ - + - + - + - + - + - + - + - + @@ -1379,20 +1329,20 @@ - + - - + + - - + + - - + + - + @@ -1427,13 +1377,13 @@ - - + + - + @@ -1493,10 +1443,10 @@ - + - + @@ -1517,16 +1467,16 @@ - + - + - + - + @@ -1541,7 +1491,7 @@ - + @@ -1552,208 +1502,204 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + - - + + - - - + + + - + - + - + - - + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + @@ -1772,16 +1718,16 @@ - - + + - - + + - - - - + + + + @@ -1791,13 +1737,13 @@ - + - + @@ -1813,9 +1759,9 @@ - + - + @@ -1878,44 +1824,44 @@ - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1925,10 +1871,10 @@ - + - + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64le-unknown-linux-gnu.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc64le-unknown-linux-gnu.abi similarity index 87% rename from test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64le-unknown-linux-gnu.abi rename to test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc64le-unknown-linux-gnu.abi index 2862e2a5b6..613f5f2f6d 100644 --- a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-powerpc64le-unknown-linux-gnu.abi +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-powerpc64le-unknown-linux-gnu.abi @@ -4,9 +4,7 @@ - - - + @@ -95,7 +93,7 @@ - + @@ -788,21 +786,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -824,13 +822,13 @@ - + - + @@ -894,81 +892,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -982,13 +971,13 @@ - + - + @@ -997,231 +986,192 @@ - + - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - + + + + - + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + + + + + + - - - + + + @@ -1232,64 +1182,64 @@ - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -1319,10 +1269,10 @@ - - + + - + @@ -1331,38 +1281,38 @@ - + - + - + - + - + - + - + - + @@ -1371,20 +1321,20 @@ - + - - + + - - + + - - + + - + @@ -1419,13 +1369,13 @@ - - + + - + @@ -1485,10 +1435,10 @@ - + - + @@ -1509,16 +1459,16 @@ - + - + - + - + @@ -1533,7 +1483,7 @@ - + @@ -1544,208 +1494,204 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + - - + + - - - + + + - + - + - + - - + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + @@ -1764,16 +1710,16 @@ - - + + - - + + - - - - + + + + @@ -1783,13 +1729,13 @@ - + - + @@ -1805,9 +1751,9 @@ - + - + @@ -1870,44 +1816,44 @@ - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -1917,10 +1863,10 @@ - + - + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-x86_64-pc-linux-gnu-m32.abi similarity index 87% rename from test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi rename to test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-x86_64-pc-linux-gnu-m32.abi index aac9172f54..82d8943b8b 100644 --- a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu-m32.abi +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-x86_64-pc-linux-gnu-m32.abi @@ -4,7 +4,7 @@ - + @@ -93,7 +93,7 @@ - + @@ -428,7 +428,7 @@ - + @@ -776,21 +776,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -812,13 +812,13 @@ - + - + @@ -882,81 +882,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -1023,25 +1014,25 @@ - + - + - + - + @@ -1053,298 +1044,245 @@ - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - + - - - - - + + - + - - - - - - - - + + + + - - - - - + + + + - - - - - + + + + - - - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + + + + + + - - - + + + @@ -1355,64 +1293,64 @@ - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -1442,10 +1380,10 @@ - - + + - + @@ -1454,38 +1392,38 @@ - + - + - + - + - + - + - + - + @@ -1494,20 +1432,20 @@ - + - - + + - - + + - - + + - + @@ -1542,13 +1480,13 @@ - - + + - + @@ -1608,10 +1546,10 @@ - + - + @@ -1632,16 +1570,16 @@ - + - + - + - + @@ -1656,7 +1594,7 @@ - + @@ -1667,209 +1605,205 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + - - + + - - - + + + - + - + - + - - - + + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + @@ -1888,16 +1822,16 @@ - - + + - - + + - - - - + + + + @@ -1907,40 +1841,62 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - - - + + + + - + - - - - + + + + @@ -1948,9 +1904,9 @@ - + - + @@ -2013,44 +1969,44 @@ - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - + @@ -2060,7 +2016,7 @@ - + diff --git a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-x86_64-pc-linux-gnu.abi similarity index 87% rename from test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi rename to test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-x86_64-pc-linux-gnu.abi index 12e224dbc3..a03df554af 100644 --- a/test/abi/zlib-ng-1ab443812aceab6c80ccd573ecdd06f73a84eef4-x86_64-pc-linux-gnu.abi +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-x86_64-pc-linux-gnu.abi @@ -4,7 +4,7 @@ - + @@ -93,7 +93,7 @@ - + @@ -435,7 +435,7 @@ - + @@ -788,21 +788,21 @@ - - - + + + - - - - + + + + - - - - + + + + @@ -824,13 +824,13 @@ - + - + @@ -894,81 +894,72 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -1035,25 +1026,25 @@ - + - + - + - + @@ -1065,298 +1056,245 @@ - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - + - - - - - + + - + - - - - - - - - + + + + - - - - - + + + + - - - - - + + + + - - - - - - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - + - + - + - - - - - - - - - - - - - - - - - - - + - - + + - - + + - + + + + + + - - - + + + @@ -1367,64 +1305,64 @@ - - + + - + - + - + - + - + - + - + - + - + - - + + - + - + - + @@ -1454,7 +1392,7 @@ - + @@ -1468,9 +1406,9 @@ - + - + @@ -1479,38 +1417,38 @@ - + - + - + - + - + - + - + - + @@ -1519,20 +1457,20 @@ - + - - + + - - + + - - + + - + @@ -1567,13 +1505,13 @@ - - + + - + @@ -1633,10 +1571,10 @@ - + - + @@ -1657,16 +1595,16 @@ - + - + - + - + @@ -1681,7 +1619,7 @@ - + @@ -1692,208 +1630,204 @@ - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - + - - + + - - - + + + - + - + - + - - + + - - + + - - - + + + - - - + + + - - + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - + + + + + + + + @@ -1912,16 +1846,16 @@ - - + + - - + + - - - - + + + + @@ -1931,41 +1865,63 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - - - + + + + - + - - - - + + + + @@ -1973,9 +1929,9 @@ - + - + @@ -2038,50 +1994,50 @@ - - - - - - - - + + + + + + + + - - - - - + + + + + - - + + - - - + + + - - - - + + + + - - + + - + - + @@ -2102,7 +2058,7 @@ - + diff --git a/test/abicheck.sh b/test/abicheck.sh index 96cb50722d..1656711f62 100755 --- a/test/abicheck.sh +++ b/test/abicheck.sh @@ -73,7 +73,7 @@ then else # Reference is most recent zlib-ng develop with zlib 1.2.12 compatible api. ABI_GIT_REPO=https://github.com/zlib-ng/zlib-ng.git - ABI_GIT_COMMIT=1ab443812aceab6c80ccd573ecdd06f73a84eef4 + ABI_GIT_COMMIT=e4614ebcb9b3e5b108dc983c155e4baf80882311 fi # Test compat build for ABI compatibility with zlib From f2cfc4ed21f2b8d56d476c1e8c7fc77e86f6706e Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Fri, 10 Feb 2023 13:41:07 +0100 Subject: [PATCH 601/798] Fix warnings in benchmarks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Initialize len in benchmark_compare256.cc. In function ‘typename std::enable_if<(std::is_trivially_copyable<_Tp>::value && (sizeof (Tp) <= sizeof (Tp*)))>::type benchmark::DoNotOptimize(Tp&) [with Tp = unsigned int]’, inlined from ‘void compare256::Bench(benchmark::State&, compare256_func)’ at /zlib-ng/test/benchmarks/benchmark_compare256.cc:44:33, inlined from ‘virtual void compare256_c_Benchmark::BenchmarkCase(benchmark::State&)’ at /zlib-ng/test/benchmarks/benchmark_compare256.cc:62:1: /zlib-ng/_deps/benchmark-src/include/benchmark/benchmark.h:480:3: warning: ‘len’ may be used uninitialized [-Wmaybe-uninitialized] 480 | asm volatile("" : "+m,r"(value) : : "memory"); | ^~~ /zlib-ng/test/benchmarks/benchmark_compare256.cc: In member function ‘virtual void compare256_c_Benchmark::BenchmarkCase(benchmark::State&)’: /zlib-ng/test/benchmarks/benchmark_compare256.cc:36:18: note: ‘len’ was declared here 36 | uint32_t len; | ^~~ 2. Make the loop counter unsigned in benchmark_slidehash.cc. /zlib-ng/test/benchmarks/benchmark_slidehash.cc: In member function ‘virtual void slide_hash::SetUp(const benchmark::State&)’: /zlib-ng/test/benchmarks/benchmark_slidehash.cc:29:31: warning: comparison of integer expressions of different signedness: ‘int32_t’ {aka ‘int’} and ‘unsigned int’ [-Wsign-compare] 29 | for (int32_t i = 0; i < HASH_SIZE; i++) { --- test/benchmarks/benchmark_compare256.cc | 2 +- test/benchmarks/benchmark_slidehash.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 54459dad06..54f6b14b84 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -33,7 +33,7 @@ class compare256: public benchmark::Fixture { void Bench(benchmark::State& state, compare256_func compare256) { int32_t match_len = (int32_t)state.range(0) - 1; - uint32_t len; + uint32_t len = 0; str2[match_len] = 0; for (auto _ : state) { diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index 655820e0cd..4ec87b6d85 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -26,7 +26,7 @@ class slide_hash: public benchmark::Fixture { void SetUp(const ::benchmark::State& state) { l0 = (uint16_t *)zng_alloc(HASH_SIZE * sizeof(uint16_t)); - for (int32_t i = 0; i < HASH_SIZE; i++) { + for (uint32_t i = 0; i < HASH_SIZE; i++) { l0[i] = rand(); } From 423ed2ffce6ca2a4f00de1163886c6802c3cb0ff Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Fri, 10 Feb 2023 12:06:59 +0200 Subject: [PATCH 602/798] [minigzip] Close gzFile before exiting on error. --- test/minigzip.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/test/minigzip.c b/test/minigzip.c index 34fc664309..d55f5086be 100644 --- a/test/minigzip.c +++ b/test/minigzip.c @@ -61,6 +61,7 @@ extern int unlink (const char *); static char *prog; void error (const char *msg); +void gz_fatal (gzFile file); void gz_compress (FILE *in, gzFile out); #ifdef USE_MMAP int gz_compress_mmap (FILE *in, gzFile out); @@ -78,6 +79,17 @@ void error(const char *msg) { exit(1); } +/* =========================================================================== + * Display last error message of gzFile, close it and exit + */ + +void gz_fatal(gzFile file) { + int err; + fprintf(stderr, "%s: %s\n", prog, PREFIX(gzerror)(file, &err)); + PREFIX(gzclose)(file); + exit(1); +} + /* =========================================================================== * Compress input to output then close both files. */ @@ -85,7 +97,6 @@ void error(const char *msg) { void gz_compress(FILE *in, gzFile out) { char *buf; int len; - int err; #ifdef USE_MMAP /* Try first compressing with mmap. If mmap fails (minigzip used in a @@ -108,7 +119,7 @@ void gz_compress(FILE *in, gzFile out) { } if (len == 0) break; - if (PREFIX(gzwrite)(out, buf, (unsigned)len) != len) error(PREFIX(gzerror)(out, &err)); + if (PREFIX(gzwrite)(out, buf, (unsigned)len) != len) gz_fatal(out); } free(buf); fclose(in); @@ -122,7 +133,6 @@ void gz_compress(FILE *in, gzFile out) { */ int gz_compress_mmap(FILE *in, gzFile out) { int len; - int err; int ifd = fileno(in); char *buf; /* mmap'ed buffer for the entire input file */ off_t buf_len; /* length of the input file */ @@ -140,7 +150,7 @@ int gz_compress_mmap(FILE *in, gzFile out) { /* Compress the whole file at once: */ len = PREFIX(gzwrite)(out, buf, (unsigned)buf_len); - if (len != (int)buf_len) error(PREFIX(gzerror)(out, &err)); + if (len != (int)buf_len) gz_fatal(out); munmap(buf, buf_len); fclose(in); @@ -155,7 +165,6 @@ int gz_compress_mmap(FILE *in, gzFile out) { void gz_uncompress(gzFile in, FILE *out) { char *buf = (char *)malloc(BUFLENW); int len; - int err; if (buf == NULL) error("out of memory"); @@ -163,7 +172,7 @@ void gz_uncompress(gzFile in, FILE *out) { len = PREFIX(gzread)(in, buf, BUFLENW); if (len < 0) { free(buf); - error(PREFIX(gzerror)(in, &err)); + gz_fatal(in); } if (len == 0) break; From d191cee37220a6972299ea3551de70593e2f16d9 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 9 Feb 2023 12:04:09 +0100 Subject: [PATCH 603/798] Narrow down the amount of packages installed for Wine. --- .github/workflows/cmake.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index b0cde4246f..b4b5897fd6 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -276,7 +276,7 @@ jobs: - name: Ubuntu MinGW i686 os: ubuntu-22.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake - packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.39-3ubuntu0.1 libpcre2-8-0:i386=10.39-3ubuntu0.1 libodbc1=2.3.9-5 libodbc1:i386=2.3.9-5 libwine:i386=6.0.3~repack-1 libgphoto2-6:i386=2.5.27-1build2 libsane:i386=1.1.1-5 libgd3=2.3.0-2ubuntu2 libgd3:i386=2.3.0-2ubuntu2 + packages: wine wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.39-3ubuntu0.1 libpcre2-8-0:i386=10.39-3ubuntu0.1 libodbc1=2.3.9-5 libodbc1:i386=2.3.9-5 libwine:i386=6.0.3~repack-1 libgphoto2-6:i386=2.5.27-1build2 libsane:i386=1.1.1-5 libgd3=2.3.0-2ubuntu2 libgd3:i386=2.3.0-2ubuntu2 ldflags: -static codecov: ubuntu_gcc_mingw_i686 # Limit parallel test jobs to prevent wine errors @@ -285,7 +285,7 @@ jobs: - name: Ubuntu MinGW x86_64 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-x86_64.cmake - packages: wine-stable gcc-mingw-w64 g++-mingw-w64 + packages: wine wine64 gcc-mingw-w64 g++-mingw-w64 ldflags: -static codecov: ubuntu_gcc_mingw_x86_64 # Limit parallel test jobs to prevent wine errors @@ -485,7 +485,7 @@ jobs: path: test/data/corpora - name: Add repositories (Wine) - if: contains(matrix.packages, 'wine') + if: contains(matrix.packages, 'wine32') run: sudo dpkg --add-architecture i386 - name: Add ubuntu mirrors @@ -500,7 +500,7 @@ jobs: if: runner.os == 'Linux' && matrix.packages run: | sudo apt-get update - sudo apt-get install -y --allow-downgrades ${{ matrix.packages }} + sudo apt-get install -y --allow-downgrades --no-install-recommends ${{ matrix.packages }} - name: Install packages (Windows) if: runner.os == 'Windows' From c8a6b3ed6b5080a41223a3db9dc2f62fdfa3a48f Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 6 Feb 2023 12:29:41 +0100 Subject: [PATCH 604/798] Simplify functable.c --- functable.c | 389 ++++++++++++++++++++-------------------------------- 1 file changed, 149 insertions(+), 240 deletions(-) diff --git a/functable.c b/functable.c index 7ecc43fa31..6d30585d65 100644 --- a/functable.c +++ b/functable.c @@ -16,310 +16,219 @@ static void init_functable(void) { cpu_check_features(); - // update_hash_stub: + // Generic code ft.update_hash = &update_hash_c; -#ifdef X86_SSE42_CRC_HASH - if (x86_cpu_has_sse42) - ft.update_hash = &update_hash_sse4; -#elif defined(ARM_ACLE_CRC_HASH) - if (arm_cpu_has_crc32) - ft.update_hash = &update_hash_acle; -#endif - - // insert_string_stub: ft.insert_string = &insert_string_c; -#ifdef X86_SSE42_CRC_HASH - if (x86_cpu_has_sse42) - ft.insert_string = &insert_string_sse4; -#elif defined(ARM_ACLE_CRC_HASH) - if (arm_cpu_has_crc32) - ft.insert_string = &insert_string_acle; -#endif - - // quick_insert_string_stub: ft.quick_insert_string = &quick_insert_string_c; -#ifdef X86_SSE42_CRC_HASH - if (x86_cpu_has_sse42) - ft.quick_insert_string = &quick_insert_string_sse4; -#elif defined(ARM_ACLE_CRC_HASH) - if (arm_cpu_has_crc32) - ft.quick_insert_string = &quick_insert_string_acle; -#endif - - // slide_hash_stub: ft.slide_hash = &slide_hash_c; -#ifdef X86_SSE2 -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - ft.slide_hash = &slide_hash_sse2; -#elif defined(ARM_NEON_SLIDEHASH) -# ifndef ARM_NOCHECK_NEON - if (arm_cpu_has_neon) -# endif - ft.slide_hash = &slide_hash_neon; -#endif -#ifdef X86_AVX2 - if (x86_cpu_has_avx2) - ft.slide_hash = &slide_hash_avx2; -#endif -#ifdef PPC_VMX_SLIDEHASH - if (power_cpu_has_altivec) - ft.slide_hash = &slide_hash_vmx; -#endif -#ifdef POWER8_VSX_SLIDEHASH - if (power_cpu_has_arch_2_07) - ft.slide_hash = &slide_hash_power8; -#endif + ft.adler32 = &adler32_c; + ft.chunksize = &chunksize_c; + ft.chunkmemset_safe = &chunkmemset_safe_c; + ft.inflate_fast = &inflate_fast_c; + ft.adler32_fold_copy = &adler32_fold_copy_c; + ft.crc32_fold = &crc32_fold_c; + ft.crc32_fold_reset = &crc32_fold_reset_c; + ft.crc32_fold_copy = &crc32_fold_copy_c; + ft.crc32_fold_final = &crc32_fold_final_c; + ft.crc32 = &PREFIX(crc32_braid); - // longest_match_stub: #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) ft.longest_match = &longest_match_unaligned_64; + ft.longest_match_slow = &longest_match_slow_unaligned_64; + ft.compare256 = &compare256_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) ft.longest_match = &longest_match_unaligned_32; + ft.longest_match_slow = &longest_match_slow_unaligned_32; + ft.compare256 = &compare256_unaligned_32; # else ft.longest_match = &longest_match_unaligned_16; + ft.longest_match_slow = &longest_match_slow_unaligned_16; + ft.compare256 = &compare256_unaligned_16; # endif #else ft.longest_match = &longest_match_c; -#endif -#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_sse2) - ft.longest_match = &longest_match_sse2; -#endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - ft.longest_match = &longest_match_avx2; -#endif -#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) - if (arm_cpu_has_neon) - ft.longest_match = &longest_match_neon; -#endif -#ifdef POWER9 - if (power_cpu_has_arch_3_00) - ft.longest_match = &longest_match_power9; + ft.longest_match_slow = &longest_match_slow_c; + ft.compare256 = &compare256_c; #endif - // longest_match_slow_stub: -#ifdef UNALIGNED_OK -# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - ft.longest_match_slow = &longest_match_slow_unaligned_64; -# elif defined(HAVE_BUILTIN_CTZ) - ft.longest_match_slow = &longest_match_slow_unaligned_32; -# else - ft.longest_match_slow = &longest_match_slow_unaligned_16; + + // Select arch-optimized functions + + // X86 - SSE2 +#ifdef X86_SSE2 +# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) + if (x86_cpu_has_sse2) # endif -#else - ft.longest_match_slow = &longest_match_slow_c; + ft.slide_hash = &slide_hash_sse2; #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_sse2) + if (x86_cpu_has_sse2) { + ft.longest_match = &longest_match_sse2; ft.longest_match_slow = &longest_match_slow_sse2; + ft.compare256 = &compare256_sse2; + } #endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - ft.longest_match_slow = &longest_match_slow_avx2; -#endif -#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) - if (arm_cpu_has_neon) - ft.longest_match_slow = &longest_match_slow_neon; -#endif -#ifdef POWER9 - if (power_cpu_has_arch_3_00) - ft.longest_match_slow = &longest_match_slow_power9; -#endif - - // adler32_stub: - ft.adler32 = &adler32_c; -#ifdef ARM_NEON_ADLER32 -# ifndef ARM_NOCHECK_NEON - if (arm_cpu_has_neon) -# endif - ft.adler32 = &adler32_neon; +#ifdef X86_SSE2_CHUNKSET +# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) + if (x86_cpu_has_sse2) +# endif + { + ft.chunksize = &chunksize_sse2; + ft.chunkmemset_safe = &chunkmemset_safe_sse2; + ft.inflate_fast = &inflate_fast_sse2; + } #endif + // X86 - SSSE3 #ifdef X86_SSSE3_ADLER32 if (x86_cpu_has_ssse3) ft.adler32 = &adler32_ssse3; #endif -#ifdef X86_AVX2_ADLER32 - if (x86_cpu_has_avx2) - ft.adler32 = &adler32_avx2; + // X86 - SSE4 +#if defined(X86_SSE41) && defined(X86_SSE2) + if (x86_cpu_has_sse41) { + ft.chunkmemset_safe = &chunkmemset_safe_sse41; + ft.inflate_fast = &inflate_fast_sse41; + } #endif -#ifdef X86_AVX512_ADLER32 - if (x86_cpu_has_avx512) - ft.adler32 = &adler32_avx512; +#ifdef X86_SSE42_ADLER32 + if (x86_cpu_has_sse42) + ft.adler32_fold_copy = &adler32_fold_copy_sse42; #endif -#ifdef X86_AVX512VNNI_ADLER32 - if (x86_cpu_has_avx512vnni) - ft.adler32 = &adler32_avx512_vnni; +#ifdef X86_SSE42_CRC_HASH + if (x86_cpu_has_sse42) { + ft.update_hash = &update_hash_sse4; + ft.insert_string = &insert_string_sse4; + ft.quick_insert_string = &quick_insert_string_sse4; + } #endif -#ifdef PPC_VMX_ADLER32 - if (power_cpu_has_altivec) - ft.adler32 = &adler32_vmx; + // X86 - PCLMUL +#ifdef X86_PCLMULQDQ_CRC + if (x86_cpu_has_pclmulqdq) { + ft.crc32 = &crc32_pclmulqdq; + ft.crc32_fold = &crc32_fold_pclmulqdq; + ft.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; + ft.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; + ft.crc32_fold_final = &crc32_fold_pclmulqdq_final; + } #endif -#ifdef POWER8_VSX_ADLER32 - if (power_cpu_has_arch_2_07) - ft.adler32 = &adler32_power8; + // X86 - AVX +#ifdef X86_AVX_CHUNKSET + if (x86_cpu_has_avx2) { + ft.chunksize = &chunksize_avx; + ft.chunkmemset_safe = &chunkmemset_safe_avx; + ft.inflate_fast = &inflate_fast_avx; + } #endif - - // adler32_fold_copy_stub: - ft.adler32_fold_copy = &adler32_fold_copy_c; -#ifdef X86_SSE42_ADLER32 - if (x86_cpu_has_sse42) - ft.adler32_fold_copy = &adler32_fold_copy_sse42; +#ifdef X86_AVX2 + if (x86_cpu_has_avx2) + ft.slide_hash = &slide_hash_avx2; +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_avx2) { + ft.longest_match = &longest_match_avx2; + ft.longest_match_slow = &longest_match_slow_avx2; + ft.compare256 = &compare256_avx2; + } #endif #ifdef X86_AVX2_ADLER32 - if (x86_cpu_has_avx2) + if (x86_cpu_has_avx2) { + ft.adler32 = &adler32_avx2; ft.adler32_fold_copy = &adler32_fold_copy_avx2; + } #endif #ifdef X86_AVX512_ADLER32 - if (x86_cpu_has_avx512) + if (x86_cpu_has_avx512) { + ft.adler32 = &adler32_avx512; ft.adler32_fold_copy = &adler32_fold_copy_avx512; + } #endif #ifdef X86_AVX512VNNI_ADLER32 - if (x86_cpu_has_avx512vnni) + if (x86_cpu_has_avx512vnni) { + ft.adler32 = &adler32_avx512_vnni; ft.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; + } #endif - // crc32_fold_reset_stub: - ft.crc32_fold_reset = &crc32_fold_reset_c; -#ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) - ft.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; -#endif - - // crc32_fold_copy_stub: - ft.crc32_fold_copy = &crc32_fold_copy_c; -#ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) - ft.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; -#endif - - // crc32_fold_stub: - ft.crc32_fold = &crc32_fold_c; -#ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) - ft.crc32_fold = &crc32_fold_pclmulqdq; -#endif - // crc32_fold_final_stub: - ft.crc32_fold_final = &crc32_fold_final_c; -#ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) - ft.crc32_fold_final = &crc32_fold_pclmulqdq_final; -#endif - - //chunksize_stub: - ft.chunksize = &chunksize_c; -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - ft.chunksize = &chunksize_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - ft.chunksize = &chunksize_avx; + // ARM - NEON +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) + if (arm_cpu_has_neon) { + ft.longest_match = &longest_match_neon; + ft.longest_match_slow = &longest_match_slow_neon; + } #endif -#ifdef ARM_NEON_CHUNKSET +#ifdef ARM_NEON_ADLER32 +# ifndef ARM_NOCHECK_NEON if (arm_cpu_has_neon) - ft.chunksize = &chunksize_neon; -#endif -#ifdef POWER8_VSX_CHUNKSET - if (power_cpu_has_arch_2_07) - ft.chunksize = &chunksize_power8; -#endif - - // chunkmemset_safe_stub: - ft.chunkmemset_safe = &chunkmemset_safe_c; -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - ft.chunkmemset_safe = &chunkmemset_safe_sse2; -#endif -#if defined(X86_SSE41) && defined(X86_SSE2) - if (x86_cpu_has_sse41) - ft.chunkmemset_safe = &chunkmemset_safe_sse41; +# endif + ft.adler32 = &adler32_neon; #endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - ft.chunkmemset_safe = &chunkmemset_safe_avx; +#ifdef ARM_NEON_SLIDEHASH +# ifndef ARM_NOCHECK_NEON + if (arm_cpu_has_neon) +# endif + ft.slide_hash = &slide_hash_neon; #endif #ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) + if (arm_cpu_has_neon) { + ft.chunksize = &chunksize_neon; ft.chunkmemset_safe = &chunkmemset_safe_neon; + ft.inflate_fast = &inflate_fast_neon; + } #endif -#ifdef POWER8_VSX_CHUNKSET - if (power_cpu_has_arch_2_07) - ft.chunkmemset_safe = &chunkmemset_safe_power8; + // ARM - ACLE +#ifdef ARM_ACLE_CRC_HASH + if (arm_cpu_has_crc32) { + ft.crc32 = &crc32_acle; + ft.update_hash = &update_hash_acle; + ft.insert_string = &insert_string_acle; + ft.quick_insert_string = &quick_insert_string_acle; + } #endif - // inflate_fast_stub: - ft.inflate_fast = &inflate_fast_c; -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - ft.inflate_fast = &inflate_fast_sse2; -#endif -#if defined(X86_SSE41) && defined(X86_SSE2) - if (x86_cpu_has_sse41) - ft.inflate_fast = &inflate_fast_sse41; + // Power - VMX +#ifdef PPC_VMX_SLIDEHASH + if (power_cpu_has_altivec) + ft.slide_hash = &slide_hash_vmx; #endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - ft.inflate_fast = &inflate_fast_avx; +#ifdef PPC_VMX_ADLER32 + if (power_cpu_has_altivec) + ft.adler32 = &adler32_vmx; #endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - ft.inflate_fast = &inflate_fast_neon; + // Power8 - VSX +#ifdef POWER8_VSX_SLIDEHASH + if (power_cpu_has_arch_2_07) + ft.slide_hash = &slide_hash_power8; #endif -#ifdef POWER8_VSX_CHUNKSET +#ifdef POWER8_VSX_ADLER32 if (power_cpu_has_arch_2_07) - ft.inflate_fast = &inflate_fast_power8; + ft.adler32 = &adler32_power8; #endif - - // crc32_stub: - ft.crc32 = &PREFIX(crc32_braid); -#ifdef ARM_ACLE_CRC_HASH - if (arm_cpu_has_crc32) - ft.crc32 = &crc32_acle; -#elif defined(POWER8_VSX_CRC32) +#ifdef POWER8_VSX_CRC32 if (power_cpu_has_arch_2_07) ft.crc32 = &crc32_power8; -#elif defined(S390_CRC32_VX) - if (PREFIX(s390_cpu_has_vx)) - ft.crc32 = &PREFIX(s390_crc32_vx); -#elif defined(X86_PCLMULQDQ_CRC) - if (x86_cpu_has_pclmulqdq) - ft.crc32 = &crc32_pclmulqdq; #endif - - // compare256_stub: -#ifdef UNALIGNED_OK -# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - ft.compare256 = &compare256_unaligned_64; -# elif defined(HAVE_BUILTIN_CTZ) - ft.compare256 = &compare256_unaligned_32; -# else - ft.compare256 = &compare256_unaligned_16; -# endif -#else - ft.compare256 = &compare256_c; -#endif -#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_sse2) - ft.compare256 = &compare256_sse2; -#endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - ft.compare256 = &compare256_avx2; +#ifdef POWER8_VSX_CHUNKSET + if (power_cpu_has_arch_2_07) { + ft.chunksize = &chunksize_power8; + ft.chunkmemset_safe = &chunkmemset_safe_power8; + ft.inflate_fast = &inflate_fast_power8; + } #endif + // Power9 #ifdef POWER9 - if (power_cpu_has_arch_3_00) + if (power_cpu_has_arch_3_00) { + ft.longest_match = &longest_match_power9; + ft.longest_match_slow = &longest_match_slow_power9; ft.compare256 = &compare256_power9; + } +#endif + + // S390 +#ifdef S390_CRC32_VX + if (PREFIX(s390_cpu_has_vx)) + ft.crc32 = &PREFIX(s390_crc32_vx); #endif // Assign function pointers individually for atomic operation From 5d9ddac4cdb8b47f7e1cf5ff016d4f5609c94c02 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 6 Feb 2023 12:40:13 +0100 Subject: [PATCH 605/798] Combine some of the checks that were not identical. Made longest_match and compare256 use the X86_NOCHECK_SSE2 override, thus now those are also automatically enabled on x86_64. --- functable.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/functable.c b/functable.c index 6d30585d65..3eef010b86 100644 --- a/functable.c +++ b/functable.c @@ -56,27 +56,24 @@ static void init_functable(void) { // Select arch-optimized functions // X86 - SSE2 -#ifdef X86_SSE2 +#if defined(X86_SSE2) || defined(X86_SSE2_CHUNKSET) # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif + { +# ifdef X86_SSE2 ft.slide_hash = &slide_hash_sse2; -#endif -#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_sse2) { +# ifdef HAVE_BUILTIN_CTZ ft.longest_match = &longest_match_sse2; ft.longest_match_slow = &longest_match_slow_sse2; ft.compare256 = &compare256_sse2; - } -#endif -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - { +# endif +# endif +# ifdef X86_SSE2_CHUNKSET ft.chunksize = &chunksize_sse2; ft.chunkmemset_safe = &chunkmemset_safe_sse2; ft.inflate_fast = &inflate_fast_sse2; +# endif } #endif // X86 - SSSE3 @@ -121,14 +118,13 @@ static void init_functable(void) { } #endif #ifdef X86_AVX2 - if (x86_cpu_has_avx2) - ft.slide_hash = &slide_hash_avx2; -#endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) { + ft.slide_hash = &slide_hash_avx2; +# ifdef HAVE_BUILTIN_CTZ ft.longest_match = &longest_match_avx2; ft.longest_match_slow = &longest_match_slow_avx2; ft.compare256 = &compare256_avx2; +# endif } #endif #ifdef X86_AVX2_ADLER32 From 6f714ef422ae93a0bf2fda7d63b4757f7425b24e Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 6 Feb 2023 20:05:33 +0100 Subject: [PATCH 606/798] Add missing compare256_neon activation to functable --- functable.c | 1 + 1 file changed, 1 insertion(+) diff --git a/functable.c b/functable.c index 3eef010b86..b64b4bd65a 100644 --- a/functable.c +++ b/functable.c @@ -150,6 +150,7 @@ static void init_functable(void) { // ARM - NEON #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) if (arm_cpu_has_neon) { + ft.compare256 = &compare256_neon; ft.longest_match = &longest_match_neon; ft.longest_match_slow = &longest_match_slow_neon; } From 7e1d80742e344b294cf3802e5ef13be42672b32c Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 6 Feb 2023 14:41:32 +0100 Subject: [PATCH 607/798] Reduce the amount of different defines required for arch-specific optimizations. Also removed a reference to a nonexistant adler32_sse41 in test/test_adler32.cc. --- CMakeLists.txt | 24 +++--- arch/arm/adler32_neon.c | 2 +- arch/arm/chunkset_neon.c | 2 +- arch/arm/crc32_acle.c | 2 +- arch/arm/insert_string_acle.c | 2 +- arch/arm/neon_intrins.h | 10 +-- arch/arm/slide_hash_neon.c | 2 +- arch/power/adler32_power8.c | 4 +- arch/power/adler32_vmx.c | 2 +- arch/power/chunkset_power8.c | 2 +- arch/power/slide_hash_power8.c | 4 +- arch/power/slide_hash_vmx.c | 4 +- arch/x86/adler32_avx2.c | 2 +- arch/x86/adler32_avx2_p.h | 2 +- arch/x86/adler32_avx2_tpl.h | 2 +- arch/x86/adler32_avx512.c | 2 +- arch/x86/adler32_avx512_tpl.h | 6 +- arch/x86/adler32_avx512_vnni.c | 10 +-- arch/x86/adler32_sse42.c | 2 +- arch/x86/adler32_ssse3.c | 2 +- arch/x86/adler32_ssse3_p.h | 2 +- arch/x86/chunkset_avx.c | 2 +- arch/x86/insert_string_sse42.c | 2 +- configure | 53 +++++------- cpu_features.h | 60 +++++++------- functable.c | 98 ++++++++--------------- test/benchmarks/benchmark_adler32.cc | 14 ++-- test/benchmarks/benchmark_adler32_copy.cc | 14 ++-- test/benchmarks/benchmark_crc32.cc | 4 +- test/benchmarks/benchmark_slidehash.cc | 6 +- test/test_adler32.cc | 17 ++-- test/test_crc32.cc | 2 +- win32/Makefile.a64 | 5 +- win32/Makefile.arm | 5 +- win32/Makefile.msc | 10 +-- 35 files changed, 163 insertions(+), 219 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8aad597f98..df5cc03e9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -616,7 +616,7 @@ if(WITH_OPTIM) if(WITH_ACLE AND NOT "${ARCH}" MATCHES "armv[2-7]") check_acle_compiler_flag() if(HAVE_ACLE_FLAG) - add_definitions(-DARM_ACLE_CRC_HASH) + add_definitions(-DARM_ACLE) set(ACLE_SRCS ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c) set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG} ${NOLTOFLAG}") list(APPEND ZLIB_ARCH_SRCS ${ACLE_SRCS}) @@ -630,7 +630,7 @@ if(WITH_OPTIM) if(WITH_NEON) check_neon_compiler_flag() if(MFPU_NEON_AVAILABLE) - add_definitions(-DARM_NEON -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) + add_definitions(-DARM_NEON) set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/compare256_neon.c ${ARCHDIR}/slide_hash_neon.c) list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) @@ -668,8 +668,7 @@ if(WITH_OPTIM) if(HAVE_VMX) add_definitions(-DPPC_FEATURES) if(HAVE_ALTIVEC) - add_definitions(-DPPC_VMX_ADLER32) - add_definitions(-DPPC_VMX_SLIDEHASH) + add_definitions(-DPPC_VMX) set(PPC_SRCS ${ARCHDIR}/adler32_vmx.c ${ARCHDIR}/slide_hash_vmx.c) list(APPEND ZLIB_ARCH_SRCS ${PPC_SRCS}) add_feature_info(ALTIVEC 1 "Support the AltiVec instruction set, using \"-maltivec\"") @@ -682,11 +681,8 @@ if(WITH_OPTIM) # Power8 specific options and files if(WITH_POWER8) if(HAVE_POWER8_INTRIN) - add_definitions(-DPOWER8) + add_definitions(-DPOWER8_VSX) add_definitions(-DPOWER_FEATURES) - add_definitions(-DPOWER8_VSX_ADLER32) - add_definitions(-DPOWER8_VSX_CHUNKSET) - add_definitions(-DPOWER8_VSX_SLIDEHASH) set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/chunkset_power8.c ${ARCHDIR}/slide_hash_power8.c) if("${ARCH}" MATCHES "powerpc64(le)?") add_definitions(-DPOWER8_VSX_CRC32) @@ -748,7 +744,7 @@ if(WITH_OPTIM) if(WITH_AVX2) check_avx2_intrinsics() if(HAVE_AVX2_INTRIN) - add_definitions(-DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET) + add_definitions(-DX86_AVX2) set(AVX2_SRCS ${ARCHDIR}/slide_hash_avx2.c) add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx.c) @@ -766,7 +762,7 @@ if(WITH_OPTIM) if(WITH_AVX512) check_avx512_intrinsics() if(HAVE_AVX512_INTRIN) - add_definitions(-DX86_AVX512 -DX86_AVX512_ADLER32) + add_definitions(-DX86_AVX512) list(APPEND AVX512_SRCS ${ARCHDIR}/adler32_avx512.c) add_feature_info(AVX512_ADLER32 1 "Support AVX512-accelerated adler32, using \"${AVX512FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${AVX512_SRCS}) @@ -782,7 +778,7 @@ if(WITH_OPTIM) if(WITH_AVX512VNNI) check_avx512vnni_intrinsics() if(HAVE_AVX512VNNI_INTRIN) - add_definitions(-DX86_AVX512VNNI -DX86_AVX512VNNI_ADLER32) + add_definitions(-DX86_AVX512VNNI) add_feature_info(AVX512VNNI_ADLER32 1 "Support AVX512VNNI adler32, using \"${AVX512VNNIFLAG}\"") list(APPEND AVX512VNNI_SRCS ${ARCHDIR}/adler32_avx512_vnni.c) list(APPEND ZLIB_ARCH_SRCS ${AVX512VNNI_SRCS}) @@ -805,7 +801,7 @@ if(WITH_OPTIM) if(WITH_SSE42) check_sse42_intrinsics() if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) - add_definitions(-DX86_SSE42_CRC_HASH -DX86_SSE42_ADLER32) + add_definitions(-DX86_SSE42) set(SSE42_SRCS ${ARCHDIR}/adler32_sse42.c ${ARCHDIR}/insert_string_sse42.c) add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE42FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) @@ -821,7 +817,7 @@ if(WITH_OPTIM) if(WITH_SSE2) check_sse2_intrinsics() if(HAVE_SSE2_INTRIN) - add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) + add_definitions(-DX86_SSE2) set(SSE2_SRCS ${ARCHDIR}/chunkset_sse2.c ${ARCHDIR}/compare256_sse2.c ${ARCHDIR}/slide_hash_sse2.c) list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) if(NOT ${ARCH} MATCHES "x86_64") @@ -838,7 +834,7 @@ if(WITH_OPTIM) if(WITH_SSSE3) check_ssse3_intrinsics() if(HAVE_SSSE3_INTRIN) - add_definitions(-DX86_SSSE3 -DX86_SSSE3_ADLER32) + add_definitions(-DX86_SSSE3) set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c) add_feature_info(SSSE3_ADLER32 1 "Support SSSE3-accelerated adler32, using \"${SSSE3FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index 7f898d18a7..f1c43ff047 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -5,7 +5,7 @@ * Adam Stylinski * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef ARM_NEON_ADLER32 +#ifdef ARM_NEON #include "neon_intrins.h" #include "../../zbuild.h" #include "../../adler32_p.h" diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index b119f21245..668c0019e9 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -2,7 +2,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef ARM_NEON_CHUNKSET +#ifdef ARM_NEON #include "neon_intrins.h" #include "../../zbuild.h" #include "../generic/chunk_permute_table.h" diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index 445c370aa8..a4e54d7182 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -5,7 +5,7 @@ * */ -#ifdef ARM_ACLE_CRC_HASH +#ifdef ARM_ACLE #ifdef _MSC_VER # include #else diff --git a/arch/arm/insert_string_acle.c b/arch/arm/insert_string_acle.c index de99023844..9ac3ccb42f 100644 --- a/arch/arm/insert_string_acle.c +++ b/arch/arm/insert_string_acle.c @@ -5,7 +5,7 @@ * */ -#ifdef ARM_ACLE_CRC_HASH +#ifdef ARM_ACLE #ifndef _MSC_VER # include #endif diff --git a/arch/arm/neon_intrins.h b/arch/arm/neon_intrins.h index 06e310c9f9..d6b57f6414 100644 --- a/arch/arm/neon_intrins.h +++ b/arch/arm/neon_intrins.h @@ -7,7 +7,7 @@ # include #endif -#if defined(ARM_NEON_ADLER32) && !defined(__aarch64__) && !defined(_M_ARM64) +#if defined(ARM_NEON) && !defined(__aarch64__) && !defined(_M_ARM64) /* Compatibility shim for the _high family of functions */ #define vmull_high_u8(a, b) vmull_u8(vget_high_u8(a), vget_high_u8(b)) #define vmlal_high_u8(a, b, c) vmlal_u8(a, vget_high_u8(b), vget_high_u8(c)) @@ -15,7 +15,7 @@ #define vaddw_high_u8(a, b) vaddw_u8(a, vget_high_u8(b)) #endif -#ifdef ARM_NEON_SLIDEHASH +#ifdef ARM_NEON #define vqsubq_u16_x4_x1(out, a, b) do { \ out.val[0] = vqsubq_u16(a.val[0], b); \ @@ -24,9 +24,8 @@ out.val[3] = vqsubq_u16(a.val[3], b); \ } while (0) -#endif -#if !defined(ARM_NEON_HASLD4) && (defined(ARM_NEON_ADLER32) || defined(ARM_NEON_SLIDEHASH)) +# ifndef ARM_NEON_HASLD4 static inline uint16x8x4_t vld1q_u16_x4(uint16_t const *a) { uint16x8x4_t ret = (uint16x8x4_t) {{ @@ -52,6 +51,7 @@ static inline void vst1q_u16_x4(uint16_t *p, uint16x8x4_t a) { vst1q_u16(p + 16, a.val[2]); vst1q_u16(p + 24, a.val[3]); } -#endif // HASLD4 check +# endif // HASLD4 check +#endif #endif // include guard ARM_NEON_INTRINS_H diff --git a/arch/arm/slide_hash_neon.c b/arch/arm/slide_hash_neon.c index 5bb4dc505c..a96ca11799 100644 --- a/arch/arm/slide_hash_neon.c +++ b/arch/arm/slide_hash_neon.c @@ -8,7 +8,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#if defined(ARM_NEON_SLIDEHASH) +#ifdef ARM_NEON #include "neon_intrins.h" #include "../../zbuild.h" #include "../../deflate.h" diff --git a/arch/power/adler32_power8.c b/arch/power/adler32_power8.c index 737c6f2fbc..4aaea9f50b 100644 --- a/arch/power/adler32_power8.c +++ b/arch/power/adler32_power8.c @@ -36,7 +36,7 @@ * https://www.ietf.org/rfc/rfc1950.txt */ -#ifdef POWER8_VSX_ADLER32 +#ifdef POWER8_VSX #include #include "zbuild.h" @@ -150,4 +150,4 @@ Z_INTERNAL uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t le return adler32_len_16(s1, buf, len, s2); } -#endif /* POWER8_VSX_ADLER32 */ +#endif /* POWER8_VSX */ diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index 47193286a7..ef1649b589 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -5,7 +5,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef PPC_VMX_ADLER32 +#ifdef PPC_VMX #include #include "zbuild.h" #include "adler32_p.h" diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index 389be08171..443aae92f1 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -2,7 +2,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef POWER8_VSX_CHUNKSET +#ifdef POWER8_VSX #include #include "../../zbuild.h" diff --git a/arch/power/slide_hash_power8.c b/arch/power/slide_hash_power8.c index 5b078ec9f9..d01e0acd56 100644 --- a/arch/power/slide_hash_power8.c +++ b/arch/power/slide_hash_power8.c @@ -4,9 +4,9 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef POWER8_VSX_SLIDEHASH +#ifdef POWER8_VSX #define SLIDE_PPC slide_hash_power8 #include "slide_ppc_tpl.h" -#endif /* POWER8_VSX_SLIDEHASH */ +#endif /* POWER8_VSX */ diff --git a/arch/power/slide_hash_vmx.c b/arch/power/slide_hash_vmx.c index cf9bd7b797..5a87ef7d9a 100644 --- a/arch/power/slide_hash_vmx.c +++ b/arch/power/slide_hash_vmx.c @@ -2,9 +2,9 @@ * Copyright (C) 2017-2021 Mika T. Lindqvist * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef PPC_VMX_SLIDEHASH +#ifdef PPC_VMX #define SLIDE_PPC slide_hash_vmx #include "slide_ppc_tpl.h" -#endif /* PPC_VMX_SLIDEHASH */ +#endif /* PPC_VMX */ diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index dcd1166f34..797d299e09 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -7,7 +7,7 @@ #include -#ifdef X86_AVX2_ADLER32 +#ifdef X86_AVX2 #include "adler32_avx2_tpl.h" diff --git a/arch/x86/adler32_avx2_p.h b/arch/x86/adler32_avx2_p.h index f7079bf3eb..f0f8a4a887 100644 --- a/arch/x86/adler32_avx2_p.h +++ b/arch/x86/adler32_avx2_p.h @@ -6,7 +6,7 @@ #ifndef ADLER32_AVX2_P_H_ #define ADLER32_AVX2_P_H_ -#if defined(X86_AVX2_ADLER32) || defined(X86_AVX512VNNI_ADLER32) +#if defined(X86_AVX2) || defined(X86_AVX512VNNI) /* 32 bit horizontal sum, adapted from Agner Fog's vector library. */ static inline uint32_t hsum256(__m256i x) { diff --git a/arch/x86/adler32_avx2_tpl.h b/arch/x86/adler32_avx2_tpl.h index 0b2e89be43..a94f44b4f9 100644 --- a/arch/x86/adler32_avx2_tpl.h +++ b/arch/x86/adler32_avx2_tpl.h @@ -10,7 +10,7 @@ #include "../../fallback_builtins.h" #include "adler32_avx2_p.h" -#ifdef X86_SSE42_ADLER32 +#ifdef X86_SSE42 extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len); diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index c0bf0721f2..e6ebb05dc8 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -6,7 +6,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef X86_AVX512_ADLER32 +#ifdef X86_AVX512 #include "adler32_avx512_tpl.h" diff --git a/arch/x86/adler32_avx512_tpl.h b/arch/x86/adler32_avx512_tpl.h index 6ed39b45df..7546afef5e 100644 --- a/arch/x86/adler32_avx512_tpl.h +++ b/arch/x86/adler32_avx512_tpl.h @@ -11,7 +11,7 @@ #include #include "adler32_avx512_p.h" -#ifdef X86_AVX512_ADLER32 +#ifdef X86_AVX512 #ifdef COPY Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { @@ -35,9 +35,9 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t le _mm512_mask_storeu_epi8(dst, storemask, copy_vec); #endif -#ifdef X86_AVX2_ADLER32 +#ifdef X86_AVX2 return adler32_avx2(adler, src, len); -#elif defined(X86_SSSE3_ADLER32) +#elif defined(X86_SSSE3) return adler32_ssse3(adler, src, len); #else return adler32_len_16(adler0, src, len, adler1); diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index 42a166062f..8dcc93d050 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -7,7 +7,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef X86_AVX512VNNI_ADLER32 +#ifdef X86_AVX512VNNI #include "../../zbuild.h" #include "../../adler32_p.h" @@ -28,16 +28,16 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size rem_peel: if (len < 32) -#if defined(X86_SSSE3_ADLER32) +#if defined(X86_SSSE3) return adler32_ssse3(adler, src, len); #else return adler32_len_16(adler0, src, len, adler1); #endif if (len < 64) -#ifdef X86_AVX2_ADLER32 +#ifdef X86_AVX2 return adler32_avx2(adler, src, len); -#elif defined(X86_SSE3_ADLER32) +#elif defined(X86_SSE3) return adler32_ssse3(adler, src, len); #else return adler32_len_16(adler0, src, len, adler1); @@ -135,7 +135,7 @@ Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, __m256i copy_vec = _mm256_maskz_loadu_epi8(storemask, src); _mm256_mask_storeu_epi8(dst, storemask, copy_vec); -#if defined(X86_SSSE3_ADLER32) +#if defined(X86_SSSE3) return adler32_ssse3(adler, src, len); #else return adler32_len_16(adler0, src, len, adler1); diff --git a/arch/x86/adler32_sse42.c b/arch/x86/adler32_sse42.c index ec0513409b..257a360982 100644 --- a/arch/x86/adler32_sse42.c +++ b/arch/x86/adler32_sse42.c @@ -12,7 +12,7 @@ #include "adler32_ssse3_p.h" #include -#ifdef X86_SSE42_ADLER32 +#ifdef X86_SSE42 Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { uint32_t adler0, adler1; diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 1f4abba507..99ce795823 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -10,7 +10,7 @@ #include "../../adler32_p.h" #include "adler32_ssse3_p.h" -#ifdef X86_SSSE3_ADLER32 +#ifdef X86_SSSE3 #include diff --git a/arch/x86/adler32_ssse3_p.h b/arch/x86/adler32_ssse3_p.h index 0b7ddcf9da..d7ec3fe0d5 100644 --- a/arch/x86/adler32_ssse3_p.h +++ b/arch/x86/adler32_ssse3_p.h @@ -6,7 +6,7 @@ #ifndef ADLER32_SSSE3_P_H_ #define ADLER32_SSSE3_P_H_ -#ifdef X86_SSSE3_ADLER32 +#ifdef X86_SSSE3 #include #include diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index e128e8f708..c2df2322fe 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -3,7 +3,7 @@ */ #include "zbuild.h" -#ifdef X86_AVX_CHUNKSET +#ifdef X86_AVX2 #include #include "../generic/chunk_permute_table.h" diff --git a/arch/x86/insert_string_sse42.c b/arch/x86/insert_string_sse42.c index 6fe4c81e08..2668f0eaa8 100644 --- a/arch/x86/insert_string_sse42.c +++ b/arch/x86/insert_string_sse42.c @@ -45,6 +45,6 @@ #define INSERT_STRING insert_string_sse4 #define QUICK_INSERT_STRING quick_insert_string_sse4 -#ifdef X86_SSE42_CRC_HASH +#ifdef X86_SSE42 # include "../../insert_string_tpl.h" #endif diff --git a/configure b/configure index c0f9524b5f..fdb5b69d7e 100755 --- a/configure +++ b/configure @@ -1545,8 +1545,8 @@ case "${ARCH}" in check_avx2_intrinsics if test ${HAVE_AVX2_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" - SFLAGS="${SFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" + CFLAGS="${CFLAGS} -DX86_AVX2" + SFLAGS="${SFLAGS} -DX86_AVX2" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_hash_avx2.o chunkset_avx.o compare256_avx2.o adler32_avx2.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx2.lo chunkset_avx.lo compare256_avx2.lo adler32_avx2.lo" fi @@ -1554,8 +1554,8 @@ case "${ARCH}" in check_avx512_intrinsics if test ${HAVE_AVX512_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_AVX512 -DX86_AVX512_ADLER32" - SFLAGS="${SFLAGS} -DX86_AVX512 -DX86_AVX512_ADLER32" + CFLAGS="${CFLAGS} -DX86_AVX512" + SFLAGS="${SFLAGS} -DX86_AVX512" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_avx512.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_avx512.lo" @@ -1570,8 +1570,8 @@ case "${ARCH}" in check_avx512vnni_intrinsics if test ${HAVE_AVX512VNNI_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_AVX512VNNI -DX86_AVX512VNNI_ADLER32" - SFLAGS="${SFLAGS} -DX86_AVX512VNNI -DX86_AVX512VNNI_ADLER32" + CFLAGS="${CFLAGS} -DX86_AVX512VNNI" + SFLAGS="${SFLAGS} -DX86_AVX512VNNI" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_avx512_vnni.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_avx512_vnni.lo" fi @@ -1589,8 +1589,8 @@ case "${ARCH}" in check_sse42_intrinsics if test ${HAVE_SSE42CRC_INTRIN} -eq 1 || test ${HAVE_SSE42CRC_INLINE_ASM} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE42_CRC_HASH -DX86_SSE42_ADLER32" - SFLAGS="${SFLAGS} -DX86_SSE42_CRC_HASH -DX86_SSE42_ADLER32" + CFLAGS="${CFLAGS} -DX86_SSE42" + SFLAGS="${SFLAGS} -DX86_SSE42" if test ${HAVE_SSE42CRC_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42_CRC_INTRIN" @@ -1604,8 +1604,8 @@ case "${ARCH}" in check_sse2_intrinsics if test ${HAVE_SSE2_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" - SFLAGS="${SFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" + CFLAGS="${CFLAGS} -DX86_SSE2" + SFLAGS="${SFLAGS} -DX86_SSE2" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse2.o compare256_sse2.o slide_hash_sse2.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse2.lo compare256_sse2.lo slide_hash_sse2.lo" @@ -1618,8 +1618,8 @@ case "${ARCH}" in check_ssse3_intrinsics if test ${HAVE_SSSE3_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSSE3 -DX86_SSSE3_ADLER32" - SFLAGS="${SFLAGS} -DX86_SSSE3 -DX86_SSSE3_ADLER32" + CFLAGS="${CFLAGS} -DX86_SSSE3" + SFLAGS="${SFLAGS} -DX86_SSSE3" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_ssse3.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_ssse3.lo" fi @@ -1785,9 +1785,6 @@ EOF SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" fi - CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi @@ -1812,9 +1809,6 @@ EOF SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" fi - CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi @@ -1825,8 +1819,8 @@ EOF if test $without_optimizations -eq 0; then if test $ACLE_AVAILABLE -eq 1; then - CFLAGS="${CFLAGS} -DARM_ACLE_CRC_HASH" - SFLAGS="${SFLAGS} -DARM_ACLE_CRC_HASH" + CFLAGS="${CFLAGS} -DARM_ACLE" + SFLAGS="${SFLAGS} -DARM_ACLE" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" @@ -1845,9 +1839,6 @@ EOF SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" fi - CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi @@ -1899,8 +1890,8 @@ EOF if test $native -eq 0; then ARCH="${ARCH}+crc" fi - CFLAGS="${CFLAGS} -DARM_ACLE_CRC_HASH" - SFLAGS="${SFLAGS} -DARM_ACLE_CRC_HASH" + CFLAGS="${CFLAGS} -DARM_ACLE" + SFLAGS="${SFLAGS} -DARM_ACLE" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" fi @@ -1909,8 +1900,8 @@ EOF if test $native -eq 0; then ARCH="${ARCH}+simd" fi - CFLAGS="${CFLAGS} -DARM_NEON -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" + CFLAGS="${CFLAGS} -DARM_NEON" + SFLAGS="${SFLAGS} -DARM_NEON" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi @@ -1949,15 +1940,15 @@ EOF ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power_features.lo" fi if test $HAVE_VMX -eq 1 -a $HAVE_ALTIVEC_INTRIN -eq 1; then - CFLAGS="${CFLAGS} -DPPC_VMX_ADLER32 -DPPC_VMX_SLIDEHASH" - SFLAGS="${SFLAGS} -DPPC_VMX_ADLER32 -DPPC_VMX_SLIDEHASH" + CFLAGS="${CFLAGS} -DPPC_VMX" + SFLAGS="${SFLAGS} -DPPC_VMX" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_vmx.o slide_hash_vmx.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_vmx.lo slide_hash_vmx.lo" fi if test $HAVE_POWER8_INTRIN -eq 1; then - CFLAGS="${CFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_CHUNKSET -DPOWER8_VSX_SLIDEHASH" - SFLAGS="${SFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_CHUNKSET -DPOWER8_VSX_SLIDEHASH" + CFLAGS="${CFLAGS} -DPOWER8_VSX -DPOWER_FEATURES" + SFLAGS="${SFLAGS} -DPOWER8_VSX -DPOWER_FEATURES" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_power8.o chunkset_power8.o slide_hash_power8.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_power8.lo chunkset_power8.lo slide_hash_power8.lo" diff --git a/cpu_features.h b/cpu_features.h index f71372dd69..c098ee2d34 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -26,39 +26,39 @@ extern void cpu_check_features(void); typedef uint32_t (*adler32_func)(uint32_t adler, const uint8_t *buf, size_t len); extern uint32_t adler32_c(uint32_t adler, const uint8_t *buf, size_t len); -#ifdef ARM_NEON_ADLER32 +#ifdef ARM_NEON extern uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len); #endif -#ifdef PPC_VMX_ADLER32 +#ifdef PPC_VMX extern uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len); #endif -#ifdef X86_SSSE3_ADLER32 +#ifdef X86_SSSE3 extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len); #endif -#ifdef X86_AVX2_ADLER32 +#ifdef X86_AVX2 extern uint32_t adler32_avx2(uint32_t adler, const uint8_t *buf, size_t len); #endif -#ifdef X86_AVX512_ADLER32 +#ifdef X86_AVX512 extern uint32_t adler32_avx512(uint32_t adler, const uint8_t *buf, size_t len); #endif -#ifdef X86_AVX512VNNI_ADLER32 +#ifdef X86_AVX512VNNI extern uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *buf, size_t len); #endif -#ifdef POWER8_VSX_ADLER32 +#ifdef POWER8_VSX extern uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len); #endif /* adler32 folding */ -#ifdef X86_SSE42_ADLER32 +#ifdef X86_SSE42 extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif -#ifdef X86_AVX2_ADLER32 +#ifdef X86_AVX2 extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif -#ifdef X86_AVX512_ADLER32 +#ifdef X86_AVX512 extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif -#ifdef X86_AVX512VNNI_ADLER32 +#ifdef X86_AVX512VNNI extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif @@ -74,22 +74,22 @@ extern uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len); /* memory chunking */ extern uint32_t chunksize_c(void); extern uint8_t* chunkmemset_safe_c(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#ifdef X86_SSE2_CHUNKSET +#ifdef X86_SSE2 extern uint32_t chunksize_sse2(void); extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif #ifdef X86_SSE41 extern uint8_t* chunkmemset_safe_sse41(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif -#ifdef X86_AVX_CHUNKSET +#ifdef X86_AVX2 extern uint32_t chunksize_avx(void); extern uint8_t* chunkmemset_safe_avx(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif -#ifdef ARM_NEON_CHUNKSET +#ifdef ARM_NEON extern uint32_t chunksize_neon(void); extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif -#ifdef POWER8_VSX_CHUNKSET +#ifdef POWER8_VSX extern uint32_t chunksize_power8(void); extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif @@ -102,19 +102,19 @@ typedef struct zng_stream_s zng_stream; /* inflate fast loop */ extern void inflate_fast_c(PREFIX3(stream) *strm, uint32_t start); -#ifdef X86_SSE2_CHUNKSET +#ifdef X86_SSE2 extern void inflate_fast_sse2(PREFIX3(stream) *strm, uint32_t start); #endif #ifdef X86_SSE41 extern void inflate_fast_sse41(PREFIX3(stream) *strm, uint32_t start); #endif -#ifdef X86_AVX_CHUNKSET +#ifdef X86_AVX2 extern void inflate_fast_avx(PREFIX3(stream) *strm, uint32_t start); #endif -#ifdef ARM_NEON_CHUNKSET +#ifdef ARM_NEON extern void inflate_fast_neon(PREFIX3(stream) *strm, uint32_t start); #endif -#ifdef POWER8_VSX_CHUNKSET +#ifdef POWER8_VSX extern void inflate_fast_power8(PREFIX3(stream) *strm, uint32_t start); #endif @@ -122,9 +122,9 @@ extern void inflate_fast_power8(PREFIX3(stream) *strm, uint32_t start); typedef uint32_t (*crc32_func)(uint32_t crc32, const uint8_t *buf, size_t len); extern uint32_t PREFIX(crc32_braid)(uint32_t crc, const uint8_t *buf, size_t len); -#ifdef ARM_ACLE_CRC_HASH +#ifdef ARM_ACLE extern uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len); -#elif defined(POWER8_VSX_CRC32) +#elif defined(POWER8_VSX) extern uint32_t crc32_power8(uint32_t crc, const uint8_t *buf, size_t len); #elif defined(S390_CRC32_VX) extern uint32_t PREFIX(s390_crc32_vx)(uint32_t crc, const uint8_t *buf, size_t len); @@ -159,9 +159,9 @@ extern uint32_t compare256_power9(const uint8_t *src0, const uint8_t *src1); #ifdef DEFLATE_H_ /* insert_string */ extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); -#ifdef X86_SSE42_CRC_HASH +#ifdef X86_SSE42 extern void insert_string_sse4(deflate_state *const s, const uint32_t str, uint32_t count); -#elif defined(ARM_ACLE_CRC_HASH) +#elif defined(ARM_ACLE) extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint32_t count); #endif @@ -213,9 +213,9 @@ extern uint32_t longest_match_slow_power9(deflate_state *const s, Pos cur_match) /* quick_insert_string */ extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); -#ifdef X86_SSE42_CRC_HASH +#ifdef X86_SSE42 extern Pos quick_insert_string_sse4(deflate_state *const s, const uint32_t str); -#elif defined(ARM_ACLE_CRC_HASH) +#elif defined(ARM_ACLE) extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); #endif @@ -224,13 +224,13 @@ typedef void (*slide_hash_func)(deflate_state *s); #ifdef X86_SSE2 extern void slide_hash_sse2(deflate_state *s); -#elif defined(ARM_NEON_SLIDEHASH) +#elif defined(ARM_NEON) extern void slide_hash_neon(deflate_state *s); #endif -#if defined(PPC_VMX_SLIDEHASH) +#if defined(PPC_VMX) extern void slide_hash_vmx(deflate_state *s); #endif -#if defined(POWER8_VSX_SLIDEHASH) +#if defined(POWER8_VSX) extern void slide_hash_power8(deflate_state *s); #endif #ifdef X86_AVX2 @@ -239,9 +239,9 @@ extern void slide_hash_avx2(deflate_state *s); /* update_hash */ extern uint32_t update_hash_c(deflate_state *const s, uint32_t h, uint32_t val); -#ifdef X86_SSE42_CRC_HASH +#ifdef X86_SSE42 extern uint32_t update_hash_sse4(deflate_state *const s, uint32_t h, uint32_t val); -#elif defined(ARM_ACLE_CRC_HASH) +#elif defined(ARM_ACLE) extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); #endif #endif diff --git a/functable.c b/functable.c index b64b4bd65a..a02aae77f0 100644 --- a/functable.c +++ b/functable.c @@ -56,28 +56,24 @@ static void init_functable(void) { // Select arch-optimized functions // X86 - SSE2 -#if defined(X86_SSE2) || defined(X86_SSE2_CHUNKSET) +#ifdef X86_SSE2 # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) if (x86_cpu_has_sse2) # endif { -# ifdef X86_SSE2 ft.slide_hash = &slide_hash_sse2; -# ifdef HAVE_BUILTIN_CTZ - ft.longest_match = &longest_match_sse2; - ft.longest_match_slow = &longest_match_slow_sse2; - ft.compare256 = &compare256_sse2; -# endif -# endif -# ifdef X86_SSE2_CHUNKSET ft.chunksize = &chunksize_sse2; ft.chunkmemset_safe = &chunkmemset_safe_sse2; ft.inflate_fast = &inflate_fast_sse2; +# ifdef HAVE_BUILTIN_CTZ + ft.longest_match = &longest_match_sse2; + ft.longest_match_slow = &longest_match_slow_sse2; + ft.compare256 = &compare256_sse2; # endif } #endif // X86 - SSSE3 -#ifdef X86_SSSE3_ADLER32 +#ifdef X86_SSSE3 if (x86_cpu_has_ssse3) ft.adler32 = &adler32_ssse3; #endif @@ -88,12 +84,9 @@ static void init_functable(void) { ft.inflate_fast = &inflate_fast_sse41; } #endif -#ifdef X86_SSE42_ADLER32 - if (x86_cpu_has_sse42) - ft.adler32_fold_copy = &adler32_fold_copy_sse42; -#endif -#ifdef X86_SSE42_CRC_HASH +#ifdef X86_SSE42 if (x86_cpu_has_sse42) { + ft.adler32_fold_copy = &adler32_fold_copy_sse42; ft.update_hash = &update_hash_sse4; ft.insert_string = &insert_string_sse4; ft.quick_insert_string = &quick_insert_string_sse4; @@ -110,16 +103,14 @@ static void init_functable(void) { } #endif // X86 - AVX -#ifdef X86_AVX_CHUNKSET +#ifdef X86_AVX2 if (x86_cpu_has_avx2) { ft.chunksize = &chunksize_avx; ft.chunkmemset_safe = &chunkmemset_safe_avx; ft.inflate_fast = &inflate_fast_avx; - } -#endif -#ifdef X86_AVX2 - if (x86_cpu_has_avx2) { ft.slide_hash = &slide_hash_avx2; + ft.adler32 = &adler32_avx2; + ft.adler32_fold_copy = &adler32_fold_copy_avx2; # ifdef HAVE_BUILTIN_CTZ ft.longest_match = &longest_match_avx2; ft.longest_match_slow = &longest_match_slow_avx2; @@ -127,19 +118,13 @@ static void init_functable(void) { # endif } #endif -#ifdef X86_AVX2_ADLER32 - if (x86_cpu_has_avx2) { - ft.adler32 = &adler32_avx2; - ft.adler32_fold_copy = &adler32_fold_copy_avx2; - } -#endif -#ifdef X86_AVX512_ADLER32 +#ifdef X86_AVX512 if (x86_cpu_has_avx512) { ft.adler32 = &adler32_avx512; ft.adler32_fold_copy = &adler32_fold_copy_avx512; } #endif -#ifdef X86_AVX512VNNI_ADLER32 +#ifdef X86_AVX512VNNI if (x86_cpu_has_avx512vnni) { ft.adler32 = &adler32_avx512_vnni; ft.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; @@ -148,34 +133,25 @@ static void init_functable(void) { // ARM - NEON -#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) - if (arm_cpu_has_neon) { - ft.compare256 = &compare256_neon; - ft.longest_match = &longest_match_neon; - ft.longest_match_slow = &longest_match_slow_neon; - } -#endif -#ifdef ARM_NEON_ADLER32 +#ifdef ARM_NEON # ifndef ARM_NOCHECK_NEON if (arm_cpu_has_neon) # endif + { ft.adler32 = &adler32_neon; -#endif -#ifdef ARM_NEON_SLIDEHASH -# ifndef ARM_NOCHECK_NEON - if (arm_cpu_has_neon) -# endif ft.slide_hash = &slide_hash_neon; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) { ft.chunksize = &chunksize_neon; ft.chunkmemset_safe = &chunkmemset_safe_neon; ft.inflate_fast = &inflate_fast_neon; +# ifdef HAVE_BUILTIN_CTZLL + ft.compare256 = &compare256_neon; + ft.longest_match = &longest_match_neon; + ft.longest_match_slow = &longest_match_slow_neon; +# endif } #endif // ARM - ACLE -#ifdef ARM_ACLE_CRC_HASH +#ifdef ARM_ACLE if (arm_cpu_has_crc32) { ft.crc32 = &crc32_acle; ft.update_hash = &update_hash_acle; @@ -184,34 +160,27 @@ static void init_functable(void) { } #endif + // Power - VMX -#ifdef PPC_VMX_SLIDEHASH - if (power_cpu_has_altivec) - ft.slide_hash = &slide_hash_vmx; -#endif -#ifdef PPC_VMX_ADLER32 - if (power_cpu_has_altivec) +#ifdef PPC_VMX + if (power_cpu_has_altivec) { ft.adler32 = &adler32_vmx; + ft.slide_hash = &slide_hash_vmx; + } #endif // Power8 - VSX -#ifdef POWER8_VSX_SLIDEHASH - if (power_cpu_has_arch_2_07) - ft.slide_hash = &slide_hash_power8; -#endif -#ifdef POWER8_VSX_ADLER32 - if (power_cpu_has_arch_2_07) +#ifdef POWER8_VSX + if (power_cpu_has_arch_2_07) { ft.adler32 = &adler32_power8; + ft.chunkmemset_safe = &chunkmemset_safe_power8; + ft.chunksize = &chunksize_power8; + ft.inflate_fast = &inflate_fast_power8; + ft.slide_hash = &slide_hash_power8; + } #endif #ifdef POWER8_VSX_CRC32 if (power_cpu_has_arch_2_07) ft.crc32 = &crc32_power8; -#endif -#ifdef POWER8_VSX_CHUNKSET - if (power_cpu_has_arch_2_07) { - ft.chunksize = &chunksize_power8; - ft.chunkmemset_safe = &chunkmemset_safe_power8; - ft.inflate_fast = &inflate_fast_power8; - } #endif // Power9 #ifdef POWER9 @@ -222,6 +191,7 @@ static void init_functable(void) { } #endif + // S390 #ifdef S390_CRC32_VX if (PREFIX(s390_cpu_has_vx)) diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index b94912ac96..19691376fb 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -64,26 +64,26 @@ class adler32: public benchmark::Fixture { BENCHMARK_ADLER32(c, adler32_c, 1); -#ifdef ARM_NEON_ADLER32 +#ifdef ARM_NEON BENCHMARK_ADLER32(neon, adler32_neon, arm_cpu_has_neon); #endif -#ifdef PPC_VMX_ADLER32 +#ifdef PPC_VMX BENCHMARK_ADLER32(vmx, adler32_vmx, power_cpu_has_altivec); #endif -#ifdef POWER8_VSX_ADLER32 +#ifdef POWER8_VSX BENCHMARK_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07); #endif -#ifdef X86_SSSE3_ADLER32 +#ifdef X86_SSSE3 BENCHMARK_ADLER32(ssse3, adler32_ssse3, x86_cpu_has_ssse3); #endif -#ifdef X86_AVX2_ADLER32 +#ifdef X86_AVX2 BENCHMARK_ADLER32(avx2, adler32_avx2, x86_cpu_has_avx2); #endif -#ifdef X86_AVX512_ADLER32 +#ifdef X86_AVX512 BENCHMARK_ADLER32(avx512, adler32_avx512, x86_cpu_has_avx512); #endif -#ifdef X86_AVX512VNNI_ADLER32 +#ifdef X86_AVX512VNNI BENCHMARK_ADLER32(avx512_vnni, adler32_avx512_vnni, x86_cpu_has_avx512vnni); #endif diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index 62998d41ee..d508a004aa 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -85,34 +85,34 @@ class adler32_copy: public benchmark::Fixture { BENCHMARK_ADLER32_BASELINE_COPY(c, adler32_c, 1); -#ifdef ARM_NEON_ADLER32 +#ifdef ARM_NEON /* If we inline this copy for neon, the function would go here */ //BENCHMARK_ADLER32_COPY(neon, adler32_neon, arm_cpu_has_neon); BENCHMARK_ADLER32_BASELINE_COPY(neon_copy_baseline, adler32_neon, arm_cpu_has_neon); #endif -#ifdef PPC_VMX_ADLER32 +#ifdef PPC_VMX //BENCHMARK_ADLER32_COPY(vmx_inline_copy, adler32_fold_copy_vmx, power_cpu_has_altivec); BENCHMARK_ADLER32_BASELINE_COPY(vmx_copy_baseline, adler32_vmx, power_cpu_has_altivec); #endif -#ifdef POWER8_VSX_ADLER32 +#ifdef POWER8_VSX //BENCHMARK_ADLER32_COPY(power8_inline_copy, adler32_fold_copy_power8, power_cpu_has_arch_2_07); BENCHMARK_ADLER32_BASELINE_COPY(power8, adler32_power8, power_cpu_has_arch_2_07); #endif -#ifdef X86_SSE42_ADLER32 +#ifdef X86_SSE42 BENCHMARK_ADLER32_BASELINE_COPY(sse42_baseline, adler32_ssse3, x86_cpu_has_ssse3); BENCHMARK_ADLER32_COPY(sse42, adler32_fold_copy_sse42, x86_cpu_has_sse42); #endif -#ifdef X86_AVX2_ADLER32 +#ifdef X86_AVX2 BENCHMARK_ADLER32_BASELINE_COPY(avx2_baseline, adler32_avx2, x86_cpu_has_avx2); BENCHMARK_ADLER32_COPY(avx2, adler32_fold_copy_avx2, x86_cpu_has_avx2); #endif -#ifdef X86_AVX512_ADLER32 +#ifdef X86_AVX512 BENCHMARK_ADLER32_BASELINE_COPY(avx512_baseline, adler32_avx512, x86_cpu_has_avx512); BENCHMARK_ADLER32_COPY(avx512, adler32_fold_copy_avx512, x86_cpu_has_avx512); #endif -#ifdef X86_AVX512VNNI_ADLER32 +#ifdef X86_AVX512VNNI BENCHMARK_ADLER32_BASELINE_COPY(avx512_vnni_baseline, adler32_avx512_vnni, x86_cpu_has_avx512vnni); BENCHMARK_ADLER32_COPY(avx512_vnni, adler32_fold_copy_avx512_vnni, x86_cpu_has_avx512vnni); #endif diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index f17ebf6c11..b5ecda5179 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -57,9 +57,9 @@ class crc32: public benchmark::Fixture { BENCHMARK_CRC32(braid, PREFIX(crc32_braid), 1); -#ifdef ARM_ACLE_CRC_HASH +#ifdef ARM_ACLE BENCHMARK_CRC32(acle, crc32_acle, arm_cpu_has_crc32); -#elif defined(POWER8_VSX_CRC32) +#elif defined(POWER8_VSX) BENCHMARK_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07); #elif defined(S390_CRC32_VX) BENCHMARK_CRC32(vx, PREFIX(s390_crc32_vx), PREFIX(s390_cpu_has_vx)); diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index 4ec87b6d85..5ffa7039d0 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -68,13 +68,13 @@ class slide_hash: public benchmark::Fixture { BENCHMARK_SLIDEHASH(c, slide_hash_c, 1); -#ifdef ARM_NEON_SLIDEHASH +#ifdef ARM_NEON BENCHMARK_SLIDEHASH(neon, slide_hash_neon, arm_cpu_has_neon); #endif -#ifdef POWER8_VSX_SLIDEHASH +#ifdef POWER8_VSX BENCHMARK_SLIDEHASH(power8, slide_hash_power8, power_cpu_has_arch_2_07); #endif -#ifdef PPC_VMX_SLIDEHASH +#ifdef PPC_VMX BENCHMARK_SLIDEHASH(vmx, slide_hash_vmx, power_cpu_has_altivec); #endif diff --git a/test/test_adler32.cc b/test/test_adler32.cc index fa113da5ae..7f88f25565 100644 --- a/test/test_adler32.cc +++ b/test/test_adler32.cc @@ -364,26 +364,23 @@ INSTANTIATE_TEST_SUITE_P(adler32, adler32_variant, testing::ValuesIn(tests)); TEST_ADLER32(c, adler32_c, 1) -#ifdef ARM_NEON_ADLER32 +#ifdef ARM_NEON TEST_ADLER32(neon, adler32_neon, arm_cpu_has_neon) -#elif defined(POWER8_VSX_ADLER32) +#elif defined(POWER8_VSX) TEST_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07) -#elif defined(PPC_VMX_ADLER32) +#elif defined(PPC_VMX) TEST_ADLER32(vmx, adler32_vmx, power_cpu_has_altivec) #endif -#ifdef X86_SSSE3_ADLER32 +#ifdef X86_SSSE3 TEST_ADLER32(ssse3, adler32_ssse3, x86_cpu_has_ssse3) #endif -#ifdef X86_SSE41_ADLER32 -TEST_ADLER32(sse41, adler32_sse41, x86_cpu_has_sse41) -#endif -#ifdef X86_AVX2_ADLER32 +#ifdef X86_AVX2 TEST_ADLER32(avx2, adler32_avx2, x86_cpu_has_avx2) #endif -#ifdef X86_AVX512_ADLER32 +#ifdef X86_AVX512 TEST_ADLER32(avx512, adler32_avx512, x86_cpu_has_avx512) #endif -#ifdef X86_AVX512VNNI_ADLER32 +#ifdef X86_AVX512VNNI TEST_ADLER32(avx512_vnni, adler32_avx512_vnni, x86_cpu_has_avx512vnni) #endif diff --git a/test/test_crc32.cc b/test/test_crc32.cc index 6b6af4bce5..c46d0eb80a 100644 --- a/test/test_crc32.cc +++ b/test/test_crc32.cc @@ -208,7 +208,7 @@ INSTANTIATE_TEST_SUITE_P(crc32, crc32_variant, testing::ValuesIn(tests)); TEST_CRC32(braid, PREFIX(crc32_braid), 1) -#ifdef ARM_ACLE_CRC_HASH +#ifdef ARM_ACLE TEST_CRC32(acle, crc32_acle, arm_cpu_has_crc32) #elif defined(POWER8_VSX_CRC32) TEST_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07) diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 8537bd5fe9..2a0f3cfe4e 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -91,12 +91,9 @@ OBJS = $(OBJS) gzlib.obj gzread.obj gzwrite.obj !endif WFLAGS = $(WFLAGS) \ - -DARM_ACLE_CRC_HASH \ + -DARM_ACLE \ -D__ARM_NEON__=1 \ -DARM_NEON \ - -DARM_NEON_ADLER32 \ - -DARM_NEON_CHUNKSET \ - -DARM_NEON_SLIDEHASH \ -DARM_NOCHECK_NEON \ # OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj adler32_neon.obj chunkset_neon.obj compare256_neon.obj slide_hash_neon.obj diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 58a7fc8661..7d3f1b58a9 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -95,7 +95,7 @@ OBJS = $(OBJS) gzlib.obj gzread.obj gzwrite.obj !endif !if "$(WITH_ACLE)" != "" -WFLAGS = $(WFLAGS) -DARM_ACLE_CRC_HASH +WFLAGS = $(WFLAGS) -DARM_ACLE OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj !endif !if "$(WITH_VFPV3)" != "" @@ -106,9 +106,6 @@ CFLAGS = $(CFLAGS) $(NEON_ARCH) WFLAGS = $(WFLAGS) \ -D__ARM_NEON__=1 \ -DARM_NEON \ - -DARM_NEON_ADLER32 \ - -DARM_NEON_CHUNKSET \ - -DARM_NEON_SLIDEHASH \ -DARM_NOCHECK_NEON \ # OBJS = $(OBJS) adler32_neon.obj chunkset_neon.obj compare256_neon.obj slide_hash_neon.obj diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 9c00737a8f..f2f0631a15 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -30,14 +30,10 @@ WFLAGS = \ -DX86_FEATURES \ -DX86_PCLMULQDQ_CRC \ -DX86_SSE2 \ - -DX86_SSE42_ADLER32 \ + -DX86_SSE42 \ -DX86_SSE42_CRC_INTRIN \ - -DX86_SSE42_CRC_HASH \ - -DX86_SSSE3_ADLER32 \ - -DX86_AVX2 \ - -DX86_AVX2_ADLER32 \ - -DX86_AVX_CHUNKSET \ - -DX86_SSE2_CHUNKSET + -DX86_SSSE3 \ + -DX86_AVX2 LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest ARFLAGS = -nologo From 2fa631e029084b75acd81db5d33fd4aa802fd082 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 7 Feb 2023 16:03:46 +0100 Subject: [PATCH 608/798] Fix CMake not enabling POWER9_FEATURES --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df5cc03e9d..d85ccf010e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -660,6 +660,7 @@ if(WITH_OPTIM) check_power9_intrinsics() endif() if(HAVE_VMX OR HAVE_POWER8_INTRIN OR HAVE_POWER9_INTRIN) + add_definitions(-DPOWER_FEATURES) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power_features.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power_features.c) endif() @@ -682,7 +683,6 @@ if(WITH_OPTIM) if(WITH_POWER8) if(HAVE_POWER8_INTRIN) add_definitions(-DPOWER8_VSX) - add_definitions(-DPOWER_FEATURES) set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/chunkset_power8.c ${ARCHDIR}/slide_hash_power8.c) if("${ARCH}" MATCHES "powerpc64(le)?") add_definitions(-DPOWER8_VSX_CRC32) From 9db6a98894ab462f5bf65f1e61bcac3e67bdca83 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Wed, 8 Feb 2023 22:53:36 +0100 Subject: [PATCH 609/798] Sort functable alphabetically --- functable.c | 132 ++++++++++++++++++++++++++-------------------------- functable.h | 10 ++-- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/functable.c b/functable.c index a02aae77f0..23106b33d2 100644 --- a/functable.c +++ b/functable.c @@ -17,20 +17,20 @@ static void init_functable(void) { cpu_check_features(); // Generic code - ft.update_hash = &update_hash_c; - ft.insert_string = &insert_string_c; - ft.quick_insert_string = &quick_insert_string_c; - ft.slide_hash = &slide_hash_c; ft.adler32 = &adler32_c; - ft.chunksize = &chunksize_c; - ft.chunkmemset_safe = &chunkmemset_safe_c; - ft.inflate_fast = &inflate_fast_c; ft.adler32_fold_copy = &adler32_fold_copy_c; + ft.chunkmemset_safe = &chunkmemset_safe_c; + ft.chunksize = &chunksize_c; + ft.crc32 = &PREFIX(crc32_braid); ft.crc32_fold = &crc32_fold_c; - ft.crc32_fold_reset = &crc32_fold_reset_c; ft.crc32_fold_copy = &crc32_fold_copy_c; ft.crc32_fold_final = &crc32_fold_final_c; - ft.crc32 = &PREFIX(crc32_braid); + ft.crc32_fold_reset = &crc32_fold_reset_c; + ft.inflate_fast = &inflate_fast_c; + ft.insert_string = &insert_string_c; + ft.quick_insert_string = &quick_insert_string_c; + ft.slide_hash = &slide_hash_c; + ft.update_hash = &update_hash_c; #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) @@ -61,14 +61,14 @@ static void init_functable(void) { if (x86_cpu_has_sse2) # endif { - ft.slide_hash = &slide_hash_sse2; - ft.chunksize = &chunksize_sse2; ft.chunkmemset_safe = &chunkmemset_safe_sse2; + ft.chunksize = &chunksize_sse2; ft.inflate_fast = &inflate_fast_sse2; + ft.slide_hash = &slide_hash_sse2; # ifdef HAVE_BUILTIN_CTZ + ft.compare256 = &compare256_sse2; ft.longest_match = &longest_match_sse2; ft.longest_match_slow = &longest_match_slow_sse2; - ft.compare256 = &compare256_sse2; # endif } #endif @@ -87,9 +87,9 @@ static void init_functable(void) { #ifdef X86_SSE42 if (x86_cpu_has_sse42) { ft.adler32_fold_copy = &adler32_fold_copy_sse42; - ft.update_hash = &update_hash_sse4; ft.insert_string = &insert_string_sse4; ft.quick_insert_string = &quick_insert_string_sse4; + ft.update_hash = &update_hash_sse4; } #endif // X86 - PCLMUL @@ -97,24 +97,24 @@ static void init_functable(void) { if (x86_cpu_has_pclmulqdq) { ft.crc32 = &crc32_pclmulqdq; ft.crc32_fold = &crc32_fold_pclmulqdq; - ft.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; ft.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; ft.crc32_fold_final = &crc32_fold_pclmulqdq_final; + ft.crc32_fold_reset = &crc32_fold_pclmulqdq_reset; } #endif // X86 - AVX #ifdef X86_AVX2 if (x86_cpu_has_avx2) { - ft.chunksize = &chunksize_avx; + ft.adler32 = &adler32_avx2; + ft.adler32_fold_copy = &adler32_fold_copy_avx2; ft.chunkmemset_safe = &chunkmemset_safe_avx; + ft.chunksize = &chunksize_avx; ft.inflate_fast = &inflate_fast_avx; ft.slide_hash = &slide_hash_avx2; - ft.adler32 = &adler32_avx2; - ft.adler32_fold_copy = &adler32_fold_copy_avx2; # ifdef HAVE_BUILTIN_CTZ + ft.compare256 = &compare256_avx2; ft.longest_match = &longest_match_avx2; ft.longest_match_slow = &longest_match_slow_avx2; - ft.compare256 = &compare256_avx2; # endif } #endif @@ -139,10 +139,10 @@ static void init_functable(void) { # endif { ft.adler32 = &adler32_neon; - ft.slide_hash = &slide_hash_neon; - ft.chunksize = &chunksize_neon; ft.chunkmemset_safe = &chunkmemset_safe_neon; + ft.chunksize = &chunksize_neon; ft.inflate_fast = &inflate_fast_neon; + ft.slide_hash = &slide_hash_neon; # ifdef HAVE_BUILTIN_CTZLL ft.compare256 = &compare256_neon; ft.longest_match = &longest_match_neon; @@ -154,9 +154,9 @@ static void init_functable(void) { #ifdef ARM_ACLE if (arm_cpu_has_crc32) { ft.crc32 = &crc32_acle; - ft.update_hash = &update_hash_acle; ft.insert_string = &insert_string_acle; ft.quick_insert_string = &quick_insert_string_acle; + ft.update_hash = &update_hash_acle; } #endif @@ -185,9 +185,9 @@ static void init_functable(void) { // Power9 #ifdef POWER9 if (power_cpu_has_arch_3_00) { + ft.compare256 = &compare256_power9; ft.longest_match = &longest_match_power9; ft.longest_match_slow = &longest_match_slow_power9; - ft.compare256 = &compare256_power9; } #endif @@ -201,14 +201,14 @@ static void init_functable(void) { // Assign function pointers individually for atomic operation functable.adler32 = ft.adler32; functable.adler32_fold_copy = ft.adler32_fold_copy; + functable.chunkmemset_safe = ft.chunkmemset_safe; + functable.chunksize = ft.chunksize; + functable.compare256 = ft.compare256; functable.crc32 = ft.crc32; - functable.crc32_fold_reset = ft.crc32_fold_reset; - functable.crc32_fold_copy = ft.crc32_fold_copy; functable.crc32_fold = ft.crc32_fold; + functable.crc32_fold_copy = ft.crc32_fold_copy; functable.crc32_fold_final = ft.crc32_fold_final; - functable.compare256 = ft.compare256; - functable.chunksize = ft.chunksize; - functable.chunkmemset_safe = ft.chunkmemset_safe; + functable.crc32_fold_reset = ft.crc32_fold_reset; functable.inflate_fast = ft.inflate_fast; functable.insert_string = ft.insert_string; functable.longest_match = ft.longest_match; @@ -219,103 +219,103 @@ static void init_functable(void) { } /* stub functions */ -static uint32_t update_hash_stub(deflate_state* const s, uint32_t h, uint32_t val) { +static uint32_t adler32_stub(uint32_t adler, const uint8_t* buf, size_t len) { init_functable(); - return functable.update_hash(s, h, val); + return functable.adler32(adler, buf, len); } -static void insert_string_stub(deflate_state* const s, uint32_t str, uint32_t count) { +static uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t* dst, const uint8_t* src, size_t len) { init_functable(); - functable.insert_string(s, str, count); + return functable.adler32_fold_copy(adler, dst, src, len); } -static Pos quick_insert_string_stub(deflate_state* const s, const uint32_t str) { +static uint8_t* chunkmemset_safe_stub(uint8_t* out, unsigned dist, unsigned len, unsigned left) { init_functable(); - return functable.quick_insert_string(s, str); + return functable.chunkmemset_safe(out, dist, len, left); } -static void slide_hash_stub(deflate_state* s) { +static uint32_t chunksize_stub(void) { init_functable(); - functable.slide_hash(s); + return functable.chunksize(); } -static uint32_t longest_match_stub(deflate_state* const s, Pos cur_match) { +static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) { init_functable(); - return functable.longest_match(s, cur_match); + return functable.compare256(src0, src1); } -static uint32_t longest_match_slow_stub(deflate_state* const s, Pos cur_match) { +static uint32_t crc32_stub(uint32_t crc, const uint8_t* buf, size_t len) { init_functable(); - return functable.longest_match_slow(s, cur_match); + return functable.crc32(crc, buf, len); } -static uint32_t adler32_stub(uint32_t adler, const uint8_t* buf, size_t len) { +static void crc32_fold_stub(crc32_fold* crc, const uint8_t* src, size_t len, uint32_t init_crc) { init_functable(); - return functable.adler32(adler, buf, len); + functable.crc32_fold(crc, src, len, init_crc); } -static uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t* dst, const uint8_t* src, size_t len) { +static void crc32_fold_copy_stub(crc32_fold* crc, uint8_t* dst, const uint8_t* src, size_t len) { init_functable(); - return functable.adler32_fold_copy(adler, dst, src, len); + functable.crc32_fold_copy(crc, dst, src, len); } -static uint32_t crc32_fold_reset_stub(crc32_fold* crc) { +static uint32_t crc32_fold_final_stub(crc32_fold* crc) { init_functable(); - return functable.crc32_fold_reset(crc); + return functable.crc32_fold_final(crc); } -static void crc32_fold_copy_stub(crc32_fold* crc, uint8_t* dst, const uint8_t* src, size_t len) { +static uint32_t crc32_fold_reset_stub(crc32_fold* crc) { init_functable(); - functable.crc32_fold_copy(crc, dst, src, len); + return functable.crc32_fold_reset(crc); } -static void crc32_fold_stub(crc32_fold* crc, const uint8_t* src, size_t len, uint32_t init_crc) { +static void inflate_fast_stub(PREFIX3(stream) *strm, uint32_t start) { init_functable(); - functable.crc32_fold(crc, src, len, init_crc); + functable.inflate_fast(strm, start); } -static uint32_t crc32_fold_final_stub(crc32_fold* crc) { +static void insert_string_stub(deflate_state* const s, uint32_t str, uint32_t count) { init_functable(); - return functable.crc32_fold_final(crc); + functable.insert_string(s, str, count); } -static uint32_t chunksize_stub(void) { +static uint32_t longest_match_stub(deflate_state* const s, Pos cur_match) { init_functable(); - return functable.chunksize(); + return functable.longest_match(s, cur_match); } -static uint8_t* chunkmemset_safe_stub(uint8_t* out, unsigned dist, unsigned len, unsigned left) { +static uint32_t longest_match_slow_stub(deflate_state* const s, Pos cur_match) { init_functable(); - return functable.chunkmemset_safe(out, dist, len, left); + return functable.longest_match_slow(s, cur_match); } -static void inflate_fast_stub(PREFIX3(stream) *strm, uint32_t start) { +static Pos quick_insert_string_stub(deflate_state* const s, const uint32_t str) { init_functable(); - functable.inflate_fast(strm, start); + return functable.quick_insert_string(s, str); } -static uint32_t crc32_stub(uint32_t crc, const uint8_t* buf, size_t len) { +static void slide_hash_stub(deflate_state* s) { init_functable(); - return functable.crc32(crc, buf, len); + functable.slide_hash(s); } -static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) { +static uint32_t update_hash_stub(deflate_state* const s, uint32_t h, uint32_t val) { init_functable(); - return functable.compare256(src0, src1); + return functable.update_hash(s, h, val); } /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { adler32_stub, adler32_fold_copy_stub, + chunkmemset_safe_stub, + chunksize_stub, + compare256_stub, crc32_stub, - crc32_fold_reset_stub, - crc32_fold_copy_stub, crc32_fold_stub, + crc32_fold_copy_stub, crc32_fold_final_stub, - compare256_stub, - chunksize_stub, - chunkmemset_safe_stub, + crc32_fold_reset_stub, inflate_fast_stub, insert_string_stub, longest_match_stub, diff --git a/functable.h b/functable.h index 6c277f50aa..1cdfd4df41 100644 --- a/functable.h +++ b/functable.h @@ -19,14 +19,14 @@ typedef struct zng_stream_s zng_stream; struct functable_s { uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, size_t len); uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); + uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); + uint32_t (* chunksize) (void); + uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* crc32) (uint32_t crc, const uint8_t *buf, size_t len); - uint32_t (* crc32_fold_reset) (struct crc32_fold_s *crc); - void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, size_t len); void (* crc32_fold) (struct crc32_fold_s *crc, const uint8_t *src, size_t len, uint32_t init_crc); + void (* crc32_fold_copy) (struct crc32_fold_s *crc, uint8_t *dst, const uint8_t *src, size_t len); uint32_t (* crc32_fold_final) (struct crc32_fold_s *crc); - uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); - uint32_t (* chunksize) (void); - uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); + uint32_t (* crc32_fold_reset) (struct crc32_fold_s *crc); void (* inflate_fast) (PREFIX3(stream) *strm, uint32_t start); void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); From fa9bfeddcf4a3624a95c82e48471308f68b5778f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 11 Feb 2023 17:24:54 -0800 Subject: [PATCH 610/798] Use named defines instead of hard coded numbers. --- deflate.c | 10 +++++----- deflate.h | 3 --- gzread.c.in | 2 +- infback.c | 6 +++--- inffast_tpl.h | 6 +++--- inflate.c | 14 +++++++------- inftrees.c | 14 ++++++-------- test/test_deflate_hash_head_0.cc | 2 +- test/test_deflate_quick_block_open.cc | 4 ++-- test/test_raw.cc | 2 +- zconf-ng.h.in | 3 +++ zconf.h.in | 3 +++ zutil.h | 3 +++ 13 files changed, 38 insertions(+), 34 deletions(-) diff --git a/deflate.c b/deflate.c index 78b19e26a3..273967b426 100644 --- a/deflate.c +++ b/deflate.c @@ -213,17 +213,17 @@ int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level if (windowBits < 0) { /* suppress zlib wrapper */ wrap = 0; - if (windowBits < -15) + if (windowBits < -MAX_WBITS) return Z_STREAM_ERROR; windowBits = -windowBits; #ifdef GZIP - } else if (windowBits > 15) { + } else if (windowBits > MAX_WBITS) { wrap = 2; /* write gzip wrapper instead */ windowBits -= 16; #endif } - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || - windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED || + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < MIN_WBITS || + windowBits > MAX_WBITS || level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { return Z_STREAM_ERROR; } @@ -662,7 +662,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 != 15 || HASH_BITS < 15) { + s->w_bits != 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 */ diff --git a/deflate.h b/deflate.h index 2d2ee3da11..e4b971f88a 100644 --- a/deflate.h +++ b/deflate.h @@ -45,9 +45,6 @@ #define HEAP_SIZE (2*L_CODES+1) /* maximum heap size */ -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - #define BIT_BUF_SIZE 64 /* size of bit buffer in bi_buf */ diff --git a/gzread.c.in b/gzread.c.in index 262517e4fe..67a21a3e4d 100644 --- a/gzread.c.in +++ b/gzread.c.in @@ -100,7 +100,7 @@ static int gz_look(gz_state *state) { state->strm.opaque = NULL; state->strm.avail_in = 0; state->strm.next_in = NULL; - if (PREFIX(inflateInit2)(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ + if (PREFIX(inflateInit2)(&(state->strm), MAX_WBITS + 16) != Z_OK) { /* gunzip */ zng_free(state->out); zng_free(state->in); state->size = 0; diff --git a/infback.c b/infback.c index 179cea737b..9f5042b4d3 100644 --- a/infback.c +++ b/infback.c @@ -34,7 +34,7 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateBackInit)(PREFIX3(stream) *strm, int32_t windowBits, uint8_t *window) { struct inflate_state *state; - if (strm == NULL || window == NULL || windowBits < 8 || windowBits > 15) + if (strm == NULL || window == NULL || windowBits < MIN_WBITS || windowBits > MAX_WBITS) return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ if (strm->zalloc == NULL) { @@ -408,7 +408,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in } /* length code -- get extra bits, if any */ - state->extra = (here.op & 15); + state->extra = (here.op & MAX_BITS); if (state->extra) { NEEDBITS(state->extra); state->length += BITS(state->extra); @@ -439,7 +439,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in break; } state->offset = here.val; - state->extra = (here.op & 15); + state->extra = (here.op & MAX_BITS); /* get distance extra bits, if any */ if (state->extra) { diff --git a/inffast_tpl.h b/inffast_tpl.h index 6977a560a2..e17e59241e 100644 --- a/inffast_tpl.h +++ b/inffast_tpl.h @@ -148,7 +148,7 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { - if (bits < 15) { + if (bits < MAX_BITS) { hold |= load_64_bits(in, bits); in += 6; bits += 48; @@ -173,7 +173,7 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { len += BITS(op); DROPBITS(op); Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { + if (bits < MAX_BITS) { hold |= load_64_bits(in, bits); in += 6; bits += 48; @@ -184,7 +184,7 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { op = here->op; if (op & 16) { /* distance base */ dist = here->val; - op &= 15; /* number of extra bits */ + op &= MAX_BITS; /* number of extra bits */ if (bits < op) { hold |= load_64_bits(in, bits); in += 6; diff --git a/inflate.c b/inflate.c index 497b12d667..26e358efe8 100644 --- a/inflate.c +++ b/inflate.c @@ -110,19 +110,19 @@ int32_t Z_EXPORT PREFIX(inflateReset2)(PREFIX3(stream) *strm, int32_t windowBits /* extract wrap request from windowBits parameter */ if (windowBits < 0) { wrap = 0; - if (windowBits < -15) + if (windowBits < -MAX_WBITS) return Z_STREAM_ERROR; windowBits = -windowBits; } else { wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) - windowBits &= 15; + windowBits &= MAX_WBITS; #endif } /* set number of window bits, free window if different */ - if (windowBits && (windowBits < 8 || windowBits > 15)) + if (windowBits && (windowBits < MIN_WBITS || windowBits > MAX_WBITS)) return Z_STREAM_ERROR; if (state->window != NULL && state->wbits != (unsigned)windowBits) { ZFREE_WINDOW(strm, state->window); @@ -453,7 +453,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ if (state->wbits == 0) - state->wbits = 15; + state->wbits = MAX_WBITS; state->check = CRC32_INITIAL_VALUE; CRC2(state->check, hold); INITBITS(); @@ -478,7 +478,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; - if (len > 15 || len > state->wbits) { + if (len > MAX_WBITS || len > state->wbits) { SET_BAD("invalid window size"); break; } @@ -919,7 +919,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } /* length code */ - state->extra = (here.op & 15); + state->extra = (here.op & MAX_BITS); state->mode = LENEXT; Z_FALLTHROUGH; @@ -962,7 +962,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { break; } state->offset = here.val; - state->extra = (here.op & 15); + state->extra = (here.op & MAX_BITS); state->mode = DISTEXT; Z_FALLTHROUGH; diff --git a/inftrees.c b/inftrees.c index 78f6cf174b..f04d65f865 100644 --- a/inftrees.c +++ b/inftrees.c @@ -7,8 +7,6 @@ #include "zutil.h" #include "inftrees.h" -#define MAXBITS 15 - const char PREFIX(inflate_copyright)[] = " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome @@ -49,8 +47,8 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, const uint16_t *base; /* base value table to use */ const uint16_t *extra; /* extra bits table to use */ unsigned match; /* use base and extra for symbol >= match */ - uint16_t count[MAXBITS+1]; /* number of codes of each length */ - uint16_t offs[MAXBITS+1]; /* offsets in table for each length */ + uint16_t count[MAX_BITS+1]; /* number of codes of each length */ + uint16_t offs[MAX_BITS+1]; /* offsets in table for each length */ static const uint16_t lbase[31] = { /* Length codes 257..285 base */ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; @@ -98,14 +96,14 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, */ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) + for (len = 0; len <= MAX_BITS; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; - for (max = MAXBITS; max >= 1; max--) + for (max = MAX_BITS; max >= 1; max--) if (count[max] != 0) break; root = MIN(root, max); if (UNLIKELY(max == 0)) { /* no symbols to code at all */ @@ -123,7 +121,7 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, /* check for an over-subscribed or incomplete set of lengths */ left = 1; - for (len = 1; len <= MAXBITS; len++) { + for (len = 1; len <= MAX_BITS; len++) { left <<= 1; left -= count[len]; if (left < 0) return -1; /* over-subscribed */ @@ -133,7 +131,7 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; - for (len = 1; len < MAXBITS; len++) + for (len = 1; len < MAX_BITS; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ diff --git a/test/test_deflate_hash_head_0.cc b/test/test_deflate_hash_head_0.cc index 4a4e4b64ab..cbf601038c 100644 --- a/test/test_deflate_hash_head_0.cc +++ b/test/test_deflate_hash_head_0.cc @@ -64,7 +64,7 @@ TEST(deflate, hash_head_0) { EXPECT_EQ(err, Z_OK); memset(&strm, 0, sizeof(strm)); - err = PREFIX(inflateInit2)(&strm, -15); + err = PREFIX(inflateInit2)(&strm, -MAX_WBITS); EXPECT_EQ(err, Z_OK); strm.next_in = next_out; diff --git a/test/test_deflate_quick_block_open.cc b/test/test_deflate_quick_block_open.cc index b8703ae977..84a1ac8bbf 100644 --- a/test/test_deflate_quick_block_open.cc +++ b/test/test_deflate_quick_block_open.cc @@ -20,7 +20,7 @@ TEST(deflate_quick, block_open) { int err; memset(&strm, 0, sizeof(strm)); - err = PREFIX(deflateInit2)(&strm, 1, Z_DEFLATED, -15, 1, Z_FILTERED); + err = PREFIX(deflateInit2)(&strm, 1, Z_DEFLATED, -MAX_WBITS, 1, Z_FILTERED); EXPECT_EQ(err, Z_OK); z_const unsigned char next_in[495] = @@ -75,7 +75,7 @@ TEST(deflate_quick, block_open) { EXPECT_EQ(err, Z_OK); memset(&strm, 0, sizeof(strm)); - err = PREFIX(inflateInit2)(&strm, -15); + err = PREFIX(inflateInit2)(&strm, -MAX_WBITS); EXPECT_EQ(err, Z_OK); strm.next_in = next_out; diff --git a/test/test_raw.cc b/test/test_raw.cc index 69959d9e03..a013d4bb47 100644 --- a/test/test_raw.cc +++ b/test/test_raw.cc @@ -38,7 +38,7 @@ TEST(raw, basic) { EXPECT_EQ(err, Z_OK); memset(&stream, 0, sizeof(stream)); - err = PREFIX(inflateInit2)(&stream, -15); + err = PREFIX(inflateInit2)(&stream, -MAX_WBITS); EXPECT_EQ(err, Z_OK); stream.adler = 0x87654321; diff --git a/zconf-ng.h.in b/zconf-ng.h.in index 7f8983bf46..226f06a037 100644 --- a/zconf-ng.h.in +++ b/zconf-ng.h.in @@ -32,6 +32,9 @@ * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ +#ifndef MIN_WBITS +# define MIN_WBITS 8 /* 256 LZ77 window */ +#endif #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif diff --git a/zconf.h.in b/zconf.h.in index 0611fac68b..765e9c4e47 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -35,6 +35,9 @@ * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ +#ifndef MIN_WBITS +# define MIN_WBITS 8 /* 256 LZ77 window */ +#endif #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif diff --git a/zutil.h b/zutil.h index 3dd548d38b..7b9a8b0942 100644 --- a/zutil.h +++ b/zutil.h @@ -36,6 +36,9 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ #endif /* default windowBits for decompression. MAX_WBITS is for compression only */ +#define MAX_BITS 15 +/* all codes must not exceed MAX_BITS bits */ + #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 #else From 135641be1c125524564dd76ba97c2ff115384b43 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 18 Feb 2023 00:02:49 +0500 Subject: [PATCH 611/798] Fix warning: comparison of integer expressions of different signedness: 'size_t' {aka 'long unsigned int'} and 'int' [-Wsign-compare] Signed-off-by: Vladislav Shchapov --- test/gh1235.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/gh1235.c b/test/gh1235.c index 472282d1ee..7bf8738f34 100644 --- a/test/gh1235.c +++ b/test/gh1235.c @@ -7,7 +7,7 @@ int main(void) { unsigned char plain[32]; unsigned char compressed[130]; PREFIX3(stream) strm; - int bound; + z_size_t bound; z_size_t bytes; for (int i = 0; i <= 32; i++) { @@ -21,7 +21,7 @@ int main(void) { strm.avail_out = sizeof(compressed); if (PREFIX(deflate)(&strm, Z_FINISH) != Z_STREAM_END) return -1; if (strm.avail_in != 0) return -1; - printf("bytes = %2i, deflateBound = %2i, total_out = %2zi\n", i, bound, strm.total_out); + printf("bytes = %2i, deflateBound = %2zi, total_out = %2zi\n", i, (size_t)bound, (size_t)strm.total_out); if (bound < strm.total_out) return -1; if (PREFIX(deflateEnd)(&strm) != Z_OK) return -1; } @@ -32,7 +32,7 @@ int main(void) { } bound = PREFIX(compressBound)(i); if (PREFIX(compress2)(compressed, &bytes, plain, i, 1) != Z_OK) return -1; - printf("bytes = %2i, compressBound = %2i, total_out = %2zi\n", i, bound, (size_t)bytes); + printf("bytes = %2i, compressBound = %2zi, total_out = %2zi\n", i, (size_t)bound, (size_t)bytes); if (bytes > bound) return -1; } return 0; From c970422caa6b32d0488e5dede95719eb4a9a5bd8 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Wed, 7 Dec 2022 21:48:31 +0200 Subject: [PATCH 612/798] Fix definition of z_size_t to match documentation of legacy zlib API. --- PORTING.md | 3 ++- compress.c | 12 ++++++------ inflate.c | 4 ++-- test/example.c | 16 ++++++++-------- test/test_compress.cc | 2 +- test/test_compress_bound.cc | 2 +- uncompr.c | 6 +++--- zbuild.h | 13 ++++++++++++- 8 files changed, 35 insertions(+), 23 deletions(-) diff --git a/PORTING.md b/PORTING.md index 3875ccc965..c48522e3a0 100644 --- a/PORTING.md +++ b/PORTING.md @@ -43,7 +43,8 @@ certain value will need to be updated. - Static library is *libz.a* on Unix and macOS, or *zlib.lib* on Windows - Shared library is *libz.so* on Unix, *libz.dylib* on macOS, or *zlib1.dll* on Windows -- Type `z_size_t` is *unsigned long* +- Type `z_size_t` is *unsigned __int64* on 64-bit Windows, and *unsigned long* on 32-bit Windows, Unix and macOS +- Type `z_uintmax_t` is *unsigned long* in zlib-compat mode, and *size_t* with zlib-ng API zlib-ng native mode ------------------- diff --git a/compress.c b/compress.c index 44f8dd9eb3..66118e4f4b 100644 --- a/compress.c +++ b/compress.c @@ -28,8 +28,8 @@ memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ -int Z_EXPORT PREFIX(compress2)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, - z_size_t sourceLen, int level) { +int Z_EXPORT PREFIX(compress2)(unsigned char *dest, z_uintmax_t *destLen, const unsigned char *source, + z_uintmax_t sourceLen, int level) { PREFIX3(stream) stream; int err; const unsigned int max = (unsigned int)-1; @@ -63,14 +63,14 @@ int Z_EXPORT PREFIX(compress2)(unsigned char *dest, z_size_t *destLen, const uns err = PREFIX(deflate)(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); } while (err == Z_OK); - *destLen = (z_size_t)stream.total_out; + *destLen = stream.total_out; PREFIX(deflateEnd)(&stream); return err == Z_STREAM_END ? Z_OK : err; } /* =========================================================================== */ -int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t sourceLen) { +int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_uintmax_t *destLen, const unsigned char *source, z_uintmax_t sourceLen) { return PREFIX(compress2)(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); } @@ -78,8 +78,8 @@ int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsi If the default memLevel or windowBits for deflateInit() is changed, then this function needs to be updated. */ -z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) { - z_size_t complen = DEFLATE_BOUND_COMPLEN(sourceLen); +z_uintmax_t Z_EXPORT PREFIX(compressBound)(z_uintmax_t sourceLen) { + z_uintmax_t complen = DEFLATE_BOUND_COMPLEN(sourceLen); if (complen > 0) /* Architecture-specific code provided an upper bound. */ diff --git a/inflate.c b/inflate.c index 26e358efe8..506bb2a50a 100644 --- a/inflate.c +++ b/inflate.c @@ -1292,8 +1292,8 @@ int32_t Z_EXPORT PREFIX(inflateSync)(PREFIX3(stream) *strm) { in = strm->total_in; out = strm->total_out; PREFIX(inflateReset)(strm); - strm->total_in = (z_size_t)in; - strm->total_out = (z_size_t)out; + strm->total_in = (z_uintmax_t)in; /* Can't use z_size_t here as it will overflow on 64-bit Windows */ + strm->total_out = (z_uintmax_t)out; state->flags = flags; state->mode = TYPE; return Z_OK; diff --git a/test/example.c b/test/example.c index 8644bdce5a..b500af92c6 100644 --- a/test/example.c +++ b/test/example.c @@ -26,13 +26,13 @@ static unsigned long dictId = 0; /* Adler32 value of the dictionary */ #define MAX_DICTIONARY_SIZE 32768 -void test_compress (unsigned char *compr, z_size_t comprLen,unsigned char *uncompr, z_size_t uncomprLen); +void test_compress (unsigned char *compr, z_uintmax_t comprLen, unsigned char *uncompr, z_uintmax_t uncomprLen); void test_gzio (const char *fname, unsigned char *uncompr, z_size_t uncomprLen); void test_deflate (unsigned char *compr, size_t comprLen); void test_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen); void test_large_deflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen, int zng_params); void test_large_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen); -void test_flush (unsigned char *compr, z_size_t *comprLen); +void test_flush (unsigned char *compr, z_uintmax_t *comprLen); void test_sync (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen); void test_dict_deflate (unsigned char *compr, size_t comprLen); void test_dict_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen); @@ -63,11 +63,11 @@ void error(const char *format, ...) { /* =========================================================================== * Test compress() and uncompress() */ -void test_compress(unsigned char *compr, z_size_t comprLen, unsigned char *uncompr, z_size_t uncomprLen) { +void test_compress(unsigned char *compr, z_uintmax_t comprLen, unsigned char *uncompr, z_uintmax_t uncomprLen) { int err; - size_t len = strlen(hello)+1; + unsigned int len = (unsigned int)strlen(hello)+1; - err = PREFIX(compress)(compr, &comprLen, (const unsigned char*)hello, (z_size_t)len); + err = PREFIX(compress)(compr, &comprLen, (const unsigned char*)hello, len); CHECK_ERR(err, "compress"); strcpy((char*)uncompr, "garbage"); @@ -402,7 +402,7 @@ void test_large_inflate(unsigned char *compr, size_t comprLen, unsigned char *un /* =========================================================================== * Test deflate() with full flush */ -void test_flush(unsigned char *compr, z_size_t *comprLen) { +void test_flush(unsigned char *compr, z_uintmax_t *comprLen) { PREFIX3(stream) c_stream; /* compression stream */ int err; unsigned int len = (unsigned int)strlen(hello)+1; @@ -953,8 +953,8 @@ void test_deflate_tune(unsigned char *compr, size_t comprLen) { */ int main(int argc, char *argv[]) { unsigned char *compr, *uncompr; - z_size_t comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ - z_size_t uncomprLen = comprLen; + z_uintmax_t comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + z_uintmax_t uncomprLen = comprLen; static const char* myVersion = PREFIX2(VERSION); if (zVersion()[0] != myVersion[0]) { diff --git a/test/test_compress.cc b/test/test_compress.cc index 9885b33014..e069b69d31 100644 --- a/test/test_compress.cc +++ b/test/test_compress.cc @@ -18,7 +18,7 @@ TEST(compress, basic) { uint8_t compr[128], uncompr[128]; - z_size_t compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); + z_uintmax_t compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); int err; err = PREFIX(compress)(compr, &compr_len, (const unsigned char *)hello, hello_len); diff --git a/test/test_compress_bound.cc b/test/test_compress_bound.cc index d51452b235..b83b59f4fb 100644 --- a/test/test_compress_bound.cc +++ b/test/test_compress_bound.cc @@ -35,7 +35,7 @@ class compress_bound_variant : public testing::TestWithParam { } for (z_size_t i = 0; i < MAX_LENGTH; i++) { - z_size_t dest_len = sizeof(dest); + z_uintmax_t dest_len = sizeof(dest); /* calculate actual output length */ estimate_len = PREFIX(compressBound)(i); diff --git a/uncompr.c b/uncompr.c index 54ed57fdbd..311eca2b06 100644 --- a/uncompr.c +++ b/uncompr.c @@ -22,11 +22,11 @@ Z_DATA_ERROR if the input data was corrupted, including if the input data is an incomplete zlib stream. */ -int Z_EXPORT PREFIX(uncompress2)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t *sourceLen) { +int Z_EXPORT PREFIX(uncompress2)(unsigned char *dest, z_uintmax_t *destLen, const unsigned char *source, z_uintmax_t *sourceLen) { PREFIX3(stream) stream; int err; const unsigned int max = (unsigned int)-1; - z_size_t len, left; + z_uintmax_t len, left; unsigned char buf[1]; /* for detection of incomplete stream when *destLen == 0 */ len = *sourceLen; @@ -75,6 +75,6 @@ int Z_EXPORT PREFIX(uncompress2)(unsigned char *dest, z_size_t *destLen, const u err; } -int Z_EXPORT PREFIX(uncompress)(unsigned char *dest, z_size_t *destLen, const unsigned char *source, z_size_t sourceLen) { +int Z_EXPORT PREFIX(uncompress)(unsigned char *dest, z_uintmax_t *destLen, const unsigned char *source, z_uintmax_t sourceLen) { return PREFIX(uncompress2)(dest, destLen, source, &sourceLen); } diff --git a/zbuild.h b/zbuild.h index c7df4b1e69..da21b45ef8 100644 --- a/zbuild.h +++ b/zbuild.h @@ -85,7 +85,11 @@ # define PREFIX3(x) z_ ## x # define PREFIX4(x) x ## 64 # define zVersion zlibVersion -# define z_size_t unsigned long +# if defined(_WIN64) +# define z_size_t unsigned __int64 +# else +# define z_size_t unsigned long +# endif #else # define PREFIX(x) zng_ ## x # define PREFIX2(x) ZLIBNG_ ## x @@ -95,6 +99,13 @@ # define z_size_t size_t #endif +/* In zlib-compat some functions and types use unsigned long, but zlib-ng use size_t */ +#if defined(ZLIB_COMPAT) +# define z_uintmax_t unsigned long +#else +# define z_uintmax_t size_t +#endif + /* Minimum of a and b. */ #define MIN(a, b) ((a) > (b) ? (b) : (a)) /* Maximum of a and b. */ From 3cebd4721153aa813252a8c862d9c97ccf529509 Mon Sep 17 00:00:00 2001 From: Dougall Johnson Date: Mon, 22 Aug 2022 11:39:35 +1000 Subject: [PATCH 613/798] Inflate: refill unconditionally --- inffast_tpl.h | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/inffast_tpl.h b/inffast_tpl.h index e17e59241e..c209021b92 100644 --- a/inffast_tpl.h +++ b/inffast_tpl.h @@ -145,14 +145,22 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { window is overwritten then future matches with far distances will fail to copy correctly. */ extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); + /* This is extremely latency sensitive, so empty inline assembly blocks are + used to prevent the compiler from reassociating. */ +#define REFILL() do { \ + hold |= load_64_bits(in, bits); \ + in += 7; \ + __asm__ volatile ("" : "+r"(in)); \ + uint64_t tmp = ((bits >> 3) & 7); \ + __asm__ volatile ("" : "+r"(tmp)); \ + in -= tmp; \ + bits |= 56; \ + } while (0) + /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { - if (bits < MAX_BITS) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } + REFILL(); here = lcode + (hold & lmask); dolen: DROPBITS(here->bits); @@ -164,20 +172,10 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { *out++ = (unsigned char)(here->val); } else if (op & 16) { /* length base */ len = here->val; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } + op &= MAX_BITS; /* number of extra bits */ len += BITS(op); DROPBITS(op); Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < MAX_BITS) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } here = dcode + (hold & dmask); dodist: DROPBITS(here->bits); @@ -185,11 +183,6 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { if (op & 16) { /* distance base */ dist = here->val; op &= MAX_BITS; /* number of extra bits */ - if (bits < op) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } dist += BITS(op); #ifdef INFLATE_STRICT if (dist > dmax) { From 6a74e9294f12e879d792376bf98ed720f7362d7d Mon Sep 17 00:00:00 2001 From: Dougall Johnson Date: Mon, 22 Aug 2022 11:44:41 +1000 Subject: [PATCH 614/798] Inflate: add fast-path for literals --- inffast_tpl.h | 20 ++++++++++++++------ inflate_p.h | 4 ++-- zutil.h | 2 ++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/inffast_tpl.h b/inffast_tpl.h index c209021b92..9ddd187d84 100644 --- a/inffast_tpl.h +++ b/inffast_tpl.h @@ -145,15 +145,10 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { window is overwritten then future matches with far distances will fail to copy correctly. */ extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); - /* This is extremely latency sensitive, so empty inline assembly blocks are - used to prevent the compiler from reassociating. */ #define REFILL() do { \ hold |= load_64_bits(in, bits); \ in += 7; \ - __asm__ volatile ("" : "+r"(in)); \ - uint64_t tmp = ((bits >> 3) & 7); \ - __asm__ volatile ("" : "+r"(tmp)); \ - in -= tmp; \ + in -= ((bits >> 3) & 7); \ bits |= 56; \ } while (0) @@ -162,6 +157,16 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { do { REFILL(); here = lcode + (hold & lmask); + if (here->op == 0) { + *out++ = (unsigned char)(here->val); + DROPBITS(here->bits); + here = lcode + (hold & lmask); + if (here->op == 0) { + *out++ = (unsigned char)(here->val); + DROPBITS(here->bits); + here = lcode + (hold & lmask); + } + } dolen: DROPBITS(here->bits); op = here->op; @@ -177,6 +182,9 @@ void Z_INTERNAL INFLATE_FAST(PREFIX3(stream) *strm, uint32_t start) { DROPBITS(op); Tracevv((stderr, "inflate: length %u\n", len)); here = dcode + (hold & dmask); + if (bits < MAX_BITS + MAX_DIST_EXTRA_BITS) { + REFILL(); + } dodist: DROPBITS(here->bits); op = here->op; diff --git a/inflate_p.h b/inflate_p.h index 2b57b317e7..a007cd05df 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -132,8 +132,8 @@ strm->msg = (char *)errmsg; \ } while (0) -#define INFLATE_FAST_MIN_HAVE 8 -#define INFLATE_FAST_MIN_LEFT 258 +#define INFLATE_FAST_MIN_HAVE 15 +#define INFLATE_FAST_MIN_LEFT 260 /* Load 64 bits from IN and place the bytes at offset BITS in the result. */ static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { diff --git a/zutil.h b/zutil.h index 7b9a8b0942..663616b44d 100644 --- a/zutil.h +++ b/zutil.h @@ -38,6 +38,8 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ #define MAX_BITS 15 /* all codes must not exceed MAX_BITS bits */ +#define MAX_DIST_EXTRA_BITS 13 +/* maximum number of extra distance bits */ #if MAX_MEM_LEVEL >= 8 # define DEF_MEM_LEVEL 8 From fdb87d63a5963e2d7112e10151d9ca413bbefb62 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Fri, 17 Feb 2023 21:41:46 +0500 Subject: [PATCH 615/798] Split crc32 pclmulqdq and vpclmulqdq implementations Signed-off-by: Vladislav Shchapov --- CMakeLists.txt | 6 +-- arch/x86/Makefile.in | 20 +++++----- arch/x86/crc32_fold_pclmulqdq_tpl.h | 21 +++++----- arch/x86/crc32_fold_vpclmulqdq.c | 19 --------- arch/x86/crc32_fold_vpclmulqdq_tpl.h | 6 +-- arch/x86/crc32_pclmulqdq.c | 30 ++++++++++++++ ...fold_pclmulqdq.c => crc32_pclmulqdq_tpl.h} | 40 +++++++++++-------- arch/x86/crc32_vpclmulqdq.c | 17 ++++++++ configure | 8 ++-- cpu_features.h | 7 ++++ functable.c | 10 +++++ win32/Makefile.msc | 5 ++- 12 files changed, 120 insertions(+), 69 deletions(-) delete mode 100644 arch/x86/crc32_fold_vpclmulqdq.c create mode 100644 arch/x86/crc32_pclmulqdq.c rename arch/x86/{crc32_fold_pclmulqdq.c => crc32_pclmulqdq_tpl.h} (92%) create mode 100644 arch/x86/crc32_vpclmulqdq.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d85ccf010e..265772dd26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -847,7 +847,7 @@ if(WITH_OPTIM) check_pclmulqdq_intrinsics() if(HAVE_PCLMULQDQ_INTRIN AND HAVE_SSSE3_INTRIN) add_definitions(-DX86_PCLMULQDQ_CRC) - set(PCLMULQDQ_SRCS ${ARCHDIR}/crc32_fold_pclmulqdq.c) + set(PCLMULQDQ_SRCS ${ARCHDIR}/crc32_pclmulqdq.c) add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") @@ -856,10 +856,10 @@ if(WITH_OPTIM) check_vpclmulqdq_intrinsics() if(HAVE_VPCLMULQDQ_INTRIN AND HAVE_AVX512_INTRIN) add_definitions(-DX86_VPCLMULQDQ_CRC) - set(VPCLMULQDQ_SRCS ${ARCHDIR}/crc32_fold_vpclmulqdq.c) + set(VPCLMULQDQ_SRCS ${ARCHDIR}/crc32_vpclmulqdq.c) add_feature_info(VPCLMUL_CRC 1 "Support CRC hash generation using VPCLMULQDQ, using \"${VPCLMULFLAG} ${AVX512FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${VPCLMULQDQ_SRCS}) - set_property(SOURCE ${VPCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${VPCLMULFLAG} ${AVX512FLAG} ${NOLTOFLAG}") + set_property(SOURCE ${VPCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG} ${VPCLMULFLAG} ${AVX512FLAG} ${NOLTOFLAG}") else() set(WITH_VPCLMULQDQ OFF) endif() diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index a3d5283b91..4cebe55531 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -37,8 +37,8 @@ all: \ compare256_avx2.o compare256_avx2.lo \ compare256_sse2.o compare256_sse2.lo \ insert_string_sse42.o insert_string_sse42.lo \ - crc32_fold_pclmulqdq.o crc32_fold_pclmulqdq.lo \ - crc32_fold_vpclmulqdq.o crc32_fold_vpclmulqdq.lo \ + crc32_pclmulqdq.o crc32_pclmulqdq.lo \ + crc32_vpclmulqdq.o crc32_vpclmulqdq.lo \ slide_hash_avx2.o slide_hash_avx2.lo \ slide_hash_sse2.o slide_hash_sse2.lo @@ -84,17 +84,17 @@ insert_string_sse42.o: insert_string_sse42.lo: $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse42.c -crc32_fold_pclmulqdq.o: - $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c +crc32_pclmulqdq.o: + $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_pclmulqdq.c -crc32_fold_pclmulqdq.lo: - $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c +crc32_pclmulqdq.lo: + $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_pclmulqdq.c -crc32_fold_vpclmulqdq.o: - $(CC) $(CFLAGS) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_vpclmulqdq.c +crc32_vpclmulqdq.o: + $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_vpclmulqdq.c -crc32_fold_vpclmulqdq.lo: - $(CC) $(SFLAGS) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_vpclmulqdq.c +crc32_vpclmulqdq.lo: + $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_vpclmulqdq.c slide_hash_avx2.o: $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx2.c diff --git a/arch/x86/crc32_fold_pclmulqdq_tpl.h b/arch/x86/crc32_fold_pclmulqdq_tpl.h index 47bbc0111b..da1810bf7b 100644 --- a/arch/x86/crc32_fold_pclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_pclmulqdq_tpl.h @@ -17,12 +17,10 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef X86_PCLMULQDQ_CRC - #ifdef COPY -Z_INTERNAL void crc32_fold_pclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL void CRC32_FOLD_COPY_NAME (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { #else -Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { +Z_INTERNAL void CRC32_FOLD_NAME (crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { #endif unsigned long algn_diff; __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; @@ -61,7 +59,7 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t _mm_storeu_si128((__m128i *)dst, xmm_crc_part); dst += algn_diff; #else - XOR_INITIAL(xmm_crc_part); + XOR_INITIAL128(xmm_crc_part); if (algn_diff < 4 && init_crc != 0) { xmm_t0 = xmm_crc_part; @@ -79,8 +77,8 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len -= algn_diff; } -#ifdef X86_VPCLMULQDQ_CRC - if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { +#ifdef X86_VPCLMULQDQ + if (len >= 256) { #ifdef COPY size_t n = fold_16_vpclmulqdq_copy(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); dst += n; @@ -110,7 +108,7 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t _mm_storeu_si128((__m128i *)dst + 3, xmm_t3); dst += 64; #else - XOR_INITIAL(xmm_t0); + XOR_INITIAL128(xmm_t0); #endif xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); @@ -135,7 +133,7 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); dst += 48; #else - XOR_INITIAL(xmm_t0); + XOR_INITIAL128(xmm_t0); #endif fold_3(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); @@ -153,7 +151,7 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); dst += 32; #else - XOR_INITIAL(xmm_t0); + XOR_INITIAL128(xmm_t0); #endif fold_2(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); @@ -167,7 +165,7 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t _mm_storeu_si128((__m128i *)dst, xmm_t0); dst += 16; #else - XOR_INITIAL(xmm_t0); + XOR_INITIAL128(xmm_t0); #endif fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); @@ -186,4 +184,3 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t crc32_fold_save((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); } -#endif diff --git a/arch/x86/crc32_fold_vpclmulqdq.c b/arch/x86/crc32_fold_vpclmulqdq.c deleted file mode 100644 index d9c43be742..0000000000 --- a/arch/x86/crc32_fold_vpclmulqdq.c +++ /dev/null @@ -1,19 +0,0 @@ -/* crc32_fold_vpclmulqdq.c -- VPCMULQDQ-based CRC32 folding implementation. - * Copyright Wangyang Guo (wangyang.guo@intel.com) - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifdef X86_VPCLMULQDQ_CRC -#include "../../zbuild.h" -#include "../../fallback_builtins.h" - -#include - -#define ONCE(op) if (first) { first = 0; op; } -#define XOR_INITIAL(where) ONCE(where = _mm512_xor_si512(where, zmm_initial)) - -#include "crc32_fold_vpclmulqdq_tpl.h" -#define COPY -#include "crc32_fold_vpclmulqdq_tpl.h" - -#endif diff --git a/arch/x86/crc32_fold_vpclmulqdq_tpl.h b/arch/x86/crc32_fold_vpclmulqdq_tpl.h index 3d27cb3dfb..67f08e1281 100644 --- a/arch/x86/crc32_fold_vpclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_vpclmulqdq_tpl.h @@ -4,10 +4,10 @@ */ #ifdef COPY -Z_INTERNAL size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, +static size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len) { #else -Z_INTERNAL size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, +static size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, __m128i init_crc, int32_t first) { __m512i zmm_initial = _mm512_zextsi128_si512(init_crc); @@ -25,7 +25,7 @@ Z_INTERNAL size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, zmm_crc0 = _mm512_setzero_si512(); zmm_t0 = _mm512_loadu_si512((__m512i *)src); #ifndef COPY - XOR_INITIAL(zmm_t0); + XOR_INITIAL512(zmm_t0); #endif zmm_crc1 = _mm512_loadu_si512((__m512i *)src + 1); zmm_crc2 = _mm512_loadu_si512((__m512i *)src + 2); diff --git a/arch/x86/crc32_pclmulqdq.c b/arch/x86/crc32_pclmulqdq.c new file mode 100644 index 0000000000..b4cdeb360e --- /dev/null +++ b/arch/x86/crc32_pclmulqdq.c @@ -0,0 +1,30 @@ +/* + * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ + * instruction. + * + * A white paper describing this algorithm can be found at: + * doc/crc-pclmulqdq.pdf + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Copyright (C) 2016 Marian Beermann (support for initial value) + * Authors: + * Wajdi Feghali + * Jim Guilford + * Vinodh Gopal + * Erdinc Ozturk + * Jim Kukunas + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef X86_PCLMULQDQ_CRC + +#define CRC32_FOLD_COPY_NAME crc32_fold_pclmulqdq_copy +#define CRC32_FOLD_NAME crc32_fold_pclmulqdq +#define CRC32_FOLD_RESET_NAME crc32_fold_pclmulqdq_reset +#define CRC32_FOLD_FINAL_NAME crc32_fold_pclmulqdq_final +#define CRC32_NAME crc32_pclmulqdq + +#include "crc32_pclmulqdq_tpl.h" + +#endif diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_pclmulqdq_tpl.h similarity index 92% rename from arch/x86/crc32_fold_pclmulqdq.c rename to arch/x86/crc32_pclmulqdq_tpl.h index ecee0c578c..6726e34919 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_pclmulqdq_tpl.h @@ -17,25 +17,25 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifdef X86_PCLMULQDQ_CRC #include "../../zbuild.h" #include #include #include // _mm_extract_epi32 - -#include "x86_features.h" -#include "cpu_features.h" +#ifdef X86_VPCLMULQDQ +#include +#endif #include "../../crc32_fold.h" #include "../../crc32_braid_p.h" +#include "../../fallback_builtins.h" #include -#ifdef X86_VPCLMULQDQ_CRC -extern size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, +#ifdef X86_VPCLMULQDQ +static size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, __m128i init_crc, int32_t first); -extern size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, +static size_t fold_16_vpclmulqdq_copy(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len); #endif @@ -246,18 +246,27 @@ static inline void crc32_fold_save(__m128i *fold, const __m128i *fold0, const __ _mm_storeu_si128(fold + 3, *fold3); } -Z_INTERNAL uint32_t crc32_fold_pclmulqdq_reset(crc32_fold *crc) { +Z_INTERNAL uint32_t CRC32_FOLD_RESET_NAME (crc32_fold *crc) { __m128i xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); __m128i xmm_zero = _mm_setzero_si128(); crc32_fold_save((__m128i *)crc->fold, &xmm_crc0, &xmm_zero, &xmm_zero, &xmm_zero); return 0; } -#define ONCE(op) if (first) { first = 0; op; } -#define XOR_INITIAL(where) ONCE(where = _mm_xor_si128(where, xmm_initial)) +#define ONCE(op) if (first) { first = 0; op; } +#define XOR_INITIAL128(where) ONCE(where = _mm_xor_si128(where, xmm_initial)) +#ifdef X86_VPCLMULQDQ +#define XOR_INITIAL512(where) ONCE(where = _mm512_xor_si512(where, zmm_initial)) +#endif +#ifdef X86_VPCLMULQDQ +#include "crc32_fold_vpclmulqdq_tpl.h" +#endif #include "crc32_fold_pclmulqdq_tpl.h" #define COPY +#ifdef X86_VPCLMULQDQ +#include "crc32_fold_vpclmulqdq_tpl.h" +#endif #include "crc32_fold_pclmulqdq_tpl.h" static const unsigned ALIGNED_(16) crc_k[] = { @@ -277,7 +286,7 @@ static const unsigned ALIGNED_(16) crc_mask2[4] = { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; -Z_INTERNAL uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc) { +Z_INTERNAL uint32_t CRC32_FOLD_FINAL_NAME (crc32_fold *crc) { const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3; @@ -342,15 +351,14 @@ Z_INTERNAL uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc) { return crc->value; } -Z_INTERNAL uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len) { +Z_INTERNAL uint32_t CRC32_NAME (uint32_t crc32, const uint8_t *buf, size_t len) { /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for * these short lengths might also prove to be effective */ if (len < 64) return PREFIX(crc32_braid)(crc32, buf, len); crc32_fold ALIGNED_(16) crc_state; - crc32_fold_pclmulqdq_reset(&crc_state); - crc32_fold_pclmulqdq(&crc_state, buf, len, crc32); - return crc32_fold_pclmulqdq_final(&crc_state); + CRC32_FOLD_RESET_NAME (&crc_state); + CRC32_FOLD_NAME (&crc_state, buf, len, crc32); + return CRC32_FOLD_FINAL_NAME (&crc_state); } -#endif diff --git a/arch/x86/crc32_vpclmulqdq.c b/arch/x86/crc32_vpclmulqdq.c new file mode 100644 index 0000000000..b05ddb9a2d --- /dev/null +++ b/arch/x86/crc32_vpclmulqdq.c @@ -0,0 +1,17 @@ +/* crc32_vpclmulqdq.c -- VPCMULQDQ-based CRC32 folding implementation. + * Copyright Wangyang Guo (wangyang.guo@intel.com) + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#if defined(X86_PCLMULQDQ_CRC) && defined(X86_VPCLMULQDQ_CRC) + +#define X86_VPCLMULQDQ +#define CRC32_FOLD_COPY_NAME crc32_fold_vpclmulqdq_copy +#define CRC32_FOLD_NAME crc32_fold_vpclmulqdq +#define CRC32_FOLD_RESET_NAME crc32_fold_vpclmulqdq_reset +#define CRC32_FOLD_FINAL_NAME crc32_fold_vpclmulqdq_final +#define CRC32_NAME crc32_vpclmulqdq + +#include "crc32_pclmulqdq_tpl.h" + +#endif diff --git a/configure b/configure index fdb5b69d7e..5dd146386c 100755 --- a/configure +++ b/configure @@ -1629,8 +1629,8 @@ case "${ARCH}" in if test ${HAVE_PCLMULQDQ_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_PCLMULQDQ_CRC" SFLAGS="${SFLAGS} -DX86_PCLMULQDQ_CRC" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_fold_pclmulqdq.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_fold_pclmulqdq.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_pclmulqdq.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_pclmulqdq.lo" if test $buildvpclmulqdq -eq 1; then check_vpclmulqdq_intrinsics @@ -1638,8 +1638,8 @@ case "${ARCH}" in if test ${HAVE_VPCLMULQDQ_INTRIN} -eq 1 && test ${HAVE_AVX512_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_VPCLMULQDQ_CRC" SFLAGS="${SFLAGS} -DX86_VPCLMULQDQ_CRC" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_fold_vpclmulqdq.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_fold_vpclmulqdq.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_vpclmulqdq.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_vpclmulqdq.lo" fi fi fi diff --git a/cpu_features.h b/cpu_features.h index c098ee2d34..22d70da3d9 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -70,6 +70,13 @@ extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t extern uint32_t crc32_fold_pclmulqdq_final(crc32_fold *crc); extern uint32_t crc32_pclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len); #endif +#if defined(X86_PCLMULQDQ_CRC) && defined(X86_VPCLMULQDQ_CRC) +extern uint32_t crc32_fold_vpclmulqdq_reset(crc32_fold *crc); +extern void crc32_fold_vpclmulqdq_copy(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern void crc32_fold_vpclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); +extern uint32_t crc32_fold_vpclmulqdq_final(crc32_fold *crc); +extern uint32_t crc32_vpclmulqdq(uint32_t crc32, const uint8_t *buf, size_t len); +#endif /* memory chunking */ extern uint32_t chunksize_c(void); diff --git a/functable.c b/functable.c index 23106b33d2..da9d10ec5b 100644 --- a/functable.c +++ b/functable.c @@ -130,6 +130,16 @@ static void init_functable(void) { ft.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; } #endif + // X86 - VPCLMULQDQ +#if defined(X86_PCLMULQDQ_CRC) && defined(X86_VPCLMULQDQ_CRC) + if (x86_cpu_has_pclmulqdq && x86_cpu_has_avx512 && x86_cpu_has_vpclmulqdq) { + ft.crc32 = &crc32_vpclmulqdq; + ft.crc32_fold = &crc32_fold_vpclmulqdq; + ft.crc32_fold_copy = &crc32_fold_vpclmulqdq_copy; + ft.crc32_fold_final = &crc32_fold_vpclmulqdq_final; + ft.crc32_fold_reset = &crc32_fold_vpclmulqdq_reset; + } +#endif // ARM - NEON diff --git a/win32/Makefile.msc b/win32/Makefile.msc index f2f0631a15..d2a98d6f0a 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -64,7 +64,7 @@ OBJS = \ crc32_braid.obj \ crc32_braid_comb.obj \ crc32_fold.obj \ - crc32_fold_pclmulqdq.obj \ + crc32_pclmulqdq.obj \ deflate.obj \ deflate_fast.obj \ deflate_huff.obj \ @@ -206,7 +206,8 @@ cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h crc32_braid.obj: $(SRCDIR)/crc32_braid.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h crc32_braid_comb.obj: $(SRCDIR)/crc32_braid_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h $(SRCDIR)/crc32_braid_comb_p.h crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h -crc32_fold_pclmulqdq.obj: $(SRCDIR)/arch/x86/crc32_fold_pclmulqdq.c $(SRCDIR)/crc32_fold.h $(SRCDIR)/zbuild.h +crc32_pclmulqdq.obj: $(SRCDIR)/arch/x86/crc32_pclmulqdq.c $(SRCDIR)/arch/x86/crc32_pclmulqdq_tpl.h $(SRCDIR)/arch/x86/crc32_fold_pclmulqdq_tpl.h \ + $(SRCDIR)/crc32_fold.h $(SRCDIR)/zbuild.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_huff.obj: $(SRCDIR)/deflate_huff.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h From 330f2ffb3f66dea60c9e7a5610de0d9cc5b576fb Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 18 Feb 2023 14:18:18 +0500 Subject: [PATCH 616/798] Fix formatting Signed-off-by: Vladislav Shchapov --- arch/x86/crc32_fold_pclmulqdq_tpl.h | 4 ++-- arch/x86/crc32_pclmulqdq.c | 10 +++++----- arch/x86/crc32_pclmulqdq_tpl.h | 25 ++++++++++++------------- arch/x86/crc32_vpclmulqdq.c | 10 +++++----- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq_tpl.h b/arch/x86/crc32_fold_pclmulqdq_tpl.h index da1810bf7b..3e79928317 100644 --- a/arch/x86/crc32_fold_pclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_pclmulqdq_tpl.h @@ -18,9 +18,9 @@ */ #ifdef COPY -Z_INTERNAL void CRC32_FOLD_COPY_NAME (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL void CRC32_FOLD_COPY(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { #else -Z_INTERNAL void CRC32_FOLD_NAME (crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { +Z_INTERNAL void CRC32_FOLD(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { #endif unsigned long algn_diff; __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; diff --git a/arch/x86/crc32_pclmulqdq.c b/arch/x86/crc32_pclmulqdq.c index b4cdeb360e..9383b7a2ba 100644 --- a/arch/x86/crc32_pclmulqdq.c +++ b/arch/x86/crc32_pclmulqdq.c @@ -19,11 +19,11 @@ #ifdef X86_PCLMULQDQ_CRC -#define CRC32_FOLD_COPY_NAME crc32_fold_pclmulqdq_copy -#define CRC32_FOLD_NAME crc32_fold_pclmulqdq -#define CRC32_FOLD_RESET_NAME crc32_fold_pclmulqdq_reset -#define CRC32_FOLD_FINAL_NAME crc32_fold_pclmulqdq_final -#define CRC32_NAME crc32_pclmulqdq +#define CRC32_FOLD_COPY crc32_fold_pclmulqdq_copy +#define CRC32_FOLD crc32_fold_pclmulqdq +#define CRC32_FOLD_RESET crc32_fold_pclmulqdq_reset +#define CRC32_FOLD_FINAL crc32_fold_pclmulqdq_final +#define CRC32 crc32_pclmulqdq #include "crc32_pclmulqdq_tpl.h" diff --git a/arch/x86/crc32_pclmulqdq_tpl.h b/arch/x86/crc32_pclmulqdq_tpl.h index 6726e34919..04dad4b60d 100644 --- a/arch/x86/crc32_pclmulqdq_tpl.h +++ b/arch/x86/crc32_pclmulqdq_tpl.h @@ -23,7 +23,7 @@ #include #include // _mm_extract_epi32 #ifdef X86_VPCLMULQDQ -#include +# include #endif #include "../../crc32_fold.h" @@ -187,7 +187,6 @@ static const unsigned ALIGNED_(32) pshufb_shf_table[60] = { static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, __m128i *xmm_crc_part) { - const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); const __m128i xmm_mask3 = _mm_set1_epi32((int32_t)0x80808080); @@ -246,26 +245,26 @@ static inline void crc32_fold_save(__m128i *fold, const __m128i *fold0, const __ _mm_storeu_si128(fold + 3, *fold3); } -Z_INTERNAL uint32_t CRC32_FOLD_RESET_NAME (crc32_fold *crc) { +Z_INTERNAL uint32_t CRC32_FOLD_RESET(crc32_fold *crc) { __m128i xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); __m128i xmm_zero = _mm_setzero_si128(); crc32_fold_save((__m128i *)crc->fold, &xmm_crc0, &xmm_zero, &xmm_zero, &xmm_zero); return 0; } -#define ONCE(op) if (first) { first = 0; op; } -#define XOR_INITIAL128(where) ONCE(where = _mm_xor_si128(where, xmm_initial)) +#define ONCE(op) if (first) { first = 0; op; } +#define XOR_INITIAL128(where) ONCE(where = _mm_xor_si128(where, xmm_initial)) #ifdef X86_VPCLMULQDQ -#define XOR_INITIAL512(where) ONCE(where = _mm512_xor_si512(where, zmm_initial)) +# define XOR_INITIAL512(where) ONCE(where = _mm512_xor_si512(where, zmm_initial)) #endif #ifdef X86_VPCLMULQDQ -#include "crc32_fold_vpclmulqdq_tpl.h" +# include "crc32_fold_vpclmulqdq_tpl.h" #endif #include "crc32_fold_pclmulqdq_tpl.h" #define COPY #ifdef X86_VPCLMULQDQ -#include "crc32_fold_vpclmulqdq_tpl.h" +# include "crc32_fold_vpclmulqdq_tpl.h" #endif #include "crc32_fold_pclmulqdq_tpl.h" @@ -286,7 +285,7 @@ static const unsigned ALIGNED_(16) crc_mask2[4] = { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; -Z_INTERNAL uint32_t CRC32_FOLD_FINAL_NAME (crc32_fold *crc) { +Z_INTERNAL uint32_t CRC32_FOLD_FINAL(crc32_fold *crc) { const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3; @@ -351,14 +350,14 @@ Z_INTERNAL uint32_t CRC32_FOLD_FINAL_NAME (crc32_fold *crc) { return crc->value; } -Z_INTERNAL uint32_t CRC32_NAME (uint32_t crc32, const uint8_t *buf, size_t len) { +Z_INTERNAL uint32_t CRC32(uint32_t crc32, const uint8_t *buf, size_t len) { /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for * these short lengths might also prove to be effective */ if (len < 64) return PREFIX(crc32_braid)(crc32, buf, len); crc32_fold ALIGNED_(16) crc_state; - CRC32_FOLD_RESET_NAME (&crc_state); - CRC32_FOLD_NAME (&crc_state, buf, len, crc32); - return CRC32_FOLD_FINAL_NAME (&crc_state); + CRC32_FOLD_RESET(&crc_state); + CRC32_FOLD(&crc_state, buf, len, crc32); + return CRC32_FOLD_FINAL(&crc_state); } diff --git a/arch/x86/crc32_vpclmulqdq.c b/arch/x86/crc32_vpclmulqdq.c index b05ddb9a2d..ec641b4326 100644 --- a/arch/x86/crc32_vpclmulqdq.c +++ b/arch/x86/crc32_vpclmulqdq.c @@ -6,11 +6,11 @@ #if defined(X86_PCLMULQDQ_CRC) && defined(X86_VPCLMULQDQ_CRC) #define X86_VPCLMULQDQ -#define CRC32_FOLD_COPY_NAME crc32_fold_vpclmulqdq_copy -#define CRC32_FOLD_NAME crc32_fold_vpclmulqdq -#define CRC32_FOLD_RESET_NAME crc32_fold_vpclmulqdq_reset -#define CRC32_FOLD_FINAL_NAME crc32_fold_vpclmulqdq_final -#define CRC32_NAME crc32_vpclmulqdq +#define CRC32_FOLD_COPY crc32_fold_vpclmulqdq_copy +#define CRC32_FOLD crc32_fold_vpclmulqdq +#define CRC32_FOLD_RESET crc32_fold_vpclmulqdq_reset +#define CRC32_FOLD_FINAL crc32_fold_vpclmulqdq_final +#define CRC32 crc32_vpclmulqdq #include "crc32_pclmulqdq_tpl.h" From c43888037bdb114405e869b726024ed735a41233 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 18 Feb 2023 14:30:13 +0500 Subject: [PATCH 617/798] Fix CodeQL warnings: This pointer might have type (size 4), but this pointer arithmetic is done with type __m128i * (size 16) Signed-off-by: Vladislav Shchapov --- arch/x86/crc32_pclmulqdq_tpl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/crc32_pclmulqdq_tpl.h b/arch/x86/crc32_pclmulqdq_tpl.h index 04dad4b60d..0d66663cb5 100644 --- a/arch/x86/crc32_pclmulqdq_tpl.h +++ b/arch/x86/crc32_pclmulqdq_tpl.h @@ -195,7 +195,7 @@ static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i xmm_a0_0, xmm_a0_1; __m128 ps_crc3, psa0_0, psa0_1, ps_res; - xmm_shl = _mm_load_si128((__m128i *)pshufb_shf_table + (len - 1)); + xmm_shl = _mm_load_si128((__m128i *)(pshufb_shf_table + (4 * (len - 1)))); xmm_shr = xmm_shl; xmm_shr = _mm_xor_si128(xmm_shr, xmm_mask3); @@ -316,7 +316,7 @@ Z_INTERNAL uint32_t CRC32_FOLD_FINAL(crc32_fold *crc) { /* * k5 */ - crc_fold = _mm_load_si128((__m128i *)crc_k + 1); + crc_fold = _mm_load_si128((__m128i *)(crc_k + 4)); xmm_crc0 = xmm_crc3; xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); @@ -334,7 +334,7 @@ Z_INTERNAL uint32_t CRC32_FOLD_FINAL(crc32_fold *crc) { */ xmm_crc1 = xmm_crc3; xmm_crc2 = xmm_crc3; - crc_fold = _mm_load_si128((__m128i *)crc_k + 2); + crc_fold = _mm_load_si128((__m128i *)(crc_k + 8)); xmm_crc3 = _mm_clmulepi64_si128(xmm_crc3, crc_fold, 0); xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); From 3848b94cb097a9b8d5ce32f5c751f5b3ecdbb818 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 18 Feb 2023 17:46:40 +0500 Subject: [PATCH 618/798] Add missing test for crc32_vpclmulqdq Signed-off-by: Vladislav Shchapov --- test/test_crc32.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_crc32.cc b/test/test_crc32.cc index c46d0eb80a..e36226fab7 100644 --- a/test/test_crc32.cc +++ b/test/test_crc32.cc @@ -216,4 +216,7 @@ TEST_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07) TEST_CRC32(vx, PREFIX(s390_crc32_vx), PREFIX(s390_cpu_has_vx)) #elif defined(X86_PCLMULQDQ_CRC) TEST_CRC32(pclmulqdq, crc32_pclmulqdq, x86_cpu_has_pclmulqdq) +# ifdef X86_VPCLMULQDQ_CRC +TEST_CRC32(vpclmulqdq, crc32_vpclmulqdq, (x86_cpu_has_pclmulqdq && x86_cpu_has_avx512 && x86_cpu_has_vpclmulqdq)) +# endif #endif From 61524f590ce2a0bffd7f9440a1a3babac0b364b3 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 18 Feb 2023 17:58:36 +0500 Subject: [PATCH 619/798] Fix TEST_CRC32 macro Signed-off-by: Vladislav Shchapov --- test/test_crc32.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_crc32.cc b/test/test_crc32.cc index e36226fab7..4d0b5b966a 100644 --- a/test/test_crc32.cc +++ b/test/test_crc32.cc @@ -199,7 +199,7 @@ INSTANTIATE_TEST_SUITE_P(crc32, crc32_variant, testing::ValuesIn(tests)); #define TEST_CRC32(name, func, support_flag) \ TEST_P(crc32_variant, name) { \ - if (!support_flag) { \ + if (!(support_flag)) { \ GTEST_SKIP(); \ return; \ } \ From c5b4aa34fe4c8e6690f7935ad27dacbdd5cc821d Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 23 Feb 2023 23:22:35 +0500 Subject: [PATCH 620/798] Replace __WIN__ with X86_FEATURES Signed-off-by: Vladislav Shchapov --- zbuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zbuild.h b/zbuild.h index da21b45ef8..bb1148667d 100644 --- a/zbuild.h +++ b/zbuild.h @@ -187,7 +187,7 @@ # define PREFETCH_L1(addr) __builtin_prefetch(addr, 0, 3) # define PREFETCH_L2(addr) __builtin_prefetch(addr, 0, 2) # define PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 2) -#elif defined(__WIN__) +#elif defined(X86_FEATURES) # include # define LIKELY_NULL(x) x # define LIKELY(x) x From 20d8fa8af137e5efb4ec79b25caf2de0ed68b5c7 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 18 Feb 2023 21:25:55 +0500 Subject: [PATCH 621/798] Replace global CPU feature flag variables with local variable in init_functable Signed-off-by: Vladislav Shchapov --- arch/arm/arm_features.c | 12 ++--- arch/arm/arm_features.h | 8 +-- arch/power/power_features.c | 12 ++--- arch/power/power_features.h | 10 ++-- arch/s390/crc32-vx.c | 2 +- arch/s390/s390_features.c | 8 +-- arch/s390/s390_features.h | 6 ++- arch/x86/x86_features.c | 59 +++++++++-------------- arch/x86/x86_features.h | 26 +++++----- cpu_features.c | 17 +++---- cpu_features.h | 16 +++++- deflate.c | 3 -- functable.c | 37 +++++++------- inflate.c | 3 -- test/benchmarks/benchmark_adler32.cc | 16 +++--- test/benchmarks/benchmark_adler32_copy.cc | 30 ++++++------ test/benchmarks/benchmark_compare256.cc | 10 ++-- test/benchmarks/benchmark_crc32.cc | 10 ++-- test/benchmarks/benchmark_main.cc | 6 ++- test/benchmarks/benchmark_slidehash.cc | 12 ++--- test/test_adler32.cc | 16 +++--- test/test_compare256.cc | 10 ++-- test/test_cpu_features.h | 8 +++ test/test_crc32.cc | 12 ++--- test/test_main.cc | 8 +-- 25 files changed, 180 insertions(+), 177 deletions(-) create mode 100644 test/test_cpu_features.h diff --git a/arch/arm/arm_features.c b/arch/arm/arm_features.c index d41c13acb0..7394351fa1 100644 --- a/arch/arm/arm_features.c +++ b/arch/arm/arm_features.c @@ -1,4 +1,5 @@ #include "../../zbuild.h" +#include "arm_features.h" #if defined(__linux__) && defined(HAVE_SYS_AUXV_H) # include @@ -71,14 +72,11 @@ static inline int arm_has_neon() { } #endif -Z_INTERNAL int arm_cpu_has_neon; -Z_INTERNAL int arm_cpu_has_crc32; - -void Z_INTERNAL arm_check_features(void) { +void Z_INTERNAL arm_check_features(struct arm_cpu_features *features) { #if defined(__aarch64__) || defined(_M_ARM64) - arm_cpu_has_neon = 1; /* always available */ + features->has_neon = 1; /* always available */ #else - arm_cpu_has_neon = arm_has_neon(); + features->has_neon = arm_has_neon(); #endif - arm_cpu_has_crc32 = arm_has_crc32(); + features->has_crc32 = arm_has_crc32(); } diff --git a/arch/arm/arm_features.h b/arch/arm/arm_features.h index 7998e79422..6fcd8d3eb5 100644 --- a/arch/arm/arm_features.h +++ b/arch/arm/arm_features.h @@ -5,9 +5,11 @@ #ifndef ARM_H_ #define ARM_H_ -extern int arm_cpu_has_neon; -extern int arm_cpu_has_crc32; +struct arm_cpu_features { + int has_neon; + int has_crc32; +}; -void Z_INTERNAL arm_check_features(void); +void Z_INTERNAL arm_check_features(struct arm_cpu_features *features); #endif /* ARM_H_ */ diff --git a/arch/power/power_features.c b/arch/power/power_features.c index 0614ff0f25..003a4c6e3c 100644 --- a/arch/power/power_features.c +++ b/arch/power/power_features.c @@ -13,11 +13,7 @@ #include "../../zbuild.h" #include "power_features.h" -Z_INTERNAL int power_cpu_has_altivec = 0; -Z_INTERNAL int power_cpu_has_arch_2_07 = 0; -Z_INTERNAL int power_cpu_has_arch_3_00 = 0; - -void Z_INTERNAL power_check_features(void) { +void Z_INTERNAL power_check_features(struct power_cpu_features *features) { #ifdef PPC_FEATURES unsigned long hwcap; #ifdef __FreeBSD__ @@ -27,7 +23,7 @@ void Z_INTERNAL power_check_features(void) { #endif if (hwcap & PPC_FEATURE_HAS_ALTIVEC) - power_cpu_has_altivec = 1; + features->has_altivec = 1; #endif #ifdef POWER_FEATURES @@ -39,8 +35,8 @@ void Z_INTERNAL power_check_features(void) { #endif if (hwcap2 & PPC_FEATURE2_ARCH_2_07) - power_cpu_has_arch_2_07 = 1; + features->has_arch_2_07 = 1; if (hwcap2 & PPC_FEATURE2_ARCH_3_00) - power_cpu_has_arch_3_00 = 1; + features->has_arch_3_00 = 1; #endif } diff --git a/arch/power/power_features.h b/arch/power/power_features.h index 8df9f9e958..9252364cc4 100644 --- a/arch/power/power_features.h +++ b/arch/power/power_features.h @@ -7,10 +7,12 @@ #ifndef POWER_H_ #define POWER_H_ -extern int power_cpu_has_altivec; -extern int power_cpu_has_arch_2_07; -extern int power_cpu_has_arch_3_00; +struct power_cpu_features { + int has_altivec; + int has_arch_2_07; + int has_arch_3_00; +}; -void Z_INTERNAL power_check_features(void); +void Z_INTERNAL power_check_features(struct power_cpu_features *features); #endif /* POWER_H_ */ diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index 78c0be5cee..acfa21887e 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -198,7 +198,7 @@ static uint32_t crc32_le_vgfm_16(uint32_t crc, const uint8_t *buf, size_t len) { #define VX_ALIGNMENT 16L #define VX_ALIGN_MASK (VX_ALIGNMENT - 1) -uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf, size_t len) { +uint32_t Z_INTERNAL crc32_s390_vx(uint32_t crc, const unsigned char *buf, size_t len) { size_t prealign, aligned, remaining; if (len < VX_MIN_LEN + VX_ALIGN_MASK) diff --git a/arch/s390/s390_features.c b/arch/s390/s390_features.c index 0658e4bbeb..711b7dd460 100644 --- a/arch/s390/s390_features.c +++ b/arch/s390/s390_features.c @@ -5,10 +5,6 @@ # include #endif -Z_INTERNAL int PREFIX(s390_cpu_has_vx) = 0; - -void Z_INTERNAL PREFIX(s390_check_features)(void) { -#ifdef S390_FEATURES - PREFIX(s390_cpu_has_vx) = getauxval(AT_HWCAP) & HWCAP_S390_VX; -#endif +void Z_INTERNAL s390_check_features(struct s390_cpu_features *features) { + features->has_vx = getauxval(AT_HWCAP) & HWCAP_S390_VX; } diff --git a/arch/s390/s390_features.h b/arch/s390/s390_features.h index 9e2608fa9e..b8ffef74d8 100644 --- a/arch/s390/s390_features.h +++ b/arch/s390/s390_features.h @@ -1,8 +1,10 @@ #ifndef S390_FEATURES_H_ #define S390_FEATURES_H_ -extern int PREFIX(s390_cpu_has_vx); +struct s390_cpu_features { + int has_vx; +}; -void Z_INTERNAL PREFIX(s390_check_features)(void); +void Z_INTERNAL s390_check_features(struct s390_cpu_features *features); #endif diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index 2c5cb54c65..4ff7f63ee8 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -8,6 +8,7 @@ */ #include "../../zbuild.h" +#include "x86_features.h" #ifdef _WIN32 # include @@ -18,18 +19,6 @@ #include -Z_INTERNAL int x86_cpu_has_avx2; -Z_INTERNAL int x86_cpu_has_avx512; -Z_INTERNAL int x86_cpu_has_avx512vnni; -Z_INTERNAL int x86_cpu_has_sse2; -Z_INTERNAL int x86_cpu_has_ssse3; -Z_INTERNAL int x86_cpu_has_sse41; -Z_INTERNAL int x86_cpu_has_sse42; -Z_INTERNAL int x86_cpu_has_pclmulqdq; -Z_INTERNAL int x86_cpu_has_vpclmulqdq; -Z_INTERNAL int x86_cpu_has_os_save_ymm; -Z_INTERNAL int x86_cpu_has_os_save_zmm; - static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { #ifdef _WIN32 unsigned int registers[4]; @@ -68,27 +57,27 @@ static inline uint64_t xgetbv(unsigned int xcr) { #endif } -void Z_INTERNAL x86_check_features(void) { +void Z_INTERNAL x86_check_features(struct x86_cpu_features *features) { unsigned eax, ebx, ecx, edx; unsigned maxbasic; cpuid(0, &maxbasic, &ebx, &ecx, &edx); cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx); - x86_cpu_has_sse2 = edx & 0x4000000; - x86_cpu_has_ssse3 = ecx & 0x200; - x86_cpu_has_sse41 = ecx & 0x80000; - x86_cpu_has_sse42 = ecx & 0x100000; - x86_cpu_has_pclmulqdq = ecx & 0x2; + features->has_sse2 = edx & 0x4000000; + features->has_ssse3 = ecx & 0x200; + features->has_sse41 = ecx & 0x80000; + features->has_sse42 = ecx & 0x100000; + features->has_pclmulqdq = ecx & 0x2; if (ecx & 0x08000000) { uint64_t xfeature = xgetbv(0); - x86_cpu_has_os_save_ymm = ((xfeature & 0x06) == 0x06); - x86_cpu_has_os_save_zmm = ((xfeature & 0xe6) == 0xe6); + features->has_os_save_ymm = ((xfeature & 0x06) == 0x06); + features->has_os_save_zmm = ((xfeature & 0xe6) == 0xe6); } else { - x86_cpu_has_os_save_ymm = 0; - x86_cpu_has_os_save_zmm = 0; + features->has_os_save_ymm = 0; + features->has_os_save_zmm = 0; } if (maxbasic >= 7) { @@ -96,27 +85,27 @@ void Z_INTERNAL x86_check_features(void) { // check BMI1 bit // Reference: https://software.intel.com/sites/default/files/article/405250/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf - x86_cpu_has_vpclmulqdq = ecx & 0x400; + features->has_vpclmulqdq = ecx & 0x400; // check AVX2 bit if the OS supports saving YMM registers - if (x86_cpu_has_os_save_ymm) { - x86_cpu_has_avx2 = ebx & 0x20; + if (features->has_os_save_ymm) { + features->has_avx2 = ebx & 0x20; } else { - x86_cpu_has_avx2 = 0; + features->has_avx2 = 0; } // check AVX512 bits if the OS supports saving ZMM registers - if (x86_cpu_has_os_save_zmm) { - x86_cpu_has_avx512 = ebx & 0x00010000; - x86_cpu_has_avx512vnni = ecx & 0x800; + if (features->has_os_save_zmm) { + features->has_avx512 = ebx & 0x00010000; + features->has_avx512vnni = ecx & 0x800; } else { - x86_cpu_has_avx512 = 0; - x86_cpu_has_avx512vnni = 0; + features->has_avx512 = 0; + features->has_avx512vnni = 0; } } else { - x86_cpu_has_avx2 = 0; - x86_cpu_has_avx512 = 0; - x86_cpu_has_avx512vnni = 0; - x86_cpu_has_vpclmulqdq = 0; + features->has_avx2 = 0; + features->has_avx512 = 0; + features->has_avx512vnni = 0; + features->has_vpclmulqdq = 0; } } diff --git a/arch/x86/x86_features.h b/arch/x86/x86_features.h index 06677b2e12..00b510ffc1 100644 --- a/arch/x86/x86_features.h +++ b/arch/x86/x86_features.h @@ -6,18 +6,20 @@ #ifndef X86_FEATURES_H_ #define X86_FEATURES_H_ -extern int x86_cpu_has_avx2; -extern int x86_cpu_has_avx512; -extern int x86_cpu_has_avx512vnni; -extern int x86_cpu_has_sse2; -extern int x86_cpu_has_ssse3; -extern int x86_cpu_has_sse41; -extern int x86_cpu_has_sse42; -extern int x86_cpu_has_pclmulqdq; -extern int x86_cpu_has_vpclmulqdq; -extern int x86_cpu_has_os_save_ymm; -extern int x86_cpu_has_os_save_zmm; +struct x86_cpu_features { + int has_avx2; + int has_avx512; + int has_avx512vnni; + int has_sse2; + int has_ssse3; + int has_sse41; + int has_sse42; + int has_pclmulqdq; + int has_vpclmulqdq; + int has_os_save_ymm; + int has_os_save_zmm; +}; -void Z_INTERNAL x86_check_features(void); +void Z_INTERNAL x86_check_features(struct x86_cpu_features *features); #endif /* CPU_H_ */ diff --git a/cpu_features.c b/cpu_features.c index b5e7257696..b69a01304a 100644 --- a/cpu_features.c +++ b/cpu_features.c @@ -4,21 +4,18 @@ */ #include "zbuild.h" - #include "cpu_features.h" +#include -Z_INTERNAL void cpu_check_features(void) { - static int features_checked = 0; - if (features_checked) - return; +Z_INTERNAL void cpu_check_features(struct cpu_features *features) { + memset(features, 0, sizeof(struct cpu_features)); #if defined(X86_FEATURES) - x86_check_features(); + x86_check_features(&features->x86); #elif defined(ARM_FEATURES) - arm_check_features(); + arm_check_features(&features->arm); #elif defined(PPC_FEATURES) || defined(POWER_FEATURES) - power_check_features(); + power_check_features(&features->power); #elif defined(S390_FEATURES) - PREFIX(s390_check_features)(); + s390_check_features(&features->s390); #endif - features_checked = 1; } diff --git a/cpu_features.h b/cpu_features.h index 22d70da3d9..14eb19a751 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -20,7 +20,19 @@ # include "arch/s390/s390_features.h" #endif -extern void cpu_check_features(void); +struct cpu_features { +#if defined(X86_FEATURES) + struct x86_cpu_features x86; +#elif defined(ARM_FEATURES) + struct arm_cpu_features arm; +#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) + struct power_cpu_features power; +#elif defined(S390_FEATURES) + struct s390_cpu_features s390; +#endif +}; + +extern void cpu_check_features(struct cpu_features *features); /* adler32 */ typedef uint32_t (*adler32_func)(uint32_t adler, const uint8_t *buf, size_t len); @@ -134,7 +146,7 @@ extern uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len); #elif defined(POWER8_VSX) extern uint32_t crc32_power8(uint32_t crc, const uint8_t *buf, size_t len); #elif defined(S390_CRC32_VX) -extern uint32_t PREFIX(s390_crc32_vx)(uint32_t crc, const uint8_t *buf, size_t len); +extern uint32_t crc32_s390_vx(uint32_t crc, const uint8_t *buf, size_t len); #endif /* compare256 */ diff --git a/deflate.c b/deflate.c index 273967b426..3ea92a82dd 100644 --- a/deflate.c +++ b/deflate.c @@ -48,7 +48,6 @@ */ #include "zbuild.h" -#include "cpu_features.h" #include "deflate.h" #include "deflate_p.h" #include "functable.h" @@ -195,8 +194,6 @@ int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level deflate_state *s; int wrap = 1; - cpu_check_features(); - if (strm == NULL) return Z_STREAM_ERROR; diff --git a/functable.c b/functable.c index da9d10ec5b..c7d477c7f0 100644 --- a/functable.c +++ b/functable.c @@ -13,8 +13,9 @@ static void init_functable(void) { struct functable_s ft; + struct cpu_features cf; - cpu_check_features(); + cpu_check_features(&cf); // Generic code ft.adler32 = &adler32_c; @@ -58,7 +59,7 @@ static void init_functable(void) { // X86 - SSE2 #ifdef X86_SSE2 # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) + if (cf.x86.has_sse2) # endif { ft.chunkmemset_safe = &chunkmemset_safe_sse2; @@ -74,18 +75,18 @@ static void init_functable(void) { #endif // X86 - SSSE3 #ifdef X86_SSSE3 - if (x86_cpu_has_ssse3) + if (cf.x86.has_ssse3) ft.adler32 = &adler32_ssse3; #endif // X86 - SSE4 #if defined(X86_SSE41) && defined(X86_SSE2) - if (x86_cpu_has_sse41) { + if (cf.x86.has_sse41) { ft.chunkmemset_safe = &chunkmemset_safe_sse41; ft.inflate_fast = &inflate_fast_sse41; } #endif #ifdef X86_SSE42 - if (x86_cpu_has_sse42) { + if (cf.x86.has_sse42) { ft.adler32_fold_copy = &adler32_fold_copy_sse42; ft.insert_string = &insert_string_sse4; ft.quick_insert_string = &quick_insert_string_sse4; @@ -94,7 +95,7 @@ static void init_functable(void) { #endif // X86 - PCLMUL #ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) { + if (cf.x86.has_pclmulqdq) { ft.crc32 = &crc32_pclmulqdq; ft.crc32_fold = &crc32_fold_pclmulqdq; ft.crc32_fold_copy = &crc32_fold_pclmulqdq_copy; @@ -104,7 +105,7 @@ static void init_functable(void) { #endif // X86 - AVX #ifdef X86_AVX2 - if (x86_cpu_has_avx2) { + if (cf.x86.has_avx2) { ft.adler32 = &adler32_avx2; ft.adler32_fold_copy = &adler32_fold_copy_avx2; ft.chunkmemset_safe = &chunkmemset_safe_avx; @@ -119,20 +120,20 @@ static void init_functable(void) { } #endif #ifdef X86_AVX512 - if (x86_cpu_has_avx512) { + if (cf.x86.has_avx512) { ft.adler32 = &adler32_avx512; ft.adler32_fold_copy = &adler32_fold_copy_avx512; } #endif #ifdef X86_AVX512VNNI - if (x86_cpu_has_avx512vnni) { + if (cf.x86.has_avx512vnni) { ft.adler32 = &adler32_avx512_vnni; ft.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; } #endif // X86 - VPCLMULQDQ #if defined(X86_PCLMULQDQ_CRC) && defined(X86_VPCLMULQDQ_CRC) - if (x86_cpu_has_pclmulqdq && x86_cpu_has_avx512 && x86_cpu_has_vpclmulqdq) { + if (cf.x86.has_pclmulqdq && cf.x86.has_avx512 && cf.x86.has_vpclmulqdq) { ft.crc32 = &crc32_vpclmulqdq; ft.crc32_fold = &crc32_fold_vpclmulqdq; ft.crc32_fold_copy = &crc32_fold_vpclmulqdq_copy; @@ -145,7 +146,7 @@ static void init_functable(void) { // ARM - NEON #ifdef ARM_NEON # ifndef ARM_NOCHECK_NEON - if (arm_cpu_has_neon) + if (cf.arm.has_neon) # endif { ft.adler32 = &adler32_neon; @@ -162,7 +163,7 @@ static void init_functable(void) { #endif // ARM - ACLE #ifdef ARM_ACLE - if (arm_cpu_has_crc32) { + if (cf.arm.has_crc32) { ft.crc32 = &crc32_acle; ft.insert_string = &insert_string_acle; ft.quick_insert_string = &quick_insert_string_acle; @@ -173,14 +174,14 @@ static void init_functable(void) { // Power - VMX #ifdef PPC_VMX - if (power_cpu_has_altivec) { + if (cf.power.has_altivec) { ft.adler32 = &adler32_vmx; ft.slide_hash = &slide_hash_vmx; } #endif // Power8 - VSX #ifdef POWER8_VSX - if (power_cpu_has_arch_2_07) { + if (cf.power.has_arch_2_07) { ft.adler32 = &adler32_power8; ft.chunkmemset_safe = &chunkmemset_safe_power8; ft.chunksize = &chunksize_power8; @@ -189,12 +190,12 @@ static void init_functable(void) { } #endif #ifdef POWER8_VSX_CRC32 - if (power_cpu_has_arch_2_07) + if (cf.power.has_arch_2_07) ft.crc32 = &crc32_power8; #endif // Power9 #ifdef POWER9 - if (power_cpu_has_arch_3_00) { + if (cf.power.has_arch_3_00) { ft.compare256 = &compare256_power9; ft.longest_match = &longest_match_power9; ft.longest_match_slow = &longest_match_slow_power9; @@ -204,8 +205,8 @@ static void init_functable(void) { // S390 #ifdef S390_CRC32_VX - if (PREFIX(s390_cpu_has_vx)) - ft.crc32 = &PREFIX(s390_crc32_vx); + if (cf.s390.has_vx) + ft.crc32 = crc32_s390_vx; #endif // Assign function pointers individually for atomic operation diff --git a/inflate.c b/inflate.c index 506bb2a50a..df4c56a168 100644 --- a/inflate.c +++ b/inflate.c @@ -5,7 +5,6 @@ #include "zbuild.h" #include "zutil.h" -#include "cpu_features.h" #include "inftrees.h" #include "inflate.h" #include "inflate_p.h" @@ -140,8 +139,6 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateInit2)(PREFIX3(stream) *strm, int32_t windo int32_t ret; struct inflate_state *state; - cpu_check_features(); - if (strm == NULL) return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index 19691376fb..5b0b65d67b 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -11,7 +11,7 @@ extern "C" { # include "zbuild.h" # include "zutil_p.h" -# include "cpu_features.h" +# include "../test_cpu_features.h" } #define MAX_RANDOM_INTS (1024 * 1024) @@ -65,25 +65,25 @@ class adler32: public benchmark::Fixture { BENCHMARK_ADLER32(c, adler32_c, 1); #ifdef ARM_NEON -BENCHMARK_ADLER32(neon, adler32_neon, arm_cpu_has_neon); +BENCHMARK_ADLER32(neon, adler32_neon, test_cpu_features.arm.has_neon); #endif #ifdef PPC_VMX -BENCHMARK_ADLER32(vmx, adler32_vmx, power_cpu_has_altivec); +BENCHMARK_ADLER32(vmx, adler32_vmx, test_cpu_features.power.has_altivec); #endif #ifdef POWER8_VSX -BENCHMARK_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07); +BENCHMARK_ADLER32(power8, adler32_power8, test_cpu_features.power.has_arch_2_07); #endif #ifdef X86_SSSE3 -BENCHMARK_ADLER32(ssse3, adler32_ssse3, x86_cpu_has_ssse3); +BENCHMARK_ADLER32(ssse3, adler32_ssse3, test_cpu_features.x86.has_ssse3); #endif #ifdef X86_AVX2 -BENCHMARK_ADLER32(avx2, adler32_avx2, x86_cpu_has_avx2); +BENCHMARK_ADLER32(avx2, adler32_avx2, test_cpu_features.x86.has_avx2); #endif #ifdef X86_AVX512 -BENCHMARK_ADLER32(avx512, adler32_avx512, x86_cpu_has_avx512); +BENCHMARK_ADLER32(avx512, adler32_avx512, test_cpu_features.x86.has_avx512); #endif #ifdef X86_AVX512VNNI -BENCHMARK_ADLER32(avx512_vnni, adler32_avx512_vnni, x86_cpu_has_avx512vnni); +BENCHMARK_ADLER32(avx512_vnni, adler32_avx512_vnni, test_cpu_features.x86.has_avx512vnni); #endif diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index d508a004aa..cbee780b76 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -12,7 +12,7 @@ extern "C" { # include "zbuild.h" # include "zutil_p.h" -# include "cpu_features.h" +# include "../test_cpu_features.h" } #define MAX_RANDOM_INTS (1024 * 1024) @@ -87,32 +87,32 @@ BENCHMARK_ADLER32_BASELINE_COPY(c, adler32_c, 1); #ifdef ARM_NEON /* If we inline this copy for neon, the function would go here */ -//BENCHMARK_ADLER32_COPY(neon, adler32_neon, arm_cpu_has_neon); -BENCHMARK_ADLER32_BASELINE_COPY(neon_copy_baseline, adler32_neon, arm_cpu_has_neon); +//BENCHMARK_ADLER32_COPY(neon, adler32_neon, test_cpu_features.arm.has_neon); +BENCHMARK_ADLER32_BASELINE_COPY(neon_copy_baseline, adler32_neon, test_cpu_features.arm.has_neon); #endif #ifdef PPC_VMX -//BENCHMARK_ADLER32_COPY(vmx_inline_copy, adler32_fold_copy_vmx, power_cpu_has_altivec); -BENCHMARK_ADLER32_BASELINE_COPY(vmx_copy_baseline, adler32_vmx, power_cpu_has_altivec); +//BENCHMARK_ADLER32_COPY(vmx_inline_copy, adler32_fold_copy_vmx, test_cpu_features.power.has_altivec); +BENCHMARK_ADLER32_BASELINE_COPY(vmx_copy_baseline, adler32_vmx, test_cpu_features.power.has_altivec); #endif #ifdef POWER8_VSX -//BENCHMARK_ADLER32_COPY(power8_inline_copy, adler32_fold_copy_power8, power_cpu_has_arch_2_07); -BENCHMARK_ADLER32_BASELINE_COPY(power8, adler32_power8, power_cpu_has_arch_2_07); +//BENCHMARK_ADLER32_COPY(power8_inline_copy, adler32_fold_copy_power8, test_cpu_features.power.has_arch_2_07); +BENCHMARK_ADLER32_BASELINE_COPY(power8, adler32_power8, test_cpu_features.power.has_arch_2_07); #endif #ifdef X86_SSE42 -BENCHMARK_ADLER32_BASELINE_COPY(sse42_baseline, adler32_ssse3, x86_cpu_has_ssse3); -BENCHMARK_ADLER32_COPY(sse42, adler32_fold_copy_sse42, x86_cpu_has_sse42); +BENCHMARK_ADLER32_BASELINE_COPY(sse42_baseline, adler32_ssse3, test_cpu_features.x86.has_ssse3); +BENCHMARK_ADLER32_COPY(sse42, adler32_fold_copy_sse42, test_cpu_features.x86.has_sse42); #endif #ifdef X86_AVX2 -BENCHMARK_ADLER32_BASELINE_COPY(avx2_baseline, adler32_avx2, x86_cpu_has_avx2); -BENCHMARK_ADLER32_COPY(avx2, adler32_fold_copy_avx2, x86_cpu_has_avx2); +BENCHMARK_ADLER32_BASELINE_COPY(avx2_baseline, adler32_avx2, test_cpu_features.x86.has_avx2); +BENCHMARK_ADLER32_COPY(avx2, adler32_fold_copy_avx2, test_cpu_features.x86.has_avx2); #endif #ifdef X86_AVX512 -BENCHMARK_ADLER32_BASELINE_COPY(avx512_baseline, adler32_avx512, x86_cpu_has_avx512); -BENCHMARK_ADLER32_COPY(avx512, adler32_fold_copy_avx512, x86_cpu_has_avx512); +BENCHMARK_ADLER32_BASELINE_COPY(avx512_baseline, adler32_avx512, test_cpu_features.x86.has_avx512); +BENCHMARK_ADLER32_COPY(avx512, adler32_fold_copy_avx512, test_cpu_features.x86.has_avx512); #endif #ifdef X86_AVX512VNNI -BENCHMARK_ADLER32_BASELINE_COPY(avx512_vnni_baseline, adler32_avx512_vnni, x86_cpu_has_avx512vnni); -BENCHMARK_ADLER32_COPY(avx512_vnni, adler32_fold_copy_avx512_vnni, x86_cpu_has_avx512vnni); +BENCHMARK_ADLER32_BASELINE_COPY(avx512_vnni_baseline, adler32_avx512_vnni, test_cpu_features.x86.has_avx512vnni); +BENCHMARK_ADLER32_COPY(avx512_vnni, adler32_fold_copy_avx512_vnni, test_cpu_features.x86.has_avx512vnni); #endif diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 54f6b14b84..00c6cc6f63 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -10,7 +10,7 @@ extern "C" { # include "zbuild.h" # include "zutil_p.h" -# include "cpu_features.h" +# include "../test_cpu_features.h" } #define MAX_COMPARE_SIZE (256) @@ -71,14 +71,14 @@ BENCHMARK_COMPARE256(unaligned_64, compare256_unaligned_64, 1); #endif #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) -BENCHMARK_COMPARE256(sse2, compare256_sse2, x86_cpu_has_sse2); +BENCHMARK_COMPARE256(sse2, compare256_sse2, test_cpu_features.x86.has_sse2); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -BENCHMARK_COMPARE256(avx2, compare256_avx2, x86_cpu_has_avx2); +BENCHMARK_COMPARE256(avx2, compare256_avx2, test_cpu_features.x86.has_avx2); #endif #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) -BENCHMARK_COMPARE256(neon, compare256_neon, arm_cpu_has_neon); +BENCHMARK_COMPARE256(neon, compare256_neon, test_cpu_features.arm.has_neon); #endif #ifdef POWER9 -BENCHMARK_COMPARE256(power9, compare256_power9, power_cpu_has_arch_3_00); +BENCHMARK_COMPARE256(power9, compare256_power9, test_cpu_features.power.has_arch_3_00); #endif diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index b5ecda5179..b2b9673d9f 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -11,7 +11,7 @@ extern "C" { # include "zbuild.h" # include "zutil_p.h" -# include "cpu_features.h" +# include "../test_cpu_features.h" } #define MAX_RANDOM_INTS (1024 * 1024) @@ -58,12 +58,12 @@ class crc32: public benchmark::Fixture { BENCHMARK_CRC32(braid, PREFIX(crc32_braid), 1); #ifdef ARM_ACLE -BENCHMARK_CRC32(acle, crc32_acle, arm_cpu_has_crc32); +BENCHMARK_CRC32(acle, crc32_acle, test_cpu_features.arm.has_crc32); #elif defined(POWER8_VSX) -BENCHMARK_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07); +BENCHMARK_CRC32(power8, crc32_power8, test_cpu_features.power.has_arch_2_07); #elif defined(S390_CRC32_VX) -BENCHMARK_CRC32(vx, PREFIX(s390_crc32_vx), PREFIX(s390_cpu_has_vx)); +BENCHMARK_CRC32(vx, crc32_s390_vx, test_cpu_features.s390.has_vx); #elif defined(X86_PCLMULQDQ_CRC) /* CRC32 fold does a memory copy while hashing */ -BENCHMARK_CRC32(pclmulqdq, crc32_pclmulqdq, x86_cpu_has_pclmulqdq); +BENCHMARK_CRC32(pclmulqdq, crc32_pclmulqdq, test_cpu_features.x86.has_pclmulqdq); #endif diff --git a/test/benchmarks/benchmark_main.cc b/test/benchmarks/benchmark_main.cc index ee8b614897..3ef2c5e87d 100644 --- a/test/benchmarks/benchmark_main.cc +++ b/test/benchmarks/benchmark_main.cc @@ -10,13 +10,15 @@ #ifndef BUILD_ALT extern "C" { # include "zbuild.h" -# include "cpu_features.h" +# include "../test_cpu_features.h" + + struct cpu_features test_cpu_features; } #endif int main(int argc, char** argv) { #ifndef BUILD_ALT - cpu_check_features(); + cpu_check_features(&test_cpu_features); #endif ::benchmark::Initialize(&argc, argv); diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index 5ffa7039d0..238cc1f658 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -11,7 +11,7 @@ extern "C" { # include "zbuild.h" # include "zutil_p.h" # include "deflate.h" -# include "cpu_features.h" +# include "../test_cpu_features.h" } #define MAX_RANDOM_INTS 32768 @@ -69,18 +69,18 @@ class slide_hash: public benchmark::Fixture { BENCHMARK_SLIDEHASH(c, slide_hash_c, 1); #ifdef ARM_NEON -BENCHMARK_SLIDEHASH(neon, slide_hash_neon, arm_cpu_has_neon); +BENCHMARK_SLIDEHASH(neon, slide_hash_neon, test_cpu_features.arm.has_neon); #endif #ifdef POWER8_VSX -BENCHMARK_SLIDEHASH(power8, slide_hash_power8, power_cpu_has_arch_2_07); +BENCHMARK_SLIDEHASH(power8, slide_hash_power8, test_cpu_features.power.has_arch_2_07); #endif #ifdef PPC_VMX -BENCHMARK_SLIDEHASH(vmx, slide_hash_vmx, power_cpu_has_altivec); +BENCHMARK_SLIDEHASH(vmx, slide_hash_vmx, test_cpu_features.power.has_altivec); #endif #ifdef X86_SSE2 -BENCHMARK_SLIDEHASH(sse2, slide_hash_sse2, x86_cpu_has_sse2); +BENCHMARK_SLIDEHASH(sse2, slide_hash_sse2, test_cpu_features.x86.has_sse2); #endif #ifdef X86_AVX2 -BENCHMARK_SLIDEHASH(avx2, slide_hash_avx2, x86_cpu_has_avx2); +BENCHMARK_SLIDEHASH(avx2, slide_hash_avx2, test_cpu_features.x86.has_avx2); #endif diff --git a/test/test_adler32.cc b/test/test_adler32.cc index 7f88f25565..4dfe63f203 100644 --- a/test/test_adler32.cc +++ b/test/test_adler32.cc @@ -10,7 +10,7 @@ extern "C" { # include "zbuild.h" -# include "cpu_features.h" +# include "test_cpu_features.h" } #include @@ -365,22 +365,22 @@ INSTANTIATE_TEST_SUITE_P(adler32, adler32_variant, testing::ValuesIn(tests)); TEST_ADLER32(c, adler32_c, 1) #ifdef ARM_NEON -TEST_ADLER32(neon, adler32_neon, arm_cpu_has_neon) +TEST_ADLER32(neon, adler32_neon, test_cpu_features.arm.has_neon) #elif defined(POWER8_VSX) -TEST_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07) +TEST_ADLER32(power8, adler32_power8, test_cpu_features.power.has_arch_2_07) #elif defined(PPC_VMX) -TEST_ADLER32(vmx, adler32_vmx, power_cpu_has_altivec) +TEST_ADLER32(vmx, adler32_vmx, test_cpu_features.power.has_altivec) #endif #ifdef X86_SSSE3 -TEST_ADLER32(ssse3, adler32_ssse3, x86_cpu_has_ssse3) +TEST_ADLER32(ssse3, adler32_ssse3, test_cpu_features.x86.has_ssse3) #endif #ifdef X86_AVX2 -TEST_ADLER32(avx2, adler32_avx2, x86_cpu_has_avx2) +TEST_ADLER32(avx2, adler32_avx2, test_cpu_features.x86.has_avx2) #endif #ifdef X86_AVX512 -TEST_ADLER32(avx512, adler32_avx512, x86_cpu_has_avx512) +TEST_ADLER32(avx512, adler32_avx512, test_cpu_features.x86.has_avx512) #endif #ifdef X86_AVX512VNNI -TEST_ADLER32(avx512_vnni, adler32_avx512_vnni, x86_cpu_has_avx512vnni) +TEST_ADLER32(avx512_vnni, adler32_avx512_vnni, test_cpu_features.x86.has_avx512vnni) #endif diff --git a/test/test_compare256.cc b/test/test_compare256.cc index 663ad96334..f920d1d205 100644 --- a/test/test_compare256.cc +++ b/test/test_compare256.cc @@ -10,7 +10,7 @@ extern "C" { # include "zbuild.h" # include "zutil_p.h" -# include "cpu_features.h" +# include "test_cpu_features.h" } #include @@ -70,14 +70,14 @@ TEST_COMPARE256(unaligned_64, compare256_unaligned_64, 1) #endif #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) -TEST_COMPARE256(sse2, compare256_sse2, x86_cpu_has_sse2) +TEST_COMPARE256(sse2, compare256_sse2, test_cpu_features.x86.has_sse2) #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -TEST_COMPARE256(avx2, compare256_avx2, x86_cpu_has_avx2) +TEST_COMPARE256(avx2, compare256_avx2, test_cpu_features.x86.has_avx2) #endif #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) -TEST_COMPARE256(neon, compare256_neon, arm_cpu_has_neon) +TEST_COMPARE256(neon, compare256_neon, test_cpu_features.arm.has_neon) #endif #ifdef POWER9 -TEST_COMPARE256(power9, compare256_power9, power_cpu_has_arch_3_00) +TEST_COMPARE256(power9, compare256_power9, test_cpu_features.power.has_arch_3_00) #endif diff --git a/test/test_cpu_features.h b/test/test_cpu_features.h new file mode 100644 index 0000000000..1bb4b13a08 --- /dev/null +++ b/test/test_cpu_features.h @@ -0,0 +1,8 @@ +#ifndef TEST_CPU_FEATURES_H +#define TEST_CPU_FEATURES_H + +#include "cpu_features.h" + +extern struct cpu_features test_cpu_features; + +#endif diff --git a/test/test_crc32.cc b/test/test_crc32.cc index 4d0b5b966a..f194b4ccf5 100644 --- a/test/test_crc32.cc +++ b/test/test_crc32.cc @@ -12,7 +12,7 @@ extern "C" { # include "zbuild.h" # include "zutil_p.h" -# include "cpu_features.h" +# include "test_cpu_features.h" } #include @@ -209,14 +209,14 @@ INSTANTIATE_TEST_SUITE_P(crc32, crc32_variant, testing::ValuesIn(tests)); TEST_CRC32(braid, PREFIX(crc32_braid), 1) #ifdef ARM_ACLE -TEST_CRC32(acle, crc32_acle, arm_cpu_has_crc32) +TEST_CRC32(acle, crc32_acle, test_cpu_features.arm.has_crc32) #elif defined(POWER8_VSX_CRC32) -TEST_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07) +TEST_CRC32(power8, crc32_power8, test_cpu_features.power.has_arch_2_07) #elif defined(S390_CRC32_VX) -TEST_CRC32(vx, PREFIX(s390_crc32_vx), PREFIX(s390_cpu_has_vx)) +TEST_CRC32(vx, crc32_s390_vx, test_cpu_features.s390.has_vx) #elif defined(X86_PCLMULQDQ_CRC) -TEST_CRC32(pclmulqdq, crc32_pclmulqdq, x86_cpu_has_pclmulqdq) +TEST_CRC32(pclmulqdq, crc32_pclmulqdq, test_cpu_features.x86.has_pclmulqdq) # ifdef X86_VPCLMULQDQ_CRC -TEST_CRC32(vpclmulqdq, crc32_vpclmulqdq, (x86_cpu_has_pclmulqdq && x86_cpu_has_avx512 && x86_cpu_has_vpclmulqdq)) +TEST_CRC32(vpclmulqdq, crc32_vpclmulqdq, (test_cpu_features.x86.has_pclmulqdq && test_cpu_features.x86.has_avx512 && test_cpu_features.x86.has_vpclmulqdq)) # endif #endif diff --git a/test/test_main.cc b/test/test_main.cc index c129db259f..82b39e4874 100644 --- a/test/test_main.cc +++ b/test/test_main.cc @@ -6,12 +6,14 @@ extern "C" { # include "zbuild.h" -# include "cpu_features.h" +# include "test_cpu_features.h" + + struct cpu_features test_cpu_features; } GTEST_API_ int main(int argc, char **argv) { printf("Running main() from %s\n", __FILE__); - cpu_check_features(); + cpu_check_features(&test_cpu_features); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); -} \ No newline at end of file +} From c255e58dd5e0ec3b2febb29c0905e89032419bcd Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sun, 19 Feb 2023 03:01:07 +0500 Subject: [PATCH 622/798] Remove useless assignments Signed-off-by: Vladislav Shchapov --- arch/x86/x86_features.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index 4ff7f63ee8..f60ddbcf94 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -75,9 +75,6 @@ void Z_INTERNAL x86_check_features(struct x86_cpu_features *features) { features->has_os_save_ymm = ((xfeature & 0x06) == 0x06); features->has_os_save_zmm = ((xfeature & 0xe6) == 0xe6); - } else { - features->has_os_save_ymm = 0; - features->has_os_save_zmm = 0; } if (maxbasic >= 7) { @@ -90,22 +87,12 @@ void Z_INTERNAL x86_check_features(struct x86_cpu_features *features) { // check AVX2 bit if the OS supports saving YMM registers if (features->has_os_save_ymm) { features->has_avx2 = ebx & 0x20; - } else { - features->has_avx2 = 0; } // check AVX512 bits if the OS supports saving ZMM registers if (features->has_os_save_zmm) { features->has_avx512 = ebx & 0x00010000; features->has_avx512vnni = ecx & 0x800; - } else { - features->has_avx512 = 0; - features->has_avx512vnni = 0; } - } else { - features->has_avx2 = 0; - features->has_avx512 = 0; - features->has_avx512vnni = 0; - features->has_vpclmulqdq = 0; } } From b8c2114d51ca120f76e0cdad706c8f0c15d1f829 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 6 Mar 2023 23:25:04 +0100 Subject: [PATCH 623/798] IBM zSystems: Use HWCAP_S390_VXRS glibc defines HWCAP_S390_VX and, since v2.33, its alias HWCAP_S390_VXRS; musl has only HWCAP_S390_VXRS. Use the common HWCAP_S390_VXRS, define it as HWCAP_S390_VX if necessary. --- arch/s390/s390_features.c | 6 +++++- cmake/detect-intrinsics.cmake | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/s390/s390_features.c b/arch/s390/s390_features.c index 711b7dd460..82901060eb 100644 --- a/arch/s390/s390_features.c +++ b/arch/s390/s390_features.c @@ -5,6 +5,10 @@ # include #endif +#ifndef HWCAP_S390_VXRS +#define HWCAP_S390_VXRS HWCAP_S390_VX +#endif + void Z_INTERNAL s390_check_features(struct s390_cpu_features *features) { - features->has_vx = getauxval(AT_HWCAP) & HWCAP_S390_VX; + features->has_vx = getauxval(AT_HWCAP) & HWCAP_S390_VXRS; } diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 3e932d83b2..6ce0f3e3c2 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -344,8 +344,11 @@ endmacro() macro(check_s390_intrinsics) check_c_source_compiles( "#include + #ifndef HWCAP_S390_VXRS + #define HWCAP_S390_VXRS HWCAP_S390_VX + #endif int main() { - return (getauxval(AT_HWCAP) & HWCAP_S390_VX); + return (getauxval(AT_HWCAP) & HWCAP_S390_VXRS); }" HAVE_S390_INTRIN ) From 1521bee18ea17d7df97ae9effe39ff9833565522 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 19 Mar 2023 00:36:55 +0100 Subject: [PATCH 624/798] Create FUNDING.yml Adds the required file for enabling the `Sponsor` button to appear when viewing the repo. --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..7cd8129153 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: zlib-ng From a4e1f1c981c04d36c3cf4e9eed93f10280f97579 Mon Sep 17 00:00:00 2001 From: lawadr <3211473+lawadr@users.noreply.github.com> Date: Fri, 17 Mar 2023 16:35:13 +0000 Subject: [PATCH 625/798] Fix regex for visibility attribute tests The previous regex of `not supported` was very specific to a particular compiler (Clang 3.4+). As Clang isn't the only compiler that throws a warning (but otherwise succeeds) when a visibility isn't supported, make the regex more generic to hit all such cases. Testing on Compiler Explorer shows that looking for the string `visibility` has a better hit rate. `attribute` is perhaps more dangerously generic, and `hidden`/`internal` doesn't always show up in warning messages when the visibility attribute itself isn't available. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 265772dd26..466d12deb3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -374,7 +374,7 @@ check_c_source_compiles( int main() { return 0; }" - HAVE_ATTRIBUTE_VISIBILITY_HIDDEN FAIL_REGEX "not supported") + HAVE_ATTRIBUTE_VISIBILITY_HIDDEN FAIL_REGEX "visibility") if(HAVE_ATTRIBUTE_VISIBILITY_HIDDEN) add_definitions(-DHAVE_VISIBILITY_HIDDEN) endif() @@ -388,7 +388,7 @@ check_c_source_compiles( int main() { return 0; }" - HAVE_ATTRIBUTE_VISIBILITY_INTERNAL FAIL_REGEX "not supported") + HAVE_ATTRIBUTE_VISIBILITY_INTERNAL FAIL_REGEX "visibility") if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL) add_definitions(-DHAVE_VISIBILITY_INTERNAL) endif() From 39008be53b94f6ad7704bff27b4ecd6a8067d2ef Mon Sep 17 00:00:00 2001 From: lawadr <3211473+lawadr@users.noreply.github.com> Date: Mon, 20 Mar 2023 17:46:35 +0000 Subject: [PATCH 626/798] Add member to cpu_features struct if empty When WITH_OPTIM is off, the cpu_features struct is empty. This is not allowed in standard C and causes a build failure with various compilers, including MSVC. This adds a dummy char member to the struct if it would otherwise be empty. --- cpu_features.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpu_features.h b/cpu_features.h index 14eb19a751..462671a187 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -29,6 +29,8 @@ struct cpu_features { struct power_cpu_features power; #elif defined(S390_FEATURES) struct s390_cpu_features s390; +#else + char empty; #endif }; From bfde4b91ee675a82c0ef64c6f30c1bbe7546a64d Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 24 Mar 2023 22:55:41 +0000 Subject: [PATCH 627/798] Remove unused PREFETCH macros --- zbuild.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/zbuild.h b/zbuild.h index bb1148667d..de1999cff4 100644 --- a/zbuild.h +++ b/zbuild.h @@ -184,24 +184,10 @@ # define LIKELY_NULL(x) __builtin_expect((x) != 0, 0) # define LIKELY(x) __builtin_expect(!!(x), 1) # define UNLIKELY(x) __builtin_expect(!!(x), 0) -# define PREFETCH_L1(addr) __builtin_prefetch(addr, 0, 3) -# define PREFETCH_L2(addr) __builtin_prefetch(addr, 0, 2) -# define PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 2) -#elif defined(X86_FEATURES) -# include -# define LIKELY_NULL(x) x -# define LIKELY(x) x -# define UNLIKELY(x) x -# define PREFETCH_L1(addr) _mm_prefetch((char *) addr, _MM_HINT_T0) -# define PREFETCH_L2(addr) _mm_prefetch((char *) addr, _MM_HINT_T1) -# define PREFETCH_RW(addr) _mm_prefetch((char *) addr, _MM_HINT_T1) #else # define LIKELY_NULL(x) x # define LIKELY(x) x # define UNLIKELY(x) x -# define PREFETCH_L1(addr) addr -# define PREFETCH_L2(addr) addr -# define PREFETCH_RW(addr) addr #endif /* (un)likely */ #if defined(__clang__) || defined(__GNUC__) From 667067801271648b18a325065d08e68c7a5b191b Mon Sep 17 00:00:00 2001 From: Georgiy Manuilov Date: Sun, 12 Mar 2023 14:45:05 +0100 Subject: [PATCH 628/798] Add fallback function for '_mm512_set_epi8' intrinsic '_mm512_set_epi8' intrinsic is missing in GCC <9. However, its usage can be easily eliminated in favor of '_mm512_set_epi32' with no loss in performance enabling older GCC to benefit from AVX512-optimized codepaths. --- fallback_builtins.h | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/fallback_builtins.h b/fallback_builtins.h index 0ceecc8dd1..447f9ac193 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -72,6 +72,46 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { #endif // __AVX2__ +/* GCC <9 is missing some AVX512 intrinsics. + */ +#ifdef __AVX512F__ +#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 9) +#include + +#define PACK(c0, c1, c2, c3) (((int)(unsigned char)(c0) << 24) | ((int)(unsigned char)(c1) << 16) | \ + ((int)(unsigned char)(c2) << 8) | ((int)(unsigned char)(c3))) + +static inline __m512i _mm512_set_epi8(char __q63, char __q62, char __q61, char __q60, + char __q59, char __q58, char __q57, char __q56, + char __q55, char __q54, char __q53, char __q52, + char __q51, char __q50, char __q49, char __q48, + char __q47, char __q46, char __q45, char __q44, + char __q43, char __q42, char __q41, char __q40, + char __q39, char __q38, char __q37, char __q36, + char __q35, char __q34, char __q33, char __q32, + char __q31, char __q30, char __q29, char __q28, + char __q27, char __q26, char __q25, char __q24, + char __q23, char __q22, char __q21, char __q20, + char __q19, char __q18, char __q17, char __q16, + char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) { + return _mm512_set_epi32(PACK(__q63, __q62, __q61, __q60), PACK(__q59, __q58, __q57, __q56), + PACK(__q55, __q54, __q53, __q52), PACK(__q51, __q50, __q49, __q48), + PACK(__q47, __q46, __q45, __q44), PACK(__q43, __q42, __q41, __q40), + PACK(__q39, __q38, __q37, __q36), PACK(__q35, __q34, __q33, __q32), + PACK(__q31, __q30, __q29, __q28), PACK(__q27, __q26, __q25, __q24), + PACK(__q23, __q22, __q21, __q20), PACK(__q19, __q18, __q17, __q16), + PACK(__q15, __q14, __q13, __q12), PACK(__q11, __q10, __q09, __q08), + PACK(__q07, __q06, __q05, __q04), PACK(__q03, __q02, __q01, __q00)); +} + +#undef PACK + +#endif // gcc version test +#endif // __AVX512F__ + /* Missing zero-extension AVX and AVX512 intrinsics. * Fixed in Microsoft Visual Studio 2017 version 15.7 * https://developercommunity.visualstudio.com/t/missing-zero-extension-avx-and-avx512-intrinsics/175737 From a4d9d697b3f0e65313f6ae70310dccb62c3d542a Mon Sep 17 00:00:00 2001 From: Georgiy Manuilov Date: Sun, 12 Mar 2023 14:45:53 +0100 Subject: [PATCH 629/798] Enable using AVX512 intrinsics with GCC <9 Replace missing '_mm512_set_epi8' with '_mm512_set_epi32' in test code for configuring; Add fallback for '-mtune=cascadelake' flag used when AVX512 is enabled. --- cmake/detect-intrinsics.cmake | 16 ++++++++---- configure | 49 +++++++++++++++++++++++++++++++---- 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 6ce0f3e3c2..7b59cec53c 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -46,7 +46,13 @@ macro(check_avx512_intrinsics) # instruction scheduling unless you specify a reasonable -mtune= target set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl") if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "ClangCl") - set(AVX512FLAG "${AVX512FLAG} -mtune=cascadelake") + check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) + if(HAVE_CASCADE_LAKE) + set(AVX512FLAG "${AVX512FLAG} -mtune=cascadelake") + else() + set(AVX512FLAG "${AVX512FLAG} -mtune=skylake-avx512") + endif() + unset(HAVE_CASCADE_LAKE) endif() endif() elseif(MSVC) @@ -58,10 +64,10 @@ macro(check_avx512_intrinsics) "#include int main(void) { __m512i x = _mm512_set1_epi8(2); - const __m512i y = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64); + const __m512i y = _mm512_set_epi32(0x1020304, 0x5060708, 0x90a0b0c, 0xd0e0f10, + 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, + 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40); x = _mm512_sub_epi8(x, y); (void)x; return 0; diff --git a/configure b/configure index 5dd146386c..eb9e57e90d 100755 --- a/configure +++ b/configure @@ -105,7 +105,7 @@ native=0 forcesse2=0 # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal # instruction scheduling unless you specify a reasonable -mtune= target -avx512flag="-mavx512f -mavx512dq -mavx512bw -mavx512vl -mtune=cascadelake" +avx512flag="-mavx512f -mavx512dq -mavx512bw -mavx512vl" avx512vnniflag="-mavx512vnni ${avx512flag}" avx2flag="-mavx2" sse2flag="-msse2" @@ -1063,10 +1063,10 @@ check_avx512_intrinsics() { #include int main(void) { __m512i x = _mm512_set1_epi8(2); - const __m512i y = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64); + const __m512i y = _mm512_set_epi32(0x1020304, 0x5060708, 0x90a0b0c, 0xd0e0f10, + 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, + 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, + 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40); x = _mm512_sub_epi8(x, y); (void)x; return 0; @@ -1081,6 +1081,35 @@ EOF fi } +check_mtune_skylake_avx512_compiler_flag() { + # Check whether -mtune=skylake-avx512 works correctly + cat > $test.c << EOF +int main() { return 0; } +EOF + if try $CC -c $CFLAGS -mtune=skylake-avx512 $test.c; then + MTUNE_SKYLAKE_AVX512_AVAILABLE=1 + echo "Check whether -mtune=skylake-avx512 works ... Yes." | tee -a configure.log + else + echo "Check whether -mtune=skylake-avx512 works ... No." | tee -a configure.log + MTUNE_SKYLAKE_AVX512_AVAILABLE=0 + fi +} + +check_mtune_cascadelake_compiler_flag() { + # Check whether -mtune=cascadelake works correctly + cat > $test.c << EOF +int main() { return 0; } +EOF + if try $CC -c $CFLAGS -mtune=cascadelake $test.c; then + MTUNE_CASCADELAKE_AVAILABLE=1 + echo "Check whether -mtune=cascadelake works ... Yes." | tee -a configure.log + else + echo "Check whether -mtune=cascadelake works ... No." | tee -a configure.log + MTUNE_CASCADELAKE_AVAILABLE=0 + check_mtune_skylake_avx512_compiler_flag + fi +} + check_avx512vnni_intrinsics() { # Check whether compiler supports AVX512-VNNI intrinsics cat > $test.c << EOF @@ -1567,6 +1596,16 @@ case "${ARCH}" in fi fi + check_mtune_cascadelake_compiler_flag + + if test ${MTUNE_CASCADELAKE_AVAILABLE} -eq 1; then + avx512flag="${avx512flag} -mtune=cascadelake" + else + if test ${MTUNE_SKYLAKE_AVX512_AVAILABLE} -eq 1; then + avx512flag="${avx512flag} -mtune=skylake-avx512" + fi + fi + check_avx512vnni_intrinsics if test ${HAVE_AVX512VNNI_INTRIN} -eq 1; then From fcba18927722da06c5bacc3799526cb11ab2b250 Mon Sep 17 00:00:00 2001 From: "Daisuke Fujimura (fd0)" Date: Thu, 9 Mar 2023 22:16:13 +0900 Subject: [PATCH 630/798] Shared libraries on cygwin can be named with their version number --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 466d12deb3..9ed3b24175 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1102,7 +1102,7 @@ if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "${LIB_INSTALL_DIR}") endif() endif() - if(MSYS OR CYGWIN) + if(MSYS) # Suppress version number from shared library name set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 0) elseif(WIN32) From b09215f75a0b69e19095133c3556e3e9c0686cc0 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Tue, 28 Mar 2023 19:01:44 +0100 Subject: [PATCH 631/798] Enable use of _mm_shuffle_epi8 on machines without SSE4.1 --- CMakeLists.txt | 18 +-------- README.md | 4 +- arch/arm/chunkset_neon.c | 2 +- arch/generic/chunk_permute_table.h | 2 +- arch/x86/Makefile.in | 11 +++-- arch/x86/chunkset_avx.c | 2 +- .../{chunkset_sse41.c => chunkset_ssse3.c} | 14 +++---- arch/x86/x86_features.c | 1 - arch/x86/x86_features.h | 1 - chunkset_tpl.h | 8 ++-- cmake/detect-intrinsics.cmake | 28 ------------- configure | 40 +------------------ cpu_features.h | 8 ++-- functable.c | 13 +++--- win32/Makefile.msc | 2 + 15 files changed, 37 insertions(+), 117 deletions(-) rename arch/x86/{chunkset_sse41.c => chunkset_ssse3.c} (87%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ed3b24175..e5184cca30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -117,7 +117,6 @@ elseif(BASEARCH_X86_FOUND) option(WITH_AVX512VNNI "Build with AVX512 VNNI extensions" ON) option(WITH_SSE2 "Build with SSE2" ON) option(WITH_SSSE3 "Build with SSSE3" ON) - option(WITH_SSE41 "Build with SSE41" ON) option(WITH_SSE42 "Build with SSE42" ON) option(WITH_PCLMULQDQ "Build with PCLMULQDQ" ON) option(WITH_VPCLMULQDQ "Build with VPCLMULQDQ" ON) @@ -133,8 +132,7 @@ mark_as_advanced(FORCE WITH_DFLTCC_INFLATE WITH_CRC32_VX WITH_AVX2 WITH_SSE2 - WITH_SSSE3 WITH_SSE41 - WITH_SSE42 + WITH_SSSE3 WITH_SSE42 WITH_PCLMULQDQ WITH_ALTIVEC WITH_POWER8 @@ -787,17 +785,6 @@ if(WITH_OPTIM) set(WITH_AVX512VNNI OFF) endif() endif() - if(WITH_SSE41) - check_sse41_intrinsics() - if(HAVE_SSE41_INTRIN) - add_definitions(-DX86_SSE41) - list(APPEND SSE41_SRCS ${ARCHDIR}/chunkset_sse41.c) - list(APPEND ZLIB_ARCH_SRCS ${SSE41_SRCS}) - set_property(SOURCE ${SSE41_SRCS} PROPERTY COMPILE_FLAGS "${SSE41FLAG} ${NOLTOFLAG}") - else() - set(WITH_SSE41 OFF) - endif() - endif() if(WITH_SSE42) check_sse42_intrinsics() if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) @@ -835,7 +822,7 @@ if(WITH_OPTIM) check_ssse3_intrinsics() if(HAVE_SSSE3_INTRIN) add_definitions(-DX86_SSSE3) - set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c) + set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c ${ARCHDIR}/chunkset_ssse3.c) add_feature_info(SSSE3_ADLER32 1 "Support SSSE3-accelerated adler32, using \"${SSSE3FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${NOLTOFLAG}") @@ -1226,7 +1213,6 @@ elseif(BASEARCH_X86_FOUND) add_feature_info(WITH_AVX512VNNI WITH_AVX512VNNI "Build with AVX512 VNNI") add_feature_info(WITH_SSE2 WITH_SSE2 "Build with SSE2") add_feature_info(WITH_SSSE3 WITH_SSSE3 "Build with SSSE3") - add_feature_info(WITH_SSE41 WITH_SSE41 "Build with SSE41") add_feature_info(WITH_SSE42 WITH_SSE42 "Build with SSE42") add_feature_info(WITH_PCLMULQDQ WITH_PCLMULQDQ "Build with PCLMULQDQ") add_feature_info(WITH_VPCLMULQDQ WITH_VPCLMULQDQ "Build with VPCLMULQDQ") diff --git a/README.md b/README.md index 5b8e8ccdc2..aa72365c95 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Features * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX * Compare256 implementations using SSE2, AVX2, Neon, & POWER9 - * Inflate chunk copying using SSE2, AVX, Neon & VSX + * Inflate chunk copying using SSE2, SSSE3, AVX, Neon & VSX * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements * Includes improvements from Cloudflare and Intel forks @@ -213,7 +213,7 @@ Advanced Build Options | WITH_AVX512 | | Build with AVX512 intrinsics | ON | | WITH_AVX512VNNI | | Build with AVX512VNNI intrinsics | ON | | WITH_SSE2 | | Build with SSE2 intrinsics | ON | -| WITH_SSE41 | | Build with SSE41 intrinsics | ON | +| WITH_SSSE3 | | Build with SSSE3 intrinsics | ON | | WITH_SSE42 | | Build with SSE42 intrinsics | ON | | WITH_PCLMULQDQ | | Build with PCLMULQDQ intrinsics | ON | | WITH_VPCLMULQDQ | --without-vpclmulqdq | Build with VPCLMULQDQ intrinsics | ON | diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 668c0019e9..1890c91356 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -69,7 +69,7 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t *chunk_rem = lut_rem.remval; #ifdef Z_MEMORY_SANITIZER - /* See note in chunkset_sse41.c for why this is ok */ + /* See note in chunkset_ssse3.c for why this is ok */ __msan_unpoison(buf + dist, 16 - dist); #endif diff --git a/arch/generic/chunk_permute_table.h b/arch/generic/chunk_permute_table.h index c7b2d2de7f..bad66ccc77 100644 --- a/arch/generic/chunk_permute_table.h +++ b/arch/generic/chunk_permute_table.h @@ -1,4 +1,4 @@ -/* chunk_permute_table.h - shared AVX/SSE4 permutation table for use with chunkmemset family of functions. +/* chunk_permute_table.h - shared AVX/SSSE3 permutation table for use with chunkmemset family of functions. * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 4cebe55531..5fd51929ce 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -13,7 +13,6 @@ AVX512VNNIFLAG=-mavx512vnni AVX2FLAG=-mavx2 SSE2FLAG=-msse2 SSSE3FLAG=-mssse3 -SSE41FLAG=-msse4.1 SSE42FLAG=-msse4.2 PCLMULFLAG=-mpclmul VPCLMULFLAG=-mvpclmulqdq @@ -33,7 +32,7 @@ all: \ adler32_ssse3.o adler32_ssse3.lo \ chunkset_avx.o chunkset_avx.lo \ chunkset_sse2.o chunkset_sse2.lo \ - chunkset_sse41.o chunkset_sse41.lo \ + chunkset_ssse3.o chunkset_ssse3.lo \ compare256_avx2.o compare256_avx2.lo \ compare256_sse2.o compare256_sse2.lo \ insert_string_sse42.o insert_string_sse42.lo \ @@ -60,11 +59,11 @@ chunkset_sse2.o: chunkset_sse2.lo: $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse2.c -chunkset_sse41.o: - $(CC) $(CFLAGS) $(SSE41FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse41.c +chunkset_ssse3.o: + $(CC) $(CFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_ssse3.c -chunkset_sse41.lo: - $(CC) $(SFLAGS) $(SSE41FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse41.c +chunkset_ssse3.lo: + $(CC) $(SFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_ssse3.c compare256_avx2.o: $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_avx2.c diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index c2df2322fe..abcbb474f5 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -85,7 +85,7 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t *chunk_rem = lut_rem.remval; #ifdef Z_MEMORY_SANITIZER - /* See note in chunkset_sse4.c for why this is ok */ + /* See note in chunkset_ssse3.c for why this is ok */ __msan_unpoison(buf + dist, 32 - dist); #endif diff --git a/arch/x86/chunkset_sse41.c b/arch/x86/chunkset_ssse3.c similarity index 87% rename from arch/x86/chunkset_sse41.c rename to arch/x86/chunkset_ssse3.c index 4b7396bcac..0bd6263859 100644 --- a/arch/x86/chunkset_sse41.c +++ b/arch/x86/chunkset_ssse3.c @@ -1,13 +1,13 @@ -/* chunkset_sse41.c -- SSE4 inline functions to copy small data chunks. +/* chunkset_ssse3.c -- SSSE3 inline functions to copy small data chunks. * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zbuild.h" -/* This requires SSE2 support. While it's implicit with SSE4, we can minimize +/* This requires SSE2 support. While it's implicit with SSSE3, we can minimize * code size by sharing the chunkcopy functions, which will certainly compile * to identical machine code */ -#if defined(X86_SSE41) && defined(X86_SSE2) +#if defined(X86_SSSE3) && defined(X86_SSE2) #include #include "../generic/chunk_permute_table.h" @@ -88,15 +88,15 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); -#define CHUNKSIZE chunksize_sse41 -#define CHUNKMEMSET chunkmemset_sse41 -#define CHUNKMEMSET_SAFE chunkmemset_safe_sse41 +#define CHUNKSIZE chunksize_ssse3 +#define CHUNKMEMSET chunkmemset_ssse3 +#define CHUNKMEMSET_SAFE chunkmemset_safe_ssse3 #define CHUNKCOPY chunkcopy_sse2 #define CHUNKUNROLL chunkunroll_sse2 #include "chunkset_tpl.h" -#define INFLATE_FAST inflate_fast_sse41 +#define INFLATE_FAST inflate_fast_ssse3 #include "inffast_tpl.h" diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index f60ddbcf94..3272e3fdd9 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -66,7 +66,6 @@ void Z_INTERNAL x86_check_features(struct x86_cpu_features *features) { features->has_sse2 = edx & 0x4000000; features->has_ssse3 = ecx & 0x200; - features->has_sse41 = ecx & 0x80000; features->has_sse42 = ecx & 0x100000; features->has_pclmulqdq = ecx & 0x2; diff --git a/arch/x86/x86_features.h b/arch/x86/x86_features.h index 00b510ffc1..4a36bde835 100644 --- a/arch/x86/x86_features.h +++ b/arch/x86/x86_features.h @@ -12,7 +12,6 @@ struct x86_cpu_features { int has_avx512vnni; int has_sse2; int has_ssse3; - int has_sse41; int has_sse42; int has_pclmulqdq; int has_vpclmulqdq; diff --git a/chunkset_tpl.h b/chunkset_tpl.h index f70ef42cdb..f909a12557 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -5,8 +5,8 @@ #include "zbuild.h" #include -#if CHUNK_SIZE == 32 && defined(X86_SSE41) && defined(X86_SSE2) -extern uint8_t* chunkmemset_sse41(uint8_t *out, unsigned dist, unsigned len); +#if CHUNK_SIZE == 32 && defined(X86_SSSE3) && defined(X86_SSE2) +extern uint8_t* chunkmemset_ssse3(uint8_t *out, unsigned dist, unsigned len); #endif /* Returns the chunk size */ @@ -98,9 +98,9 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { Assert(len >= sizeof(uint64_t), "chunkmemset should be called on larger chunks"); */ Assert(dist > 0, "chunkmemset cannot have a distance 0"); /* Only AVX2 */ -#if CHUNK_SIZE == 32 && defined(X86_SSE41) && defined(X86_SSE2) +#if CHUNK_SIZE == 32 && defined(X86_SSSE3) && defined(X86_SSE2) if (len <= 16) { - return chunkmemset_sse41(out, dist, len); + return chunkmemset_ssse3(out, dist, len); } #endif diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 7b59cec53c..186d87d814 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -435,34 +435,6 @@ macro(check_ssse3_intrinsics) ) endmacro() -macro(check_sse41_intrinsics) - if(CMAKE_C_COMPILER_ID MATCHES "Intel") - if(CMAKE_HOST_UNIX OR APPLE) - set(SSE41FLAG "-msse4.1") - else() - set(SSE41FLAG "/arch:SSE4.1") - endif() - elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") - if(NOT NATIVEFLAG) - set(SSE41FLAG "-msse4.1") - endif() - endif() - # Check whether compiler supports SSE4.1 intrinsics - set(CMAKE_REQUIRED_FLAGS "${SSE41FLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( - "#include - int main(void) { - __m128i u, v, w; - u = _mm_set1_epi8(1); - v = _mm_set1_epi8(2); - w = _mm_sad_epu8(u, v); - (void)w; - return 0; - }" - HAVE_SSE41_INTRIN - ) -endmacro() - macro(check_sse42_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "Intel") if(CMAKE_HOST_UNIX OR APPLE) diff --git a/configure b/configure index eb9e57e90d..2c320227fe 100755 --- a/configure +++ b/configure @@ -110,7 +110,6 @@ avx512vnniflag="-mavx512vnni ${avx512flag}" avx2flag="-mavx2" sse2flag="-msse2" ssse3flag="-mssse3" -sse41flag="-msse4.1" sse42flag="-msse4.2" pclmulflag="-mpclmul" vpclmulflag="-mvpclmulqdq -mavx512f" @@ -1399,29 +1398,6 @@ EOF fi } -check_sse41_intrinsics() { - # Check whether compiler supports SSE4.1 intrinsics - cat > $test.c << EOF -#include -int main(void) -{ - __m128i u, v, w; - u = _mm_set1_epi8(1); - v = _mm_set1_epi8(2); - w = _mm_sad_epu8(u, v); - (void)w; - return 0; -} -EOF - if try ${CC} ${CFLAGS} ${sse41flag} $test.c; then - echo "Checking for SSE4.1 intrinsics ... Yes." | tee -a configure.log - HAVE_SSE41_INTRIN=1 - else - echo "Checking for SSE4.1 intrinsics ... No." | tee -a configure.log - HAVE_SSE41_INTRIN=0 - fi -} - check_sse42_intrinsics() { # Check whether compiler supports SSE4 CRC inline asm cat > $test.c << EOF @@ -1615,16 +1591,6 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_avx512_vnni.lo" fi - check_sse41_intrinsics - - if test ${HAVE_SSE41_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE41" - SFLAGS="${SFLAGS} -DX86_SSE41" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse41.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse41.lo" - fi - check_sse42_intrinsics if test ${HAVE_SSE42CRC_INTRIN} -eq 1 || test ${HAVE_SSE42CRC_INLINE_ASM} -eq 1; then @@ -1659,8 +1625,8 @@ case "${ARCH}" in if test ${HAVE_SSSE3_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSSE3" SFLAGS="${SFLAGS} -DX86_SSSE3" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_ssse3.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_ssse3.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_ssse3.o chunkset_ssse3.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_ssse3.lo chunkset_ssse3.lo" fi check_pclmulqdq_intrinsics @@ -2111,7 +2077,6 @@ echo sharedlibdir = $sharedlibdir >> configure.log echo uname = $uname >> configure.log echo sse2flag = $sse2flag >> configure.log echo ssse3flag = $ssse3flag >> configure.log -echo sse41flag = $sse41flag >> configure.log echo sse42flag = $sse42flag >> configure.log echo pclmulflag = $pclmulflag >> configure.log echo vpclmulflag = $vpclmulflag >> configure.log @@ -2250,7 +2215,6 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^AVX512VNNIFLAG *=/s#=.*#=$avx512vnniflag# /^SSE2FLAG *=/s#=.*#=$sse2flag# /^SSSE3FLAG *=/s#=.*#=$ssse3flag# -/^SSE41FLAG *=/s#=.*#=$sse41flag# /^SSE42FLAG *=/s#=.*#=$sse42flag# /^PCLMULFLAG *=/s#=.*#=$pclmulflag# /^VPCLMULFLAG *=/s#=.*#=$vpclmulflag# diff --git a/cpu_features.h b/cpu_features.h index 462671a187..e47f947826 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -99,8 +99,8 @@ extern uint8_t* chunkmemset_safe_c(uint8_t *out, unsigned dist, unsigned len, un extern uint32_t chunksize_sse2(void); extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif -#ifdef X86_SSE41 -extern uint8_t* chunkmemset_safe_sse41(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#ifdef X86_SSSE3 +extern uint8_t* chunkmemset_safe_ssse3(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif #ifdef X86_AVX2 extern uint32_t chunksize_avx(void); @@ -126,8 +126,8 @@ extern void inflate_fast_c(PREFIX3(stream) *strm, uint32_t start); #ifdef X86_SSE2 extern void inflate_fast_sse2(PREFIX3(stream) *strm, uint32_t start); #endif -#ifdef X86_SSE41 -extern void inflate_fast_sse41(PREFIX3(stream) *strm, uint32_t start); +#ifdef X86_SSSE3 +extern void inflate_fast_ssse3(PREFIX3(stream) *strm, uint32_t start); #endif #ifdef X86_AVX2 extern void inflate_fast_avx(PREFIX3(stream) *strm, uint32_t start); diff --git a/functable.c b/functable.c index c7d477c7f0..4212da0907 100644 --- a/functable.c +++ b/functable.c @@ -75,16 +75,15 @@ static void init_functable(void) { #endif // X86 - SSSE3 #ifdef X86_SSSE3 - if (cf.x86.has_ssse3) + if (cf.x86.has_ssse3) { ft.adler32 = &adler32_ssse3; -#endif - // X86 - SSE4 -#if defined(X86_SSE41) && defined(X86_SSE2) - if (cf.x86.has_sse41) { - ft.chunkmemset_safe = &chunkmemset_safe_sse41; - ft.inflate_fast = &inflate_fast_sse41; +# ifdef X86_SSE2 + ft.chunkmemset_safe = &chunkmemset_safe_ssse3; + ft.inflate_fast = &inflate_fast_ssse3; +# endif } #endif + // X86 - SSE4.2 #ifdef X86_SSE42 if (cf.x86.has_sse42) { ft.adler32_fold_copy = &adler32_fold_copy_sse42; diff --git a/win32/Makefile.msc b/win32/Makefile.msc index d2a98d6f0a..8a01e31710 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -56,6 +56,7 @@ OBJS = \ chunkset.obj \ chunkset_avx.obj \ chunkset_sse2.obj \ + chunkset_ssse3.obj \ compare256.obj \ compare256_avx2.obj \ compare256_sse2.obj \ @@ -202,6 +203,7 @@ uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_avx.obj: $(SRCDIR)/arch/x86/chunkset_avx.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_sse2.obj: $(SRCDIR)/arch/x86/chunkset_sse2.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h +chunkset_ssse3.obj: $(SRCDIR)/arch/x86/chunkset_ssse3.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h crc32_braid.obj: $(SRCDIR)/crc32_braid.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h crc32_braid_comb.obj: $(SRCDIR)/crc32_braid_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/crc32_braid_p.h $(SRCDIR)/crc32_braid_tbl.h $(SRCDIR)/crc32_braid_comb_p.h From c4c1c7f6e039d821cf36ed3b994ae14018fe31e1 Mon Sep 17 00:00:00 2001 From: lawadr <3211473+lawadr@users.noreply.github.com> Date: Thu, 30 Mar 2023 16:29:38 +0100 Subject: [PATCH 632/798] Remove architecture dependent endian header locations The header locations are OS specific and not architecture specific. The previous behaviour was to always include machine/endian.h for ARM and AArch64 architectures on non-Windows and non-Linux OSs, causing build failures if the OS uses other locations defined further down the conditional block. --- zendian.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zendian.h b/zendian.h index 54718ed14f..3fdb13041a 100644 --- a/zendian.h +++ b/zendian.h @@ -34,7 +34,7 @@ # endif #elif defined(__linux__) # include -#elif defined(__APPLE__) || defined(__arm__) || defined(__aarch64__) +#elif defined(__APPLE__) # include #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__DragonFly__) # include From 7a60d93829d7cc17a9974896a5e0b85ea9a0ba5e Mon Sep 17 00:00:00 2001 From: lawadr <3211473+lawadr@users.noreply.github.com> Date: Thu, 30 Mar 2023 20:37:14 +0100 Subject: [PATCH 633/798] Check for attribute aligned compiler support Check for compiler support in CMake and the configure script. This allows ALIGNED_ to be defined for more compilers so that more than just Clang, GCC and MSVC can build the project. --- CMakeLists.txt | 14 ++++++++++++++ configure | 16 ++++++++++++++++ zbuild.h | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e5184cca30..ffde3d2949 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -391,6 +391,20 @@ if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL) add_definitions(-DHAVE_VISIBILITY_INTERNAL) endif() +# +# Check for __attribute__((aligned(x))) support in the compiler +# +check_c_source_compiles( + "int main(void) { + __attribute__((aligned(8))) int test = 0; + (void)test; + return 0; + }" + HAVE_ATTRIBUTE_ALIGNED FAIL_REGEX "aligned") +if(HAVE_ATTRIBUTE_ALIGNED) + add_definitions(-DHAVE_ATTRIBUTE_ALIGNED) +endif() + # # check for _Thread_local() support in the compiler # diff --git a/configure b/configure index 2c320227fe..896b0b8a4f 100755 --- a/configure +++ b/configure @@ -985,6 +985,22 @@ EOF fi fi +# Check for attribute(aligned) support in compiler +cat > $test.c << EOF +int main(void) { + __attribute__((aligned(8))) int test = 0; + (void)test; + return 0; +} +EOF +if try ${CC} ${CFLAGS} $test.c $LDSHAREDLIBC; then + echo "Checking for attribute(aligned) ... Yes." | tee -a configure.log + CFLAGS="$CFLAGS -DHAVE_ATTRIBUTE_ALIGNED" + SFLAGS="$SFLAGS -DHAVE_ATTRIBUTE_ALIGNED" +else + echo "Checking for attribute(aligned) ... No." | tee -a configure.log +fi + # Check for _Thread_local support in compiler cat > $test.c << EOF _Thread_local int test; diff --git a/zbuild.h b/zbuild.h index de1999cff4..922b2cae2c 100644 --- a/zbuild.h +++ b/zbuild.h @@ -190,7 +190,7 @@ # define UNLIKELY(x) x #endif /* (un)likely */ -#if defined(__clang__) || defined(__GNUC__) +#if defined(HAVE_ATTRIBUTE_ALIGNED) # define ALIGNED_(x) __attribute__ ((aligned(x))) #elif defined(_MSC_VER) # define ALIGNED_(x) __declspec(align(x)) From b1aafe5c674909ab134301b86c41f1badc3fa83b Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Tue, 28 Mar 2023 22:05:20 +0100 Subject: [PATCH 634/798] Clean up SSE4.2 detection --- .github/workflows/cmake.yml | 6 +++--- CMakeLists.txt | 5 ++--- arch/x86/insert_string_sse42.c | 6 +++--- cmake/detect-intrinsics.cmake | 17 ++--------------- configure | 24 +----------------------- cpu_features.h | 6 +++--- functable.c | 6 +++--- 7 files changed, 17 insertions(+), 53 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index b4b5897fd6..d50a2dcfab 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -105,12 +105,12 @@ jobs: cmake-args: -DWITH_SSE2=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_sse2 - - name: Ubuntu GCC No SSE4 UBSAN + - name: Ubuntu GCC No SSE4.2 UBSAN os: ubuntu-latest compiler: gcc cxx-compiler: g++ - cmake-args: -DWITH_SSE4=OFF -DWITH_SANITIZER=Undefined - codecov: ubuntu_gcc_no_sse4 + cmake-args: -DWITH_SSE42=OFF -DWITH_SANITIZER=Undefined + codecov: ubuntu_gcc_no_sse42 - name: Ubuntu GCC No PCLMULQDQ UBSAN os: ubuntu-latest diff --git a/CMakeLists.txt b/CMakeLists.txt index ffde3d2949..285974c7bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -810,9 +810,8 @@ if(WITH_OPTIM) if(HAVE_SSE42CRC_INTRIN) add_definitions(-DX86_SSE42_CRC_INTRIN) endif() - endif() - if(NOT HAVE_SSE42CRC_INLINE_ASM AND NOT HAVE_SSE42CRC_INTRIN AND NOT HAVE_SSE42CMPSTR_INTRIN) - set(WITH_SSE4 OFF) + else() + set(WITH_SSE42 OFF) endif() endif() if(WITH_SSE2) diff --git a/arch/x86/insert_string_sse42.c b/arch/x86/insert_string_sse42.c index 2668f0eaa8..565d92f97c 100644 --- a/arch/x86/insert_string_sse42.c +++ b/arch/x86/insert_string_sse42.c @@ -41,9 +41,9 @@ #define HASH_CALC_VAR h #define HASH_CALC_VAR_INIT uint32_t h = 0 -#define UPDATE_HASH update_hash_sse4 -#define INSERT_STRING insert_string_sse4 -#define QUICK_INSERT_STRING quick_insert_string_sse4 +#define UPDATE_HASH update_hash_sse42 +#define INSERT_STRING insert_string_sse42 +#define QUICK_INSERT_STRING quick_insert_string_sse42 #ifdef X86_SSE42 # include "../../insert_string_tpl.h" diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 186d87d814..0491d53bf8 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -447,7 +447,7 @@ macro(check_sse42_intrinsics) set(SSE42FLAG "-msse4.2") endif() endif() - # Check whether compiler supports SSE4 CRC inline asm + # Check whether compiler supports SSE4.2 CRC inline asm set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "int main(void) { @@ -461,7 +461,7 @@ macro(check_sse42_intrinsics) }" HAVE_SSE42CRC_INLINE_ASM ) - # Check whether compiler supports SSE4 CRC intrinsics + # Check whether compiler supports SSE4.2 CRC intrinsics check_c_source_compile_or_run( "#include int main(void) { @@ -477,19 +477,6 @@ macro(check_sse42_intrinsics) }" HAVE_SSE42CRC_INTRIN ) - # Check whether compiler supports SSE4.2 compare string intrinsics - check_c_source_compile_or_run( - "#include - int main(void) { - unsigned char a[64] = { 0 }; - unsigned char b[64] = { 0 }; - __m128i xmm_src0, xmm_src1; - xmm_src0 = _mm_loadu_si128((__m128i *)(char *)a); - xmm_src1 = _mm_loadu_si128((__m128i *)(char *)b); - return _mm_cmpestri(xmm_src0, 16, xmm_src1, 16, 0); - }" - HAVE_SSE42CMPSTR_INTRIN - ) set(CMAKE_REQUIRED_FLAGS) endmacro() diff --git a/configure b/configure index 896b0b8a4f..2867302b37 100755 --- a/configure +++ b/configure @@ -262,7 +262,6 @@ if test $native -eq 1; then avx2flag="" sse2flag="" ssse3flag="" - sse4flag="" sse42flag="" pclmulflag="" vpclmulflag="" @@ -1415,7 +1414,7 @@ EOF } check_sse42_intrinsics() { - # Check whether compiler supports SSE4 CRC inline asm + # Check whether compiler supports SSE4.2 CRC inline asm cat > $test.c << EOF int main(void) { unsigned val = 0, h = 0; @@ -1448,27 +1447,6 @@ EOF echo "Checking for SSE4.2 CRC intrinsics ... No." | tee -a configure.log HAVE_SSE42CRC_INTRIN=0 fi - - # Check whether compiler supports SSE4.2 compare string intrinsics - cat > $test.c << EOF -#include -int main(void) -{ - unsigned char a[64] = { 0 }; - unsigned char b[64] = { 0 }; - __m128i xmm_src0, xmm_src1; - xmm_src0 = _mm_loadu_si128((__m128i *)(char *)a); - xmm_src1 = _mm_loadu_si128((__m128i *)(char *)b); - return _mm_cmpestri(xmm_src0, 16, xmm_src1, 16, 0); -} -EOF - if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 compare string intrinsics ... Yes." | tee -a configure.log - HAVE_SSE42CMPSTR_INTRIN=1 - else - echo "Checking for SSE4.2 compare string intrinsics ... No." | tee -a configure.log - HAVE_SSE42CMPSTR_INTRIN=0 - fi } check_ssse3_intrinsics() { diff --git a/cpu_features.h b/cpu_features.h index e47f947826..c742f32c66 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -181,7 +181,7 @@ extern uint32_t compare256_power9(const uint8_t *src0, const uint8_t *src1); /* insert_string */ extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); #ifdef X86_SSE42 -extern void insert_string_sse4(deflate_state *const s, const uint32_t str, uint32_t count); +extern void insert_string_sse42(deflate_state *const s, const uint32_t str, uint32_t count); #elif defined(ARM_ACLE) extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint32_t count); #endif @@ -235,7 +235,7 @@ extern uint32_t longest_match_slow_power9(deflate_state *const s, Pos cur_match) /* quick_insert_string */ extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); #ifdef X86_SSE42 -extern Pos quick_insert_string_sse4(deflate_state *const s, const uint32_t str); +extern Pos quick_insert_string_sse42(deflate_state *const s, const uint32_t str); #elif defined(ARM_ACLE) extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); #endif @@ -261,7 +261,7 @@ extern void slide_hash_avx2(deflate_state *s); /* update_hash */ extern uint32_t update_hash_c(deflate_state *const s, uint32_t h, uint32_t val); #ifdef X86_SSE42 -extern uint32_t update_hash_sse4(deflate_state *const s, uint32_t h, uint32_t val); +extern uint32_t update_hash_sse42(deflate_state *const s, uint32_t h, uint32_t val); #elif defined(ARM_ACLE) extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); #endif diff --git a/functable.c b/functable.c index 4212da0907..f9e8163d3a 100644 --- a/functable.c +++ b/functable.c @@ -87,9 +87,9 @@ static void init_functable(void) { #ifdef X86_SSE42 if (cf.x86.has_sse42) { ft.adler32_fold_copy = &adler32_fold_copy_sse42; - ft.insert_string = &insert_string_sse4; - ft.quick_insert_string = &quick_insert_string_sse4; - ft.update_hash = &update_hash_sse4; + ft.insert_string = &insert_string_sse42; + ft.quick_insert_string = &quick_insert_string_sse42; + ft.update_hash = &update_hash_sse42; } #endif // X86 - PCLMUL From fb4f9569c661976e2680974da3ff616e2ae0056f Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Fri, 17 Mar 2023 23:27:38 +0500 Subject: [PATCH 635/798] Switch to the standard CMake module GNUInstallDirs Signed-off-by: Vladislav Shchapov --- CMakeLists.txt | 26 ++++++++++++---------- cmake/detect-install-dirs.cmake | 39 ++++++++++----------------------- test/CMakeLists.txt | 6 ++--- test/pkgcheck.sh | 2 +- 4 files changed, 31 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 285974c7bc..0dcd76be62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -927,15 +927,19 @@ endif() # Refer to prefix symbolically to ease relocation by end user, # as Makefile-generated .pc file does. -if(INC_INSTALL_DIR STREQUAL "${CMAKE_INSTALL_PREFIX}/include") +if(NOT IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") + set(PC_INC_INSTALL_DIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") +elseif(CMAKE_INSTALL_INCLUDEDIR STREQUAL "${CMAKE_INSTALL_PREFIX}/include") set(PC_INC_INSTALL_DIR "\${prefix}/include") else() - set(PC_INC_INSTALL_DIR "${INC_INSTALL_DIR}") + set(PC_INC_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") endif() -if(LIB_INSTALL_DIR STREQUAL "${CMAKE_INSTALL_PREFIX}/lib") +if(NOT IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") + set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") +elseif(CMAKE_INSTALL_LIBDIR STREQUAL "${CMAKE_INSTALL_PREFIX}/lib") set(PC_LIB_INSTALL_DIR "\${exec_prefix}/lib") else() - set(PC_LIB_INSTALL_DIR "${LIB_INSTALL_DIR}") + set(PC_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") endif() #============================================================================ @@ -1099,7 +1103,7 @@ if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.map\"") else() # Match configure/make's behavior (i.e. don't use @rpath on mac). - set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "${LIB_INSTALL_DIR}") + set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}") endif() endif() if(MSYS) @@ -1151,17 +1155,17 @@ endif() if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) install(TARGETS ${ZLIB_INSTALL_LIBRARIES} - RUNTIME DESTINATION "${BIN_INSTALL_DIR}" - ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" - LIBRARY DESTINATION "${LIB_INSTALL_DIR}") + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") endif() if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zlib${SUFFIX}.h - DESTINATION "${INC_INSTALL_DIR}" RENAME zlib${SUFFIX}.h) + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" RENAME zlib${SUFFIX}.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zlib_name_mangling${SUFFIX}.h - DESTINATION "${INC_INSTALL_DIR}" RENAME zlib_name_mangling${SUFFIX}.h) + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" RENAME zlib_name_mangling${SUFFIX}.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h - DESTINATION "${INC_INSTALL_DIR}" RENAME zconf${SUFFIX}.h) + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" RENAME zconf${SUFFIX}.h) endif() if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL) install(FILES ${ZLIB_PC} DESTINATION "${PKGCONFIG_INSTALL_DIR}") diff --git a/cmake/detect-install-dirs.cmake b/cmake/detect-install-dirs.cmake index ddf1adb8c2..2d31a59fb3 100644 --- a/cmake/detect-install-dirs.cmake +++ b/cmake/detect-install-dirs.cmake @@ -4,41 +4,23 @@ # Determine installation directory for executables if (DEFINED BIN_INSTALL_DIR) - set(BIN_INSTALL_DIR "${BIN_INSTALL_DIR}" CACHE PATH "Installation directory for executables" FORCE) + set(CMAKE_INSTALL_BINDIR "${BIN_INSTALL_DIR}") elseif (DEFINED INSTALL_BIN_DIR) - set(BIN_INSTALL_DIR "${INSTALL_BIN_DIR}" CACHE PATH "Installation directory for executables" FORCE) -elseif (DEFINED CMAKE_INSTALL_FULL_BINDIR) - set(BIN_INSTALL_DIR "${CMAKE_INSTALL_FULL_BINDIR}" CACHE PATH "Installation directory for executables" FORCE) -elseif (DEFINED CMAKE_INSTALL_BINDIR) - set(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}" CACHE PATH "Installation directory for executables" FORCE) -else() - set(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") + set(CMAKE_INSTALL_BINDIR "${INSTALL_BIN_DIR}") endif() # Determine installation directory for libraries if (DEFINED LIB_INSTALL_DIR) - set(LIB_INSTALL_DIR "${LIB_INSTALL_DIR}" CACHE PATH "Installation directory for libraries" FORCE) + set(CMAKE_INSTALL_LIBDIR "${LIB_INSTALL_DIR}") elseif (DEFINED INSTALL_LIB_DIR) - set(LIB_INSTALL_DIR "${INSTALL_LIB_DIR}" CACHE PATH "Installation directory for libraries" FORCE) -elseif (DEFINED CMAKE_INSTALL_FULL_LIBDIR) - set(LIB_INSTALL_DIR "${CMAKE_INSTALL_FULL_LIBDIR}" CACHE PATH "Installation directory for libraries" FORCE) -elseif (DEFINED CMAKE_INSTALL_LIBDIR) - set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" CACHE PATH "Installation directory for libraries" FORCE) -else() - set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") + set(CMAKE_INSTALL_LIBDIR "${INSTALL_LIB_DIR}") endif() # Determine installation directory for include files if (DEFINED INC_INSTALL_DIR) - set(INC_INSTALL_DIR "${INC_INSTALL_DIR}" CACHE PATH "Installation directory for headers" FORCE) + set(CMAKE_INSTALL_INCLUDEDIR "${INC_INSTALL_DIR}") elseif (DEFINED INSTALL_INC_DIR) - set(INC_INSTALL_DIR "${INSTALL_INC_DIR}" CACHE PATH "Installation directory for headers" FORCE) -elseif (DEFINED CMAKE_INSTALL_FULL_INCLUDEDIR) - set(INC_INSTALL_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}" CACHE PATH "Installation directory for headers" FORCE) -elseif (DEFINED CMAKE_INSTALL_INCLUDEDIR) - set(INC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}" CACHE PATH "Installation directory for headers" FORCE) -else() - set(INC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") + set(CMAKE_INSTALL_INCLUDEDIR "${INSTALL_INC_DIR}") endif() # Determine installation directory for pkgconfig files @@ -46,10 +28,13 @@ if (DEFINED PKGCONFIG_INSTALL_DIR) set(PKGCONFIG_INSTALL_DIR "${PKGCONFIG_INSTALL_DIR}" CACHE PATH "Installation directory for pkgconfig (.pc) files" FORCE) elseif (DEFINED INSTALL_PKGCONFIG_DIR) set(PKGCONFIG_INSTALL_DIR "${INSTALL_PKGCONFIG_DIR}" CACHE PATH "Installation directory for pkgconfig (.pc) files" FORCE) +elseif (DEFINED CMAKE_INSTALL_PKGCONFIGDIR) + set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_PKGCONFIGDIR}" CACHE PATH "Installation directory for pkgconfig (.pc) files" FORCE) elseif (DEFINED CMAKE_INSTALL_FULL_PKGCONFIGDIR) set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_FULL_PKGCONFIGDIR}" CACHE PATH "Installation directory for pkgconfig (.pc) files" FORCE) -elseif (DEFINED CMAKE_INSTALL_PKGCONFIGDIR) - set(PKGCONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/${CMAKE_INSTALL_PKGCONFIGDIR}" CACHE PATH "Installation directory for pkgconfig (.pc) files" FORCE) else() - set(PKGCONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") + set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") endif() + +# Define GNU standard installation directories +include(GNUInstallDirs) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e8819899ed..007509a215 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -39,9 +39,9 @@ set(MINIDEFLATE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ Date: Sat, 18 Mar 2023 14:43:37 +0500 Subject: [PATCH 636/798] Fix .pc file paths Signed-off-by: Vladislav Shchapov --- CMakeLists.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dcd76be62..8fba45535e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -927,17 +927,24 @@ endif() # Refer to prefix symbolically to ease relocation by end user, # as Makefile-generated .pc file does. +string(FIND "${CMAKE_INSTALL_INCLUDEDIR}" "${CMAKE_INSTALL_PREFIX}/" INCLUDEDIR_POS) +string(FIND "${CMAKE_INSTALL_LIBDIR}" "${CMAKE_INSTALL_PREFIX}/" LIBDIR_POS) +string(LENGTH "${CMAKE_INSTALL_PREFIX}/" INSTALL_PREFIX_LEN) + if(NOT IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") set(PC_INC_INSTALL_DIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") -elseif(CMAKE_INSTALL_INCLUDEDIR STREQUAL "${CMAKE_INSTALL_PREFIX}/include") - set(PC_INC_INSTALL_DIR "\${prefix}/include") +elseif(INCLUDEDIR_POS EQUAL 0) + string(SUBSTRING "${CMAKE_INSTALL_INCLUDEDIR}" "${INSTALL_PREFIX_LEN}" "-1" INCLUDEDIR_RELATIVE) + set(PC_INC_INSTALL_DIR "\${prefix}/${INCLUDEDIR_RELATIVE}") else() set(PC_INC_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") endif() + if(NOT IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") -elseif(CMAKE_INSTALL_LIBDIR STREQUAL "${CMAKE_INSTALL_PREFIX}/lib") - set(PC_LIB_INSTALL_DIR "\${exec_prefix}/lib") +elseif(LIBDIR_POS EQUAL 0) + string(SUBSTRING "${CMAKE_INSTALL_LIBDIR}" "${INSTALL_PREFIX_LEN}" "-1" LIBDIR_RELATIVE) + set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${LIBDIR_RELATIVE}") else() set(PC_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") endif() From 498ed7905a495c108f05cefaf739518dfed70acf Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 13 Apr 2023 19:18:03 +0500 Subject: [PATCH 637/798] Reverted description with Deprecation notice Signed-off-by: Vladislav Shchapov --- cmake/detect-install-dirs.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/detect-install-dirs.cmake b/cmake/detect-install-dirs.cmake index 2d31a59fb3..d2225f327d 100644 --- a/cmake/detect-install-dirs.cmake +++ b/cmake/detect-install-dirs.cmake @@ -4,6 +4,7 @@ # Determine installation directory for executables if (DEFINED BIN_INSTALL_DIR) + set(BIN_INSTALL_DIR "${BIN_INSTALL_DIR}" CACHE PATH "Installation directory for executables (Deprecated)" FORCE) set(CMAKE_INSTALL_BINDIR "${BIN_INSTALL_DIR}") elseif (DEFINED INSTALL_BIN_DIR) set(CMAKE_INSTALL_BINDIR "${INSTALL_BIN_DIR}") @@ -11,6 +12,7 @@ endif() # Determine installation directory for libraries if (DEFINED LIB_INSTALL_DIR) + set(LIB_INSTALL_DIR "${LIB_INSTALL_DIR}" CACHE PATH "Installation directory for libraries (Deprecated)" FORCE) set(CMAKE_INSTALL_LIBDIR "${LIB_INSTALL_DIR}") elseif (DEFINED INSTALL_LIB_DIR) set(CMAKE_INSTALL_LIBDIR "${INSTALL_LIB_DIR}") @@ -18,6 +20,7 @@ endif() # Determine installation directory for include files if (DEFINED INC_INSTALL_DIR) + set(INC_INSTALL_DIR "${INC_INSTALL_DIR}" CACHE PATH "Installation directory for headers (Deprecated)" FORCE) set(CMAKE_INSTALL_INCLUDEDIR "${INC_INSTALL_DIR}") elseif (DEFINED INSTALL_INC_DIR) set(CMAKE_INSTALL_INCLUDEDIR "${INSTALL_INC_DIR}") From 58c76217ecefcbeeccb32189ad27d162450a2e7b Mon Sep 17 00:00:00 2001 From: lawadr <3211473+lawadr@users.noreply.github.com> Date: Tue, 4 Apr 2023 14:53:35 +0100 Subject: [PATCH 638/798] Fix CMake check for posix_memalign and aligned_alloc These two functions were being checked using check_function_exists. This CMake macro does not check to see if the given function is declared in any header as it declares its own function prototype and relies on linking to determine function availability. This causes two issues. Firstly, it will always succeed when the CMake toolchain file sets CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY as no linking will take place. See: https://gitlab.kitware.com/cmake/cmake/-/issues/18121 Secondly, it will not correctly detect macros or inline functions, or whether the function is even declared in a header at all. Switch to check_symbol_exists at CMake's recommendation, the logic of which actually matches the same checks in the configure script. --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fba45535e..d5f66d6dc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,18 +331,21 @@ check_function_exists(fseeko HAVE_FSEEKO) if(NOT HAVE_FSEEKO) add_definitions(-DNO_FSEEKO) endif() + check_function_exists(strerror HAVE_STRERROR) if(NOT HAVE_STRERROR) add_definitions(-DNO_STRERROR) endif() + set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_C_SOURCE=200112L) -check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN) +check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) if(HAVE_POSIX_MEMALIGN) add_definitions(-DHAVE_POSIX_MEMALIGN) endif() set(CMAKE_REQUIRED_DEFINITIONS) + set(CMAKE_REQUIRED_DEFINITIONS -D_ISOC11_SOURCE=1) -check_function_exists(aligned_alloc HAVE_ALIGNED_ALLOC) +check_symbol_exists(aligned_alloc stdlib.h HAVE_ALIGNED_ALLOC) if(HAVE_ALIGNED_ALLOC) add_definitions(-DHAVE_ALIGNED_ALLOC) endif() From e24334f36971711753e886a5fe8f2f1c248a059d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20St=C3=BCrz?= Date: Sun, 9 Apr 2023 18:02:04 +0200 Subject: [PATCH 639/798] Fix compilation on OpenBSD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Non-POSIX functions (like vasprintf() and swap16()) require _BSD_SOURCE to be defined. Signed-off-by: Benjamin Stürz --- zbuild.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zbuild.h b/zbuild.h index 922b2cae2c..27f784a99f 100644 --- a/zbuild.h +++ b/zbuild.h @@ -8,6 +8,9 @@ #ifndef _ISOC11_SOURCE # define _ISOC11_SOURCE 1 /* aligned_alloc */ #endif +#ifdef __OpenBSD__ +# define _BSD_SOURCE 1 +#endif #include #include From 1ae7b0545dd49d32bf64f874c141e706c26cc8a6 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Sat, 15 Apr 2023 19:40:54 +0100 Subject: [PATCH 640/798] Rename chunkset_avx to chunkset_avx2 --- CMakeLists.txt | 4 ++-- arch/x86/Makefile.in | 10 +++++----- arch/x86/{chunkset_avx.c => chunkset_avx2.c} | 14 +++++++------- configure | 4 ++-- cpu_features.h | 6 +++--- functable.c | 6 +++--- win32/Makefile.msc | 4 ++-- 7 files changed, 24 insertions(+), 24 deletions(-) rename arch/x86/{chunkset_avx.c => chunkset_avx2.c} (93%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5f66d6dc8..6fc12f5bcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -762,8 +762,8 @@ if(WITH_OPTIM) add_definitions(-DX86_AVX2) set(AVX2_SRCS ${ARCHDIR}/slide_hash_avx2.c) add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx.c) - add_feature_info(AVX_CHUNKSET 1 "Support AVX optimized chunkset, using \"${AVX2FLAG}\"") + list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx2.c) + add_feature_info(AVX2_CHUNKSET 1 "Support AVX2 optimized chunkset, using \"${AVX2FLAG}\"") list(APPEND AVX2_SRCS ${ARCHDIR}/compare256_avx2.c) add_feature_info(AVX2_COMPARE256 1 "Support AVX2 optimized compare256, using \"${AVX2FLAG}\"") list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx2.c) diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 5fd51929ce..f0478bfdcc 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -30,7 +30,7 @@ all: \ adler32_avx512_vnni.o adler32_avx512_vnni.lo \ adler32_sse42.o adler32_sse42.lo \ adler32_ssse3.o adler32_ssse3.lo \ - chunkset_avx.o chunkset_avx.lo \ + chunkset_avx2.o chunkset_avx2.lo \ chunkset_sse2.o chunkset_sse2.lo \ chunkset_ssse3.o chunkset_ssse3.lo \ compare256_avx2.o compare256_avx2.lo \ @@ -47,11 +47,11 @@ x86_features.o: x86_features.lo: $(CC) $(SFLAGS) $(XSAVEFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c -chunkset_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c +chunkset_avx2.o: + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx2.c -chunkset_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c +chunkset_avx2.lo: + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx2.c chunkset_sse2.o: $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse2.c diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx2.c similarity index 93% rename from arch/x86/chunkset_avx.c rename to arch/x86/chunkset_avx2.c index abcbb474f5..f309878b35 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx2.c @@ -1,4 +1,4 @@ -/* chunkset_avx.c -- AVX inline functions to copy small data chunks. +/* chunkset_avx2.c -- AVX2 inline functions to copy small data chunks. * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zbuild.h" @@ -120,15 +120,15 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t return ret_vec; } -#define CHUNKSIZE chunksize_avx -#define CHUNKCOPY chunkcopy_avx -#define CHUNKUNROLL chunkunroll_avx -#define CHUNKMEMSET chunkmemset_avx -#define CHUNKMEMSET_SAFE chunkmemset_safe_avx +#define CHUNKSIZE chunksize_avx2 +#define CHUNKCOPY chunkcopy_avx2 +#define CHUNKUNROLL chunkunroll_avx2 +#define CHUNKMEMSET chunkmemset_avx2 +#define CHUNKMEMSET_SAFE chunkmemset_safe_avx2 #include "chunkset_tpl.h" -#define INFLATE_FAST inflate_fast_avx +#define INFLATE_FAST inflate_fast_avx2 #include "inffast_tpl.h" diff --git a/configure b/configure index 2867302b37..1f3ef7a029 100755 --- a/configure +++ b/configure @@ -1546,8 +1546,8 @@ case "${ARCH}" in if test ${HAVE_AVX2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_AVX2" SFLAGS="${SFLAGS} -DX86_AVX2" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_hash_avx2.o chunkset_avx.o compare256_avx2.o adler32_avx2.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx2.lo chunkset_avx.lo compare256_avx2.lo adler32_avx2.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_hash_avx2.o chunkset_avx2.o compare256_avx2.o adler32_avx2.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx2.lo chunkset_avx2.lo compare256_avx2.lo adler32_avx2.lo" fi check_avx512_intrinsics diff --git a/cpu_features.h b/cpu_features.h index c742f32c66..b8ec883a22 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -103,8 +103,8 @@ extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, extern uint8_t* chunkmemset_safe_ssse3(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif #ifdef X86_AVX2 -extern uint32_t chunksize_avx(void); -extern uint8_t* chunkmemset_safe_avx(uint8_t *out, unsigned dist, unsigned len, unsigned left); +extern uint32_t chunksize_avx2(void); +extern uint8_t* chunkmemset_safe_avx2(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif #ifdef ARM_NEON extern uint32_t chunksize_neon(void); @@ -130,7 +130,7 @@ extern void inflate_fast_sse2(PREFIX3(stream) *strm, uint32_t start); extern void inflate_fast_ssse3(PREFIX3(stream) *strm, uint32_t start); #endif #ifdef X86_AVX2 -extern void inflate_fast_avx(PREFIX3(stream) *strm, uint32_t start); +extern void inflate_fast_avx2(PREFIX3(stream) *strm, uint32_t start); #endif #ifdef ARM_NEON extern void inflate_fast_neon(PREFIX3(stream) *strm, uint32_t start); diff --git a/functable.c b/functable.c index f9e8163d3a..aa018c0d64 100644 --- a/functable.c +++ b/functable.c @@ -107,9 +107,9 @@ static void init_functable(void) { if (cf.x86.has_avx2) { ft.adler32 = &adler32_avx2; ft.adler32_fold_copy = &adler32_fold_copy_avx2; - ft.chunkmemset_safe = &chunkmemset_safe_avx; - ft.chunksize = &chunksize_avx; - ft.inflate_fast = &inflate_fast_avx; + ft.chunkmemset_safe = &chunkmemset_safe_avx2; + ft.chunksize = &chunksize_avx2; + ft.inflate_fast = &inflate_fast_avx2; ft.slide_hash = &slide_hash_avx2; # ifdef HAVE_BUILTIN_CTZ ft.compare256 = &compare256_avx2; diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 8a01e31710..9ed26f2834 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -54,7 +54,7 @@ OBJS = \ adler32_ssse3.obj \ adler32_fold.obj \ chunkset.obj \ - chunkset_avx.obj \ + chunkset_avx2.obj \ chunkset_sse2.obj \ chunkset_ssse3.obj \ compare256.obj \ @@ -201,7 +201,7 @@ gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR) compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -chunkset_avx.obj: $(SRCDIR)/arch/x86/chunkset_avx.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h +chunkset_avx2.obj: $(SRCDIR)/arch/x86/chunkset_avx2.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_sse2.obj: $(SRCDIR)/arch/x86/chunkset_sse2.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_ssse3.obj: $(SRCDIR)/arch/x86/chunkset_ssse3.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h From fc49c98d1f47b4f041e0cc2668fa7b66c13a6377 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 19 Apr 2023 16:03:18 +0200 Subject: [PATCH 641/798] IBM zSystems: Fix calling deflateBound() before deflateInit() Even though zlib officialy forbids calling deflateBound() before deflateInit(), Firefox does this anyway, and it happens to work [1], but unfortunately not with DFLTCC [2], because the DFLTCC code assumes that the deflate state is allocated, and segfaults when it isn't. Bow down before Hyrum's Law and add deflateStateCheck() to DEFLATE_BOUND_ADJUST_COMPLEN(). Extend the deflate_bound test accordingly. [1] https://searchfox.org/mozilla-esr102/source/dom/script/ScriptCompression.cpp#97 [2] https://bugzilla.suse.com/show_bug.cgi?id=1210593 --- arch/s390/dfltcc_deflate.h | 2 +- test/test_deflate_bound.cc | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/s390/dfltcc_deflate.h b/arch/s390/dfltcc_deflate.h index d12523017d..cb261b156c 100644 --- a/arch/s390/dfltcc_deflate.h +++ b/arch/s390/dfltcc_deflate.h @@ -45,7 +45,7 @@ int Z_INTERNAL PREFIX(dfltcc_deflate_get_dictionary)(PREFIX3(streamp) strm, unsi #define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \ do { \ - if (PREFIX(dfltcc_can_deflate)((strm))) \ + if (deflateStateCheck((strm)) || PREFIX(dfltcc_can_deflate)((strm))) \ (complen) = DEFLATE_BOUND_COMPLEN(source_len); \ } while (0) diff --git a/test/test_deflate_bound.cc b/test/test_deflate_bound.cc index 8de65535f2..33bc452ebd 100644 --- a/test/test_deflate_bound.cc +++ b/test/test_deflate_bound.cc @@ -22,12 +22,15 @@ typedef struct { int32_t level; int32_t window_size; int32_t mem_level; + bool after_init; } deflate_bound_test; static const deflate_bound_test tests[] = { - {0, MAX_WBITS + 16, 1}, - {Z_BEST_SPEED, MAX_WBITS, MAX_MEM_LEVEL}, - {Z_BEST_COMPRESSION, MAX_WBITS, MAX_MEM_LEVEL} + {0, MAX_WBITS + 16, 1, true}, + {Z_BEST_SPEED, MAX_WBITS, MAX_MEM_LEVEL, true}, + {Z_BEST_COMPRESSION, MAX_WBITS, MAX_MEM_LEVEL, true}, + {Z_BEST_SPEED, MAX_WBITS, MAX_MEM_LEVEL, false}, + {Z_BEST_COMPRESSION, MAX_WBITS, MAX_MEM_LEVEL, false}, }; class deflate_bound_variant : public testing::TestWithParam { @@ -51,12 +54,16 @@ class deflate_bound_variant : public testing::TestWithParam c_stream.avail_out = 0; c_stream.next_out = out_buf; + if (!param.after_init) + estimate_len = PREFIX(deflateBound)(&c_stream, i); + err = PREFIX(deflateInit2)(&c_stream, param.level, Z_DEFLATED, param.window_size, param.mem_level, Z_DEFAULT_STRATEGY); EXPECT_EQ(err, Z_OK); /* calculate actual output length and update structure */ - estimate_len = PREFIX(deflateBound)(&c_stream, i); + if (param.after_init) + estimate_len = PREFIX(deflateBound)(&c_stream, i); out_buf = (uint8_t *)malloc(estimate_len); if (out_buf != NULL) { @@ -70,6 +77,7 @@ class deflate_bound_variant : public testing::TestWithParam "level: " << param.level << "\n" << "window_size: " << param.window_size << "\n" << "mem_level: " << param.mem_level << "\n" << + "after_init: " << param.after_init << "\n" << "length: " << i; free(out_buf); From 38aa5751297709fa31b1a5b7e022384b57e1724d Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Sat, 15 Apr 2023 19:08:05 +0100 Subject: [PATCH 642/798] Ensure that unaligned compare256 variants are only used on little endian systems --- compare256.c | 2 +- cpu_features.h | 6 +++--- functable.c | 2 +- test/benchmarks/benchmark_compare256.cc | 2 +- test/test_compare256.cc | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compare256.c b/compare256.c index 94b88e756f..82551cdd57 100644 --- a/compare256.c +++ b/compare256.c @@ -56,7 +56,7 @@ Z_INTERNAL uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1) { #include "match_tpl.h" -#ifdef UNALIGNED_OK +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN /* 16-bit unaligned integer comparison */ static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; diff --git a/cpu_features.h b/cpu_features.h index b8ec883a22..2e1a888e38 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -155,7 +155,7 @@ extern uint32_t crc32_s390_vx(uint32_t crc, const uint8_t *buf, size_t len); typedef uint32_t (*compare256_func)(const uint8_t *src0, const uint8_t *src1); extern uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1); -#ifdef UNALIGNED_OK +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN extern uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1); #ifdef HAVE_BUILTIN_CTZ extern uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1); @@ -188,7 +188,7 @@ extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint3 /* longest_match */ extern uint32_t longest_match_c(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED_OK +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN extern uint32_t longest_match_unaligned_16(deflate_state *const s, Pos cur_match); #ifdef HAVE_BUILTIN_CTZ extern uint32_t longest_match_unaligned_32(deflate_state *const s, Pos cur_match); @@ -212,7 +212,7 @@ extern uint32_t longest_match_power9(deflate_state *const s, Pos cur_match); /* longest_match_slow */ extern uint32_t longest_match_slow_c(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED_OK +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN extern uint32_t longest_match_slow_unaligned_16(deflate_state *const s, Pos cur_match); extern uint32_t longest_match_slow_unaligned_32(deflate_state *const s, Pos cur_match); #ifdef UNALIGNED64_OK diff --git a/functable.c b/functable.c index aa018c0d64..d200982922 100644 --- a/functable.c +++ b/functable.c @@ -33,7 +33,7 @@ static void init_functable(void) { ft.slide_hash = &slide_hash_c; ft.update_hash = &update_hash_c; -#ifdef UNALIGNED_OK +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) ft.longest_match = &longest_match_unaligned_64; ft.longest_match_slow = &longest_match_slow_unaligned_64; diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 00c6cc6f63..3ab04d2022 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -61,7 +61,7 @@ class compare256: public benchmark::Fixture { BENCHMARK_COMPARE256(c, compare256_c, 1); -#ifdef UNALIGNED_OK +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN BENCHMARK_COMPARE256(unaligned_16, compare256_unaligned_16, 1); #ifdef HAVE_BUILTIN_CTZ BENCHMARK_COMPARE256(unaligned_32, compare256_unaligned_32, 1); diff --git a/test/test_compare256.cc b/test/test_compare256.cc index f920d1d205..0e656da371 100644 --- a/test/test_compare256.cc +++ b/test/test_compare256.cc @@ -60,7 +60,7 @@ static inline void compare256_match_check(compare256_func compare256) { TEST_COMPARE256(c, compare256_c, 1) -#ifdef UNALIGNED_OK +#if defined(UNALIGNED_OK) && BYTE_ORDER == LITTLE_ENDIAN TEST_COMPARE256(unaligned_16, compare256_unaligned_16, 1) #ifdef HAVE_BUILTIN_CTZ TEST_COMPARE256(unaligned_32, compare256_unaligned_32, 1) From 3f06cece6be2e1bfe7b60d17e5ef823535ec9d0c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 24 Apr 2023 09:04:24 -0700 Subject: [PATCH 643/798] Use ZLIB_INCLUDE_DIRS from FindZLIB instead of ZLIB_INCLUDE_DIR. ZLIB_INCLUDE_DIRS is set by FindZLIB if ZLIB_INCLUDE_DIR is set on the command line. --- test/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 007509a215..d434ec3083 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -210,7 +210,7 @@ if(WITH_GTEST) -fsanitize-memory-track-origins) endif() - if(NOT ZLIB_COMPAT AND DEFINED ZLIB_LIBRARIES AND DEFINED ZLIB_INCLUDE_DIR) + if(NOT ZLIB_COMPAT AND DEFINED ZLIB_LIBRARIES AND DEFINED ZLIB_INCLUDE_DIRS) if(NOT IS_ABSOLUTE ${ZLIB_LIBRARIES}) get_filename_component(ZLIB_ABSOLUTE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${ZLIB_LIBRARIES}" @@ -222,11 +222,11 @@ if(WITH_GTEST) add_library(external_zlib STATIC IMPORTED) set_property(TARGET external_zlib PROPERTY IMPORTED_LOCATION ${ZLIB_ABSOLUTE_PATH}) message(STATUS "Added dual linking tests against zlib") - message(STATUS " Zlib include dir: ${ZLIB_INCLUDE_DIR}") + message(STATUS " Zlib include dirs: ${ZLIB_INCLUDE_DIRS}") message(STATUS " Zlib libraries: ${ZLIB_ABSOLUTE_PATH}") target_sources(gtest_zlib PRIVATE test_compress_dual.cc) - target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIR}) + target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIRS}) target_link_libraries(gtest_zlib external_zlib) endif() From 045a278d86ffaeb455682618e2bc208059b72f5d Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Fri, 17 Feb 2023 00:06:32 -0800 Subject: [PATCH 644/798] Assure that inflatePrime() can't shift a 32-bit integer by 32 bits. The inflate() functions never leave state->bits greater than 24, so an inflatePrime() call could not cause this. The only way this could have happened would be by using inflatePrime() to fill the bit buffer with 32 bits, and then calling inflatePrime() a *second* time asking to insert zero bits, for some reason. This commit assures that a shift by 32 bits does not occur even in that case. --- inflate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/inflate.c b/inflate.c index df4c56a168..0cbed041d7 100644 --- a/inflate.c +++ b/inflate.c @@ -190,6 +190,8 @@ int32_t Z_EXPORT PREFIX(inflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32 if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + if (bits == 0) + return Z_OK; INFLATE_PRIME_HOOK(strm, bits, value); /* hook for IBM Z DFLTCC */ state = (struct inflate_state *)strm->state; if (bits < 0) { From 4b4377a3623e9fbe08a24fe20233dc3cdefba9ea Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 26 Apr 2023 02:18:24 +0300 Subject: [PATCH 645/798] Fix use after free in test_deflate_bound. --- test/test_deflate_bound.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_deflate_bound.cc b/test/test_deflate_bound.cc index 33bc452ebd..c86d4e00b0 100644 --- a/test/test_deflate_bound.cc +++ b/test/test_deflate_bound.cc @@ -81,6 +81,7 @@ class deflate_bound_variant : public testing::TestWithParam "length: " << i; free(out_buf); + out_buf = NULL; } err = PREFIX(deflateEnd)(&c_stream); From 2d5d0a2bafb4314b4310577824b5a949058db404 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 26 Apr 2023 19:28:43 +0300 Subject: [PATCH 646/798] Fix potential overflow before widening in makecrtc. --- tools/makecrct.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/makecrct.c b/tools/makecrct.c index b5469b7d39..5c3ba58a1a 100644 --- a/tools/makecrct.c +++ b/tools/makecrct.c @@ -93,7 +93,7 @@ static void braid(uint32_t ltl[][256], z_word_t big[][256], int n, int w) { int k; uint32_t i, p, q; for (k = 0; k < w; k++) { - p = x2nmodp((n * w + 3 - k) << 3, 0); + p = x2nmodp(((z_off64_t)n * w + 3 - k) << 3, 0); ltl[k][0] = 0; big[w - 1 - k][0] = 0; for (i = 1; i < 256; i++) { From 1c2698f9be19a8d837a83d2a08e938f22c3f3202 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 25 Apr 2023 12:37:32 +0200 Subject: [PATCH 647/798] 2.1.0 Beta1 release This release contains two years of development and improvements to zlib-ng, as well as fixes and changes inherited from zlib. The 2.1.x version series has new targeted minumum buildsystem versions, as detailed on the Wiki https://github.com/zlib-ng/zlib-ng/wiki Buildsystem: - Many improvements to the CMake scripts. - Improved support for detecting memory alignment functions. - Improved support for unaligned access by letting the compiler promote code to unaligned if supported by the CPU. - Remove x86 cpu feature detection for TZCNT, safely fallback to BSF. - Enable using AVX512 intrinsics with GCC <9. Optimizations and Enhancements: - Decompression is a lot faster (56% faster measured on AVX2-capable x86-64) - Compresson is improved for Level 9, at the cost of a little performance. - Compression is improved for Level 3, by switching from deflate_fast to deflate_medium. - Levels 3 and 4 have been reconfigured to provide a better gradual tradeoff for speed/compression between levels 2 and 5. - Deflate_quick (Level 1) has been improved to default to a bigger windowsize and support changing the window size like the other levels. New instruction set optimizations: - Adler32 implementation using AVX512, AVX512-VNNI, VMX. - CRC32-B implementation using VPCLMULQDQ & IBM-Z. - Slide hash implementation using VMX. - Compare256 implementations using SSE2, Neon, & POWER9. - Inflate chunk copying using SSSE3 & VSX. Compatibility and Porting: - CRC-32 computation changes from madler/zlib. zlib-ng/zlib-ng#a6155234 - Compatible and up-to-date with zlib 1.2.13. - Removed the usage of macros in zlib-ng.h, making life easier for languages that want to call the C functions without having the C preprocessor (Python, etc). Improved support more environments: - Apple M1 - vcpkg - Emscripten Testing: - Tests have been converted to use GTest. Many new tests have also been added. - Gbench support has been added to easily benchmark changes to performance-critical functions. Misc: - Several pieces of core code has been restructured or rewritten. - Too many changes to list here, see the git commit log for the full list of changes. Deprecations: - Configure no longer has the full range of tests. - NMake is no longer actively supported and tested, it is now community supported. - See the wiki for minimum build system versions and deprecations https://github.com/zlib-ng/zlib-ng/wiki --- Makefile.in | 2 +- zlib-ng.h.in | 4 ++-- zlib.h.in | 6 +++--- zutil.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile.in b/Makefile.in index 4bfb6313e2..8ca8c81da7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.1.0.devel +VER=2.1.0.beta1 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h.in b/zlib-ng.h.in index a1536b76d2..7f68f7a337 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -48,8 +48,8 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.0.devel" -#define ZLIBNG_VERNUM 0x02010000L /* MMNNRRMS: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.0.beta1" +#define ZLIBNG_VERNUM 0x02010010L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 #define ZLIBNG_VER_REVISION 0 diff --git a/zlib.h.in b/zlib.h.in index 311cd34e8c..6da533c402 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -49,12 +49,12 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.0.devel" -#define ZLIBNG_VERNUM 0x02010000L /* MMNNRRMS: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.0.beta1" +#define ZLIBNG_VERNUM 0x02010010L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 #define ZLIBNG_VER_REVISION 0 -#define ZLIBNG_VER_STATUS 0 /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_STATUS 1 /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ #define ZLIB_VERSION "1.2.13.zlib-ng" diff --git a/zutil.c b/zutil.c index 742c33ac3d..0fd14f4ef3 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char PREFIX3(vstring)[] = - " zlib-ng 2.1.0.devel forked from zlib"; + " zlib-ng 2.1.0.beta1"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From 5ff01803c525e84ec7ca6ebd29c1c0689e4544a6 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Tue, 2 May 2023 10:12:15 +0200 Subject: [PATCH 648/798] Remove CMAKE_MACOSX_RPATH This is ON by default since CMake 3.0 --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6fc12f5bcf..cdb38311dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,6 @@ else() endif() message(STATUS "Using CMake version ${CMAKE_VERSION}") -set(CMAKE_MACOSX_RPATH 1) - # If not specified on the command line, enable C11 as the default # Configuration items that affect the global compiler environment standards # should be issued before the "project" command. From bf985ade30906b63bdc9c382a78b435498f743e3 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Tue, 2 May 2023 10:36:16 +0200 Subject: [PATCH 649/798] Include GNUInstallDirs earlier for pkg config dir --- cmake/detect-install-dirs.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/detect-install-dirs.cmake b/cmake/detect-install-dirs.cmake index d2225f327d..a7c774f474 100644 --- a/cmake/detect-install-dirs.cmake +++ b/cmake/detect-install-dirs.cmake @@ -26,6 +26,9 @@ elseif (DEFINED INSTALL_INC_DIR) set(CMAKE_INSTALL_INCLUDEDIR "${INSTALL_INC_DIR}") endif() +# Define GNU standard installation directories +include(GNUInstallDirs) + # Determine installation directory for pkgconfig files if (DEFINED PKGCONFIG_INSTALL_DIR) set(PKGCONFIG_INSTALL_DIR "${PKGCONFIG_INSTALL_DIR}" CACHE PATH "Installation directory for pkgconfig (.pc) files" FORCE) @@ -38,6 +41,3 @@ elseif (DEFINED CMAKE_INSTALL_FULL_PKGCONFIGDIR) else() set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") endif() - -# Define GNU standard installation directories -include(GNUInstallDirs) From f346148df0123a56b47af0ebc63e7529ae50cb44 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 26 Apr 2023 02:19:50 +0300 Subject: [PATCH 650/798] Fix out-of-bound access of zng_length_codes. --- deflate_quick.c | 2 ++ deflate_rle.c | 1 + 2 files changed, 3 insertions(+) diff --git a/deflate_quick.c b/deflate_quick.c index d616677c5f..df5a17b9e6 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -99,6 +99,8 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { if (match_len >= WANT_MIN_MATCH) { if (UNLIKELY(match_len > s->lookahead)) match_len = s->lookahead; + if (UNLIKELY(match_len > STD_MAX_MATCH)) + match_len = STD_MAX_MATCH; check_match(s, s->strstart, hash_head, match_len); diff --git a/deflate_rle.c b/deflate_rle.c index 77df71f585..4e3fde09f0 100644 --- a/deflate_rle.c +++ b/deflate_rle.c @@ -47,6 +47,7 @@ Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { scan < strend); match_len = STD_MAX_MATCH - (unsigned int)(strend - scan); match_len = MIN(match_len, s->lookahead); + match_len = MIN(match_len, STD_MAX_MATCH); } Assert(scan <= s->window + s->window_size - 1, "wild scan"); } From 9087c75f8d9a35c7d7801440c23deb555e77714e Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sat, 29 Apr 2023 11:33:05 -0400 Subject: [PATCH 651/798] Use ternary logic to xor 3 operands for "fold16" This strategy is borrowed from ISA-L in this commit: https://github.com/intel/isa-l/commit/c2bec3ea65ce35b01311d1cc4b314f6b4986b9c8 We can also use it in the "fold final" routine but we'd have to take some extra care to only use it on AVX512 capable systems. --- arch/x86/crc32_fold_vpclmulqdq_tpl.h | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/arch/x86/crc32_fold_vpclmulqdq_tpl.h b/arch/x86/crc32_fold_vpclmulqdq_tpl.h index 67f08e1281..3ea5c33055 100644 --- a/arch/x86/crc32_fold_vpclmulqdq_tpl.h +++ b/arch/x86/crc32_fold_vpclmulqdq_tpl.h @@ -40,8 +40,7 @@ static size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc3, 3); z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_t0, 0x96); #ifdef COPY _mm512_storeu_si512((__m512i *)dst, zmm_t0); @@ -70,15 +69,10 @@ static size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, zmm_crc2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x10); zmm_crc3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc1 = _mm512_xor_si512(z1, zmm_crc1); - zmm_crc2 = _mm512_xor_si512(z2, zmm_crc2); - zmm_crc3 = _mm512_xor_si512(z3, zmm_crc3); - - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); - zmm_crc1 = _mm512_xor_si512(zmm_crc1, zmm_t1); - zmm_crc2 = _mm512_xor_si512(zmm_crc2, zmm_t2); - zmm_crc3 = _mm512_xor_si512(zmm_crc3, zmm_t3); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_t0, 0x96); + zmm_crc1 = _mm512_ternarylogic_epi32(zmm_crc1, z1, zmm_t1, 0x96); + zmm_crc2 = _mm512_ternarylogic_epi32(zmm_crc2, z2, zmm_t2, 0x96); + zmm_crc3 = _mm512_ternarylogic_epi32(zmm_crc3, z3, zmm_t3, 0x96); #ifdef COPY _mm512_storeu_si512((__m512i *)dst, zmm_t0); @@ -93,18 +87,15 @@ static size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, // zmm_crc[0,1,2,3] -> zmm_crc0 z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc1); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_crc1, 0x96); z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc2); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_crc2, 0x96); z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); - zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); - zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc3); + zmm_crc0 = _mm512_ternarylogic_epi32(zmm_crc0, z0, zmm_crc3, 0x96); // zmm_crc0 -> xmm_crc[0, 1, 2, 3] *xmm_crc0 = _mm512_extracti32x4_epi32(zmm_crc0, 0); From c3cdf434f32e3f158b8caedd45113384bf4aed14 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 27 Apr 2023 01:40:15 -0700 Subject: [PATCH 652/798] Add supporting RISC-V cross compilation workflows Add RISC-V cross-compilation test Enable RVV support at compile time --- .github/workflows/cmake.yml | 14 +++++++++++ CMakeLists.txt | 19 +++++++++++++++ README.md | 3 ++- arch/riscv/README.md | 45 +++++++++++++++++++++++++++++++++++ arch/riscv/riscv_features.c | 15 ++++++++++++ arch/riscv/riscv_features.h | 18 ++++++++++++++ cmake/detect-intrinsics.cmake | 18 ++++++++++++++ cmake/toolchain-riscv.cmake | 28 ++++++++++++++++++++++ cpu_features.c | 2 ++ cpu_features.h | 4 ++++ 10 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 arch/riscv/README.md create mode 100644 arch/riscv/riscv_features.c create mode 100644 arch/riscv/riscv_features.h create mode 100644 cmake/toolchain-riscv.cmake diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index d50a2dcfab..bbed1db0ca 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -378,6 +378,12 @@ jobs: # https://github.com/llvm/llvm-project/issues/55785 msan-options: use_sigaltstack=0 + - name: Ubuntu Clang RISC-V + os: ubuntu-latest + cmake-args: -GNinja -DCMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake -DTOOLCHAIN_PATH=${PWD}/prebuilt-riscv-toolchain-qemu/riscv-clang -DQEMU_PATH=${PWD}/prebuilt-riscv-toolchain-qemu/riscv-qemu/bin/qemu-riscv64 + packages: build-essential cmake ninja-build + codecov: ubuntu_clang_toolchain_riscv + - name: Ubuntu Emscripten WASM32 os: ubuntu-latest chost: wasm32 @@ -502,6 +508,14 @@ jobs: sudo apt-get update sudo apt-get install -y --allow-downgrades --no-install-recommends ${{ matrix.packages }} + - name: Download prebuilt RISC-V Clang toolchain & QEMU emulator + if: runner.os == 'Linux' && contains(matrix.name, 'RISC-V') + run: | + gh release download ubuntu20.04_llvm16.0.0_qemu7.0.0 --repo sifive/prepare-riscv-toolchain-qemu + tar zxvf prebuilt-riscv-toolchain-qemu.tar.gz + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Install packages (Windows) if: runner.os == 'Windows' run: | diff --git a/CMakeLists.txt b/CMakeLists.txt index cdb38311dd..a6199d35ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,8 @@ elseif(BASEARCH_PPC_FOUND) option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON) option(WITH_POWER8 "Build with optimisations for POWER8" ON) option(WITH_POWER9 "Build with optimisations for POWER9" ON) +elseif(BASEARCH_RISCV_FOUND) + option(WITH_RVV "Build with RVV intrinsics" ON) elseif(BASEARCH_S360_FOUND) option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF) option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF) @@ -135,6 +137,7 @@ mark_as_advanced(FORCE WITH_ALTIVEC WITH_POWER8 WITH_POWER9 + WITH_RVV WITH_INFLATE_STRICT WITH_INFLATE_ALLOW_INVALID_DIST WITH_UNALIGNED @@ -544,6 +547,8 @@ if(BASEARCH_ARM_FOUND) set(ARCHDIR "arch/arm") elseif(BASEARCH_PPC_FOUND) set(ARCHDIR "arch/power") +elseif(BASEARCH_RISCV_FOUND) + set(ARCHDIR "arch/riscv") elseif(BASEARCH_S360_FOUND) set(ARCHDIR "arch/s390") elseif(BASEARCH_X86_FOUND) @@ -718,6 +723,18 @@ if(WITH_OPTIM) set(WITH_POWER9 OFF) endif() endif() + elseif(BASEARCH_RISCV_FOUND) + if(WITH_RVV) + check_rvv_intrinsics() + if(HAVE_RVV_INTRIN) + add_definitions(-DRISCV_FEATURES) + add_definitions(-DRISCV_RVV) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/riscv_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c) + else() + set(WITH_RVV OFF) + endif() + endif() elseif(BASEARCH_S360_FOUND) check_s390_intrinsics() if(HAVE_S390_INTRIN) @@ -1228,6 +1245,8 @@ elseif(BASEARCH_PPC_FOUND) add_feature_info(WITH_ALTIVEC WITH_ALTIVEC "Build with AltiVec optimisations") add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8") add_feature_info(WITH_POWER9 WITH_POWER9 "Build with optimisations for POWER9") +elseif(BASEARCH_RISCV_FOUND) + add_feature_info(WITH_RVV WITH_RVV "Build with RVV intrinsics") elseif(BASEARCH_S360_FOUND) add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z") add_feature_info(WITH_DFLTCC_INFLATE WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z") diff --git a/README.md b/README.md index aa72365c95..367dc9463b 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Features * Comprehensive set of CMake unit tests * Code sanitizers, fuzzing, and coverage * GitHub Actions continuous integration on Windows, macOS, and Linux - * Emulated CI for ARM, AARCH64, PPC, PPC64, SPARC64, S390x using qemu + * Emulated CI for ARM, AARCH64, PPC, PPC64, RISCV, SPARC64, S390x using qemu History @@ -221,6 +221,7 @@ Advanced Build Options | WITH_NEON | --without-neon | Build with NEON intrinsics | ON | | WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | ON | | WITH_POWER8 | --without-power8 | Build with POWER8 optimisations | ON | +| WITH_RVV | | Build with RVV intrinsics | ON | | WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON | | WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF | | WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF | diff --git a/arch/riscv/README.md b/arch/riscv/README.md new file mode 100644 index 0000000000..b4309e1a0a --- /dev/null +++ b/arch/riscv/README.md @@ -0,0 +1,45 @@ +# Building RISC-V Target with Cmake # + +> **Warning** +> We cannot detect rvv support at runtime, running the rvv code on a no-rvv target is a risk. Users should disable the rvv when the target does not support it. +> +> We will have a better solution when the kernels update `hwcap` or `hwprobe` for risc-v. + +## Prerequisite: Build RISC-V Clang Toolchain and QEMU ## + +If you don't have prebuilt clang and riscv64 qemu, you can refer to the [script](https://github.com/sifive/prepare-riscv-toolchain-qemu/blob/main/prepare_riscv_toolchain_qemu.sh) to get the source. Copy the script to the zlib-ng root directory, and run it to download the source and build them. Modify the content according to your conditions (e.g., toolchain version). + +```bash +./prepare_riscv_toolchain_qemu.sh +``` + +After running script, clang & qemu are built in `build-toolchain-qemu/riscv-clang/` & `build-toolchain-qemu/riscv-qemu/`. + +`build-toolchain-qemu/riscv-clang/` is your `TOOLCHAIN_PATH`. +`build-toolchain-qemu/riscv-qemu/bin/qemu-riscv64` is your `QEMU_PATH`. + +You can also download the prebuilt toolchain & qemu from [the release page](https://github.com/sifive/prepare-riscv-toolchain-qemu/releases), and enjoy using them. + +## Cross-Compile for RISC-V Target ## + +```bash +cmake -G Ninja -B ./build-riscv \ + -D CMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake \ + -D CMAKE_INSTALL_PREFIX=./build-riscv/install \ + -D TOOLCHAIN_PATH={TOOLCHAIN_PATH} \ + -D QEMU_PATH={QEMU_PATH} \ + . + +cmake --build ./build-riscv +``` + +Disable the option if there is no RVV support: +``` +-D WITH_RVV=OFF +``` + +## Run Unittests on User Mode QEMU ## + +```bash +cd ./build-riscv && ctest --verbose +``` diff --git a/arch/riscv/riscv_features.c b/arch/riscv/riscv_features.c new file mode 100644 index 0000000000..362d714835 --- /dev/null +++ b/arch/riscv/riscv_features.c @@ -0,0 +1,15 @@ +#include +#include +#include + +#include "../../zbuild.h" +#include "riscv_features.h" + +/* TODO: detect risc-v cpu info at runtime when the kernel updates hwcap or hwprobe for risc-v */ +void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) { +#if defined(__riscv_v) && defined(__linux__) + features->has_rvv = 1; +#else + features->has_rvv = 0; +#endif +} diff --git a/arch/riscv/riscv_features.h b/arch/riscv/riscv_features.h new file mode 100644 index 0000000000..f933fc9acb --- /dev/null +++ b/arch/riscv/riscv_features.h @@ -0,0 +1,18 @@ +/* riscv_features.h -- check for riscv features. + * + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef RISCV_H_ +#define RISCV_H_ + +struct riscv_cpu_features { + int has_rvv; +}; + +void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features); + +#endif /* RISCV_H_ */ diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 0491d53bf8..c20c9e1607 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -347,6 +347,24 @@ macro(check_power8_intrinsics) set(CMAKE_REQUIRED_FLAGS) endmacro() +macro(check_rvv_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(RISCVFLAG "-march=rv64gcv") + endif() + endif() + # Check whether compiler supports RVV + set(CMAKE_REQUIRED_FLAGS "${RISCVFLAG} ${NATIVEFLAG}") + check_c_source_compiles( + "#include + int main() { + return 0; + }" + HAVE_RVV_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + macro(check_s390_intrinsics) check_c_source_compiles( "#include diff --git a/cmake/toolchain-riscv.cmake b/cmake/toolchain-riscv.cmake new file mode 100644 index 0000000000..9cf8fdb7fe --- /dev/null +++ b/cmake/toolchain-riscv.cmake @@ -0,0 +1,28 @@ +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_PROCESSOR "riscv64") + +# Avoid to use system path for cross-compile +set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH FALSE) + +set(TOOLCHAIN_PATH "" CACHE STRING "The toolchain path.") +if(NOT TOOLCHAIN_PATH) + set(TOOLCHAIN_PATH ${CMAKE_SOURCE_DIR}/prebuilt-riscv-toolchain-qemu/riscv-clang) +endif() + +set(TOOLCHAIN_PREFIX "riscv64-unknown-linux-gnu-" CACHE STRING "The toolchain prefix.") +set(QEMU_PATH "" CACHE STRING "The qemu path.") +if(NOT QEMU_PATH) + set(QEMU_PATH ${CMAKE_SOURCE_DIR}/prebuilt-riscv-toolchain-qemu/riscv-qemu/bin/qemu-riscv64) +endif() + +# toolchain setting +set(CMAKE_C_COMPILER "${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX}clang") +set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX}clang++") + +# disable auto-vectorizer +add_compile_options(-fno-vectorize -fno-slp-vectorize) + +# emulator setting +set(QEMU_CPU_OPTION "rv64,zba=true,zbb=true,zbc=true,zbs=true,v=true,vlen=512,elen=64,vext_spec=v1.0") +set(CMAKE_CROSSCOMPILING_EMULATOR ${QEMU_PATH} -cpu ${QEMU_CPU_OPTION} -L ${TOOLCHAIN_PATH}/sysroot/) diff --git a/cpu_features.c b/cpu_features.c index b69a01304a..3585172e5d 100644 --- a/cpu_features.c +++ b/cpu_features.c @@ -17,5 +17,7 @@ Z_INTERNAL void cpu_check_features(struct cpu_features *features) { power_check_features(&features->power); #elif defined(S390_FEATURES) s390_check_features(&features->s390); +#elif defined(RISCV_FEATURES) + riscv_check_features(&features->riscv); #endif } diff --git a/cpu_features.h b/cpu_features.h index 2e1a888e38..647d027f6e 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -18,6 +18,8 @@ # include "arch/power/power_features.h" #elif defined(S390_FEATURES) # include "arch/s390/s390_features.h" +#elif defined(RISCV_FEATURES) +# include "arch/riscv/riscv_features.h" #endif struct cpu_features { @@ -29,6 +31,8 @@ struct cpu_features { struct power_cpu_features power; #elif defined(S390_FEATURES) struct s390_cpu_features s390; +#elif defined(RISCV_FEATURES) + struct riscv_cpu_features riscv; #else char empty; #endif From fadf7c1e9ce5f711f83cdeecbc381551ecfa8a62 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 12 May 2023 22:27:53 +0200 Subject: [PATCH 653/798] Fix abicheck no longer ignoring version string after previous variable rename. --- test/abi/ignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/abi/ignore b/test/abi/ignore index dba3639cb9..583c92184c 100644 --- a/test/abi/ignore +++ b/test/abi/ignore @@ -8,5 +8,5 @@ # Size varies with version number [suppress_variable] - name = zlibng_string + name_regexp = z(|ng|libng)_(|v)string From f2da9052877686dd725e1bd0ab0432ccd3687089 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 13 May 2023 13:17:04 +0200 Subject: [PATCH 654/798] Fix AVX512-VNNI compile flags. --- cmake/detect-intrinsics.cmake | 8 +++++++- configure | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index c20c9e1607..60f34b80bf 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -100,7 +100,13 @@ macro(check_avx512vnni_intrinsics) if(NOT NATIVEFLAG) set(AVX512VNNIFLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx512vnni") if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "ClangCl") - set(AVX512VNNIFLAG "${AVX512VNNIFLAG} -mtune=cascadelake") + check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) + if(HAVE_CASCADE_LAKE) + set(AVX512FLAG "${AVX512VNNIFLAG} -mtune=cascadelake") + else() + set(AVX512FLAG "${AVX512VNNIFLAG} -mtune=skylake-avx512") + endif() + unset(HAVE_CASCADE_LAKE) endif() endif() elseif(MSVC) diff --git a/configure b/configure index 1f3ef7a029..145cd6fb6f 100755 --- a/configure +++ b/configure @@ -106,7 +106,7 @@ forcesse2=0 # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal # instruction scheduling unless you specify a reasonable -mtune= target avx512flag="-mavx512f -mavx512dq -mavx512bw -mavx512vl" -avx512vnniflag="-mavx512vnni ${avx512flag}" +avx512vnniflag="${avx512flag} -mavx512vnni" avx2flag="-mavx2" sse2flag="-msse2" ssse3flag="-mssse3" @@ -1570,9 +1570,11 @@ case "${ARCH}" in if test ${MTUNE_CASCADELAKE_AVAILABLE} -eq 1; then avx512flag="${avx512flag} -mtune=cascadelake" + avx512flag="${avx512vnniflag} -mtune=cascadelake" else if test ${MTUNE_SKYLAKE_AVX512_AVAILABLE} -eq 1; then avx512flag="${avx512flag} -mtune=skylake-avx512" + avx512flag="${avx512vnniflag} -mtune=skylake-avx512" fi fi From 3d713fc48c21ce2728cb87fe8870f384da487c21 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 12 May 2023 23:04:35 +0200 Subject: [PATCH 655/798] Update README.md --- README.md | 97 +++++++++++++++++++++---------------------------------- 1 file changed, 36 insertions(+), 61 deletions(-) diff --git a/README.md b/README.md index 367dc9463b..75b716b606 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,16 @@ +| CI | Stable | Develop | +|:---|:-------|:--------| +| GitHub Actions | [![Stable Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20CMake/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions)
    [![Stable Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20Configure/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions)
    [![Stable Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20NMake/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions) | [![Develop Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20CMake/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions)
    [![Develop Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20Configure/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions)
    [![Develop Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20NMake/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions) | +| CodeFactor | [![CodeFactor](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/badge/stable)](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/overview/stable) | [![CodeFactor](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/badge/develop)](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/overview/develop) | +| OSS-Fuzz | [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/zlib-ng.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zlib-ng) | [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/zlib-ng.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zlib-ng) | +| Codecov | [![codecov](https://codecov.io/github/zlib-ng/zlib-ng/branch/stable/graph/badge.svg?token=uKsgK9LIuC)](https://codecov.io/github/zlib-ng/zlib-ng/tree/stable) | [![codecov](https://codecov.io/github/zlib-ng/zlib-ng/branch/develop/graph/badge.svg?token=uKsgK9LIuC)](https://codecov.io/github/zlib-ng/zlib-ng/tree/develop) | + ## zlib-ng *zlib data compression library for the next generation systems* Maintained by Hans Kristian Rosbach aka Dead2 (zlib-ng àt circlestorm dót org) -|CI|Status| -|:-|-| -|GitHub Actions|[![Master Branch Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20CMake/badge.svg)](https://github.com/zlib-ng/zlib-ng/actions) [![Master Branch Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20Configure/badge.svg)](https://github.com/zlib-ng/zlib-ng/actions) [![Master Branch Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20NMake/badge.svg)](https://github.com/zlib-ng/zlib-ng/actions)| -|Buildkite|[![Build status](https://badge.buildkite.com/7bb1ef84356d3baee26202706cc053ee1de871c0c712b65d26.svg?branch=develop)](https://buildkite.com/circlestorm-productions/zlib-ng)| -|CodeFactor|[![CodeFactor](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/badge)](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng)| -|OSS-Fuzz|[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/zlib-ng.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zlib-ng) -|Codecov|[![codecov.io](https://codecov.io/github/zlib-ng/zlib-ng/coverage.svg?branch=develop)](https://codecov.io/github/zlib-ng/zlib-ng/)| - - Features -------- @@ -40,45 +38,31 @@ Features History ------- -The motivation for this fork came after seeing several 3rd party -contributions containing new optimizations not getting implemented -into the official zlib repository. +The motivation for this fork was seeing several 3rd party contributions with new optimizations not getting +implemented into the official zlib repository. -Mark Adler has been maintaining zlib for a very long time, and he has -done a great job and hopefully he will continue for a long time yet. -The idea of zlib-ng is not to replace zlib, but to co-exist as a -drop-in replacement with a lower threshold for code change. +Mark Adler has been maintaining zlib for a very long time, and he has done a great job and hopefully he will continue +for a long time yet. The idea of zlib-ng is not to replace zlib, but to co-exist as a drop-in replacement with a +lower threshold for code change. -zlib has a long history and is incredibly portable, even supporting -lots of systems that predate the Internet. This is great, but it does -complicate further development and maintainability. -The zlib code has numerous workarounds for old compilers that do not -understand ANSI-C or to accommodate systems with limitations such as -operating in a 16-bit environment. +zlib has a long history and is incredibly portable, even supporting many systems that predate the Internet.
    +That is great, but it can complicate further development and maintainability. The zlib code contains many workarounds +for really old compilers or to accommodate systems with limitations such as operating in a 16-bit environment. -Many of these workarounds are only maintenance burdens, some of them -are pretty huge code-wise. For example, the [v]s[n]printf workaround -code has a whopping 8 different implementations just to cater to -various old compilers. With this many workarounds cluttered throughout -the code, new programmers with an idea/interest for zlib will need -to take some time to figure out why all of these seemingly strange -things are used, and how to work within those confines. +Many of these workarounds are only maintenance burdens, some of them are pretty huge code-wise. With many workarounds +cluttered throughout the code, it makes it harder for new programmers with an idea/interest for zlib to contribute. -So I decided to make a fork, merge all the Intel optimizations, merge -the Cloudflare optimizations that did not conflict, plus a couple -of other smaller patches. Then I started cleaning out workarounds, -various dead code, all contrib and example code as there is little -point in having those in this fork for various reasons. +I decided to make a fork, merge all the Intel optimizations, some of the Cloudflare optimizations, plus a couple other +smaller patches. Then started cleaning out workarounds, various dead code, all contrib and example code.
    +The result is a better performing and easier to maintain zlib-ng. -A lot of improvements have gone into zlib-ng since its start, and -numerous people and companies have contributed both small and big -improvements, or valuable testing. - -Please read LICENSE.md, it is very simple and very liberal. +A lot of improvements have gone into zlib-ng since its start, and numerous people and companies have contributed both +small and big improvements, or valuable testing. Build ----- +Please read LICENSE.md, it is very simple and very liberal. There are two ways to build zlib-ng: @@ -130,17 +114,14 @@ Build Options Install ------- -WARNING: We do not recommend manually installing unless you really -know what you are doing, because this can potentially override the system -default zlib library, and any incompatibility or wrong configuration of -zlib-ng can make the whole system unusable, requiring recovery or reinstall. +WARNING: We do not recommend manually installing unless you really know what you are doing, because this can +potentially override the system default zlib library, and any incompatibility or wrong configuration of zlib-ng +can make the whole system unusable, requiring recovery or reinstall. If you still want a manual install, we recommend using the /opt/ path prefix. -For Linux distros, an alternative way to use zlib-ng (if compiled in -zlib-compat mode) instead of zlib, is through the use of the -_LD_PRELOAD_ environment variable. If the program is dynamically linked -with zlib, then zlib-ng will temporarily be used instead by the program, -without risking system-wide instability. +For Linux distros, an alternative way to use zlib-ng (if compiled in zlib-compat mode) instead of zlib, is through +the use of the _LD_PRELOAD_ environment variable. If the program is dynamically linked with zlib, then the program +will temporarily attempt to use zlib-ng instead, without risking system-wide instability. ``` LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.13.zlib-ng /usr/bin/program @@ -174,33 +155,27 @@ cd vcpkg ./vcpkg install zlib-ng ``` -The zlib-ng port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. +The zlib-ng port in vcpkg is kept up to date by Microsoft team members and community contributors. +If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. Contributing ------------ -Zlib-ng is a aiming to be open to contributions, and we would be delighted to -receive pull requests on github. -Just remember that any code you submit must be your own and it must be zlib licensed. -Help with testing and reviewing of pull requests etc is also very much appreciated. - -If you are interested in contributing, please consider joining our -IRC channel #zlib-ng on the Freenode IRC network. +Zlib-ng is aiming to be open to contributions, and we would be delighted to receive pull requests on github. +Help with testing and reviewing pull requests etc is also very much appreciated. +Please check the Wiki for more info: [Contributing](https://github.com/zlib-ng/zlib-ng/wiki/Contributing) Acknowledgments ---------------- -Thanks to Servebolt.com for sponsoring my maintainership of zlib-ng. - Thanks go out to all the people and companies who have taken the time to contribute code reviews, testing and/or patches. Zlib-ng would not have been nearly as good without you. -The deflate format used by zlib was defined by Phil Katz. +The deflate format used by zlib was defined by Phil Katz.
    The deflate and zlib specifications were written by L. Peter Deutsch. -zlib was originally created by Jean-loup Gailly (compression) -and Mark Adler (decompression). +zlib was originally created by Jean-loup Gailly (compression) and Mark Adler (decompression). Advanced Build Options From c631a47ec527e95a047c3fa24c6dc519ef75fc3e Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 13 May 2023 21:16:32 +0200 Subject: [PATCH 656/798] Fix error in previous commit breaking AVX512. --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 145cd6fb6f..0f11018c1b 100755 --- a/configure +++ b/configure @@ -1570,11 +1570,11 @@ case "${ARCH}" in if test ${MTUNE_CASCADELAKE_AVAILABLE} -eq 1; then avx512flag="${avx512flag} -mtune=cascadelake" - avx512flag="${avx512vnniflag} -mtune=cascadelake" + avx512vnniflag="${avx512vnniflag} -mtune=cascadelake" else if test ${MTUNE_SKYLAKE_AVX512_AVAILABLE} -eq 1; then avx512flag="${avx512flag} -mtune=skylake-avx512" - avx512flag="${avx512vnniflag} -mtune=skylake-avx512" + avx512vnniflag="${avx512vnniflag} -mtune=skylake-avx512" fi fi From 362945baecfa4e0f5bd323d013792d2c2331bf46 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 13 May 2023 22:57:47 +0200 Subject: [PATCH 657/798] Fix the same AVX512 error in CMake. --- cmake/detect-intrinsics.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 60f34b80bf..e9e6d36da8 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -102,9 +102,9 @@ macro(check_avx512vnni_intrinsics) if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "ClangCl") check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) if(HAVE_CASCADE_LAKE) - set(AVX512FLAG "${AVX512VNNIFLAG} -mtune=cascadelake") + set(AVX512VNNIFLAG "${AVX512VNNIFLAG} -mtune=cascadelake") else() - set(AVX512FLAG "${AVX512VNNIFLAG} -mtune=skylake-avx512") + set(AVX512VNNIFLAG "${AVX512VNNIFLAG} -mtune=skylake-avx512") endif() unset(HAVE_CASCADE_LAKE) endif() From cc23c00201255b37371510137578877375d20b6b Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Sat, 13 May 2023 23:15:28 +0300 Subject: [PATCH 658/798] Fix MinGW CI. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index bbed1db0ca..2a148626a5 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -276,7 +276,7 @@ jobs: - name: Ubuntu MinGW i686 os: ubuntu-22.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake - packages: wine wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.39-3ubuntu0.1 libpcre2-8-0:i386=10.39-3ubuntu0.1 libodbc1=2.3.9-5 libodbc1:i386=2.3.9-5 libwine:i386=6.0.3~repack-1 libgphoto2-6:i386=2.5.27-1build2 libsane:i386=1.1.1-5 libgd3=2.3.0-2ubuntu2 libgd3:i386=2.3.0-2ubuntu2 + packages: wine wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.39-3ubuntu0.1 libpcre2-8-0:i386=10.39-3ubuntu0.1 libodbc1=2.3.9-5 libodbc1:i386=2.3.9-5 libwine:i386=6.0.3~repack-1 libgphoto2-6:i386=2.5.27-1build2 libsane:i386=1.1.1-5 libgd3=2.3.0-2ubuntu2 libgd3:i386=2.3.0-2ubuntu2 libgcc-s1:i386 libstdc++6:i386 ldflags: -static codecov: ubuntu_gcc_mingw_i686 # Limit parallel test jobs to prevent wine errors From d7ba81940e06e3e4db8b2dc92bb07ece2ae4c9db Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 15 May 2023 16:22:25 +0200 Subject: [PATCH 659/798] Make an AVX512 status message more clear --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 0f11018c1b..f84233e098 100755 --- a/configure +++ b/configure @@ -1161,10 +1161,10 @@ int main(void) { } EOF if try ${CC} ${CFLAGS} ${avx512flag} $test.c; then - echo "Checking for k-mask intrinsics ... Yes." | tee -a configure.log + echo "Checking for AVX512 k-mask intrinsics ... Yes." | tee -a configure.log HAVE_MASK_INTRIN=1 else - echo "Checking for k-mask intrinsics ... No." | tee -a configure.log + echo "Checking for AVX512 k-mask intrinsics ... No." | tee -a configure.log HAVE_MASK_INTRIN=0 fi } From 80ba8b6e198cc52c61c71be456a9c18e10c055b8 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 5 Feb 2023 10:30:18 -0800 Subject: [PATCH 660/798] Added support for unaligned/intrinsic to deflate_rle. --- CMakeLists.txt | 1 + compare256_rle.h | 134 +++++++++++++++++++++++++++++++++ deflate_rle.c | 30 ++++---- test/benchmarks/CMakeLists.txt | 2 + 4 files changed, 154 insertions(+), 13 deletions(-) create mode 100644 compare256_rle.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a6199d35ab..424fddf618 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -979,6 +979,7 @@ set(ZLIB_PUBLIC_HDRS set(ZLIB_PRIVATE_HDRS adler32_p.h chunkset_tpl.h + compare256_rle.h cpu_features.h crc32_braid_p.h crc32_braid_comb_p.h diff --git a/compare256_rle.h b/compare256_rle.h new file mode 100644 index 0000000000..0f3998d4a3 --- /dev/null +++ b/compare256_rle.h @@ -0,0 +1,134 @@ +/* compare256_rle.h -- 256 byte run-length encoding comparison + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "fallback_builtins.h" + +typedef uint32_t (*compare256_rle_func)(const uint8_t* src0, const uint8_t* src1); + +/* ALIGNED, byte comparison */ +static inline uint32_t compare256_rle_c(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + if (*src0 != *src1) + return len; + src1 += 1, len += 1; + } while (len < 256); + + return 256; +} + +#ifdef UNALIGNED_OK +/* 16-bit unaligned integer comparison */ +static inline uint32_t compare256_rle_unaligned_16(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + uint16_t src0_cmp, src1_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + + do { + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + if (src0_cmp != src1_cmp) + return len + (*src0 == *src1); + src1 += 2, len += 2; + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + if (src0_cmp != src1_cmp) + return len + (*src0 == *src1); + src1 += 2, len += 2; + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + if (src0_cmp != src1_cmp) + return len + (*src0 == *src1); + src1 += 2, len += 2; + memcpy(&src1_cmp, src1, sizeof(src1_cmp)); + if (src0_cmp != src1_cmp) + return len + (*src0 == *src1); + src1 += 2, len += 2; + } while (len < 256); + + return 256; +} + +#ifdef HAVE_BUILTIN_CTZ +/* 32-bit unaligned integer comparison */ +static inline uint32_t compare256_rle_unaligned_32(const uint8_t *src0, const uint8_t *src1) { + uint32_t sv, len = 0; + uint16_t src0_cmp; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + sv = ((uint32_t)src0_cmp << 16) | src0_cmp; + + do { + uint32_t mv, diff; + + memcpy(&mv, src1, sizeof(mv)); + + diff = sv ^ mv; + if (diff) { + uint32_t match_byte = __builtin_ctz(diff) / 8; + return len + match_byte; + } + + src1 += 4, len += 4; + } while (len < 256); + + return 256; +} + +#endif + +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +/* 64-bit unaligned integer comparison */ +static inline uint32_t compare256_rle_unaligned_64(const uint8_t *src0, const uint8_t *src1) { + uint32_t src0_cmp32, len = 0; + uint16_t src0_cmp; + uint64_t sv; + + memcpy(&src0_cmp, src0, sizeof(src0_cmp)); + src0_cmp32 = ((uint32_t)src0_cmp << 16) | src0_cmp; + sv = ((uint64_t)src0_cmp32 << 32) | src0_cmp32; + + do { + uint64_t mv, diff; + + memcpy(&mv, src1, sizeof(mv)); + + diff = sv ^ mv; + if (diff) { + uint64_t match_byte = __builtin_ctzll(diff) / 8; + return len + (uint32_t)match_byte; + } + + src1 += 8, len += 8; + } while (len < 256); + + return 256; +} + +#endif + +#endif + diff --git a/deflate_rle.c b/deflate_rle.c index 4e3fde09f0..cd08509946 100644 --- a/deflate_rle.c +++ b/deflate_rle.c @@ -5,10 +5,23 @@ */ #include "zbuild.h" +#include "compare256_rle.h" #include "deflate.h" #include "deflate_p.h" #include "functable.h" +#ifdef UNALIGNED_OK +# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +# define compare256_rle compare256_rle_unaligned_64 +# elif defined(HAVE_BUILTIN_CTZ) +# define compare256_rle compare256_rle_unaligned_32 +# else +# define compare256_rle compare256_rle_unaligned_16 +# endif +#else +# define compare256_rle compare256_rle_c +#endif + /* =========================================================================== * For Z_RLE, simply look for runs of bytes, generate matches only of distance * one. Do not maintain a hash table. (It will be regenerated if this run of @@ -16,8 +29,7 @@ */ Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { int bflush = 0; /* set if current block must be flushed */ - unsigned int prev; /* byte at distance one to match */ - unsigned char *scan, *strend; /* scan goes up to strend for length of run */ + unsigned char *scan; /* scan goes up to strend for length of run */ uint32_t match_len = 0; for (;;) { @@ -36,20 +48,12 @@ Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { /* See how many times the previous byte repeats */ if (s->lookahead >= STD_MIN_MATCH && s->strstart > 0) { scan = s->window + s->strstart - 1; - prev = *scan; - if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + STD_MAX_MATCH; - do { - } while (prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - scan < strend); - match_len = STD_MAX_MATCH - (unsigned int)(strend - scan); + if (scan[0] == scan[1] && scan[1] == scan[2]) { + match_len = compare256_rle(scan, scan+3)+2; match_len = MIN(match_len, s->lookahead); match_len = MIN(match_len, STD_MAX_MATCH); } - Assert(scan <= s->window + s->window_size - 1, "wild scan"); + Assert(scan+match_len <= s->window + s->window_size - 1, "wild scan"); } /* Emit match if have run of STD_MIN_MATCH or longer, else emit literal */ diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index ebc6acb78a..475fe07cee 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -5,6 +5,7 @@ include(FetchContent) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS ON) + enable_language(CXX) # Search for Google benchmark package @@ -36,6 +37,7 @@ add_executable(benchmark_zlib benchmark_adler32.cc benchmark_adler32_copy.cc benchmark_compare256.cc + benchmark_compare256_rle.cc benchmark_crc32.cc benchmark_main.cc benchmark_slidehash.cc From 7ffe135b5b5d3be8cca798e2477996df1986c95d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 18 Mar 2022 15:49:54 -0700 Subject: [PATCH 661/798] Added unit tests for compare256_rle family of functions. --- test/test_compare256_rle.cc | 63 +++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 test/test_compare256_rle.cc diff --git a/test/test_compare256_rle.cc b/test/test_compare256_rle.cc new file mode 100644 index 0000000000..da60d6f975 --- /dev/null +++ b/test/test_compare256_rle.cc @@ -0,0 +1,63 @@ +/* test_compare256_rle.cc -- compare256_rle unit tests + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include + +extern "C" { +# include "zbuild.h" +# include "zutil_p.h" +# include "compare256_rle.h" +} + +#include + +#define MAX_COMPARE_SIZE (256) + +/* Ensure that compare256_rle returns the correct match length */ +static inline void compare256_rle_match_check(compare256_rle_func compare256_rle) { + int32_t match_len, i; + uint8_t str1[] = {'a', 'a', 0}; + uint8_t *str2; + + str2 = (uint8_t *)zng_alloc(MAX_COMPARE_SIZE); + ASSERT_TRUE(str2 != NULL); + memset(str2, 'a', MAX_COMPARE_SIZE); + + for (i = 0; i <= MAX_COMPARE_SIZE; i++) { + if (i < MAX_COMPARE_SIZE) + str2[i] = 0; + + match_len = compare256_rle(str1, str2); + EXPECT_EQ(match_len, i); + + if (i < MAX_COMPARE_SIZE) + str2[i] = 'a'; + } + + zng_free(str2); +} + +#define TEST_COMPARE256_RLE(name, func, support_flag) \ + TEST(compare256_rle, name) { \ + if (!support_flag) { \ + GTEST_SKIP(); \ + return; \ + } \ + compare256_rle_match_check(func); \ + } + +TEST_COMPARE256_RLE(c, compare256_rle_c, 1) + +#ifdef UNALIGNED_OK +TEST_COMPARE256_RLE(unaligned_16, compare256_rle_unaligned_16, 1) +#ifdef HAVE_BUILTIN_CTZ +TEST_COMPARE256_RLE(unaligned_32, compare256_rle_unaligned_32, 1) +#endif +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +TEST_COMPARE256_RLE(unaligned_64, compare256_rle_unaligned_64, 1) +#endif +#endif From 8162f6b7c5d48a64e0e99f6197274743b8bd128f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 5 Feb 2023 10:30:18 -0800 Subject: [PATCH 662/798] Added benchmark for compare256_rle family of functions. --- test/benchmarks/benchmark_compare256_rle.cc | 73 +++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 test/benchmarks/benchmark_compare256_rle.cc diff --git a/test/benchmarks/benchmark_compare256_rle.cc b/test/benchmarks/benchmark_compare256_rle.cc new file mode 100644 index 0000000000..5a8afd6943 --- /dev/null +++ b/test/benchmarks/benchmark_compare256_rle.cc @@ -0,0 +1,73 @@ +/* benchmark_compare256_rle.cc -- benchmark compare256_rle variants + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include + +#include + +extern "C" { +# include "zbuild.h" +# include "zutil_p.h" +# include "compare256_rle.h" +# include "cpu_features.h" +} + +#define MAX_COMPARE_SIZE (256) + +class compare256_rle: public benchmark::Fixture { +private: + uint8_t *str1; + uint8_t *str2; + +public: + void SetUp(const ::benchmark::State& state) { + str1 = (uint8_t *)zng_alloc(MAX_COMPARE_SIZE); + assert(str1 != NULL); + memset(str1, 'a', MAX_COMPARE_SIZE); + + str2 = (uint8_t *)zng_alloc(MAX_COMPARE_SIZE); + assert(str2 != NULL); + memset(str2, 'a', MAX_COMPARE_SIZE); + } + + void Bench(benchmark::State& state, compare256_rle_func compare256_rle) { + int32_t match_len = (int32_t)state.range(0); + uint32_t len; + + str2[match_len] = 0; + for (auto _ : state) { + len = compare256_rle((const uint8_t *)str1, (const uint8_t *)str2); + } + str2[match_len] = 'a'; + + benchmark::DoNotOptimize(len); + } + + void TearDown(const ::benchmark::State& state) { + zng_free(str1); + zng_free(str2); + } +}; + +#define BENCHMARK_COMPARE256_RLE(name, fptr, support_flag) \ + BENCHMARK_DEFINE_F(compare256_rle, name)(benchmark::State& state) { \ + if (!support_flag) { \ + state.SkipWithError("CPU does not support " #name); \ + } \ + Bench(state, fptr); \ + } \ + BENCHMARK_REGISTER_F(compare256_rle, name)->Range(1, MAX_COMPARE_SIZE); + +BENCHMARK_COMPARE256_RLE(c, compare256_rle_c, 1); + +#ifdef UNALIGNED_OK +BENCHMARK_COMPARE256_RLE(unaligned_16, compare256_rle_unaligned_16, 1); +#ifdef HAVE_BUILTIN_CTZ +BENCHMARK_COMPARE256_RLE(unaligned_32, compare256_rle_unaligned_32, 1); +#endif +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +BENCHMARK_COMPARE256_RLE(unaligned_64, compare256_rle_unaligned_64, 1); +#endif +#endif From c211d11c6655f2d1473fdde9dd2eb64eff5a622b Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 13 May 2023 01:54:25 +0200 Subject: [PATCH 663/798] Add tests of file_compress/file_uncompress in minigzip and minideflate. --- test/cmake/compress-and-verify.cmake | 100 ++++++++++++++++----------- test/cmake/test-data.cmake | 1 + test/cmake/test-tools.cmake | 19 +++++ 3 files changed, 81 insertions(+), 39 deletions(-) diff --git a/test/cmake/compress-and-verify.cmake b/test/cmake/compress-and-verify.cmake index e79c50c4f0..fa69773906 100644 --- a/test/cmake/compress-and-verify.cmake +++ b/test/cmake/compress-and-verify.cmake @@ -22,6 +22,7 @@ # GZIP_VERIFY - Verify that gzip can decompress the COMPRESS_TARGET output and # verify that DECOMPRESS_TARGET can decompress gzip output of INPUT # COMPARE - Verify decompressed output is the same as input +# FILEMODE - Pass data to/from (de)compressor using files instead of stdin/stdout # SUCCESS_EXIT - List of successful exit codes (default: 0, ie: 0;1) if(TARGET) @@ -37,11 +38,20 @@ endif() if(NOT DEFINED COMPARE) set(COMPARE ON) endif() +if(NOT DEFINED FILEMODE) + set(FILEMODE OFF) +endif() if(NOT DEFINED COMPRESS_ARGS) - set(COMPRESS_ARGS -c -k) + set(COMPRESS_ARGS -3 -k) + if(NOT FILEMODE) + list(APPEND COMPRESS_ARGS -c) + endif() endif() if(NOT DEFINED DECOMPRESS_ARGS) - set(DECOMPRESS_ARGS -d -c) + set(DECOMPRESS_ARGS -d -k) + if(NOT FILEMODE) + list(APPEND DECOMPRESS_ARGS -c) + endif() endif() if(NOT DEFINED GZIP_VERIFY) set(GZIP_VERIFY ON) @@ -101,6 +111,25 @@ macro(diff src1 src2) endif() endmacro() + +macro(exec_streams tcmd tsrc tdst) + execute_process(COMMAND ${CMAKE_COMMAND} + "-DCOMMAND=${tcmd}" + -DINPUT=${tsrc} + -DOUTPUT=${tdst} + "-DSUCCESS_EXIT=${SUCCESS_EXIT}" + -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake + RESULT_VARIABLE CMD_RESULT + COMMAND_ECHO STDOUT) +endmacro() + +macro(exec_files tcmd tsrc) + execute_process(COMMAND + ${tcmd} ${tsrc} + RESULT_VARIABLE CMD_RESULT + COMMAND_ECHO STDOUT) +endmacro() + # Compress input file if(NOT EXISTS ${INPUT}) message(FATAL_ERROR "Cannot find compress input: ${INPUT}") @@ -108,17 +137,21 @@ endif() set(COMPRESS_COMMAND ${COMPRESS_TARGET} ${COMPRESS_ARGS}) +set(INPUT_FILE ${OUTPUT_BASE}) + +# Make CMake copy and rename file in one operation +configure_file(${INPUT} ${INPUT_FILE} COPYONLY) + message(STATUS "Compress ${COMPRESS_COMMAND}") -message(STATUS " Input: ${INPUT}") +message(STATUS " Source file: ${INPUT}") +message(STATUS " Compression input file: ${INPUT_FILE}") message(STATUS " Output: ${OUTPUT_BASE}.gz") -execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${COMPRESS_COMMAND}" - -DINPUT=${INPUT} - -DOUTPUT=${OUTPUT_BASE}.gz - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) +if(FILEMODE) + exec_files("${COMPRESS_COMMAND}" "${INPUT_FILE}") +else() + exec_streams("${COMPRESS_COMMAND}" "${INPUT_FILE}" "${OUTPUT_BASE}.gz") +endif() if(CMD_RESULT) cleanup() @@ -137,13 +170,11 @@ message(STATUS "Decompress ${DECOMPRESS_COMMAND}") message(STATUS " Input: ${OUTPUT_BASE}.gz") message(STATUS " Output: ${OUTPUT_BASE}") -execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT_BASE}.gz - -DOUTPUT=${OUTPUT_BASE} - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) +if(FILEMODE) + exec_files("${DECOMPRESS_COMMAND}" "${OUTPUT_BASE}.gz") +else() + exec_streams("${DECOMPRESS_COMMAND}" "${OUTPUT_BASE}.gz" "${OUTPUT_BASE}") +endif() if(CMD_RESULT) cleanup() @@ -151,10 +182,15 @@ if(CMD_RESULT) endif() if(COMPARE) + message(STATUS "Diff comparison") + message(STATUS " Input: ${INPUT}") + message(STATUS " Output: ${OUTPUT_BASE}") + # Compare decompressed output with original input file execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files ${INPUT} ${OUTPUT_BASE} - RESULT_VARIABLE CMD_RESULT) + RESULT_VARIABLE CMD_RESULT + COMMAND_ECHO STDOUT) if(CMD_RESULT) diff(${INPUT} ${OUTPUT_BASE}) @@ -179,13 +215,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") message(STATUS " Input: ${OUTPUT_BASE}.gz") message(STATUS " Output: ${OUTPUT_BASE}-ungzip") - execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${GZ_DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT_BASE}.gz - -DOUTPUT=${OUTPUT_BASE}-ungzip - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) + exec_streams("${GZ_DECOMPRESS_COMMAND}" "${OUTPUT_BASE}.gz" "${OUTPUT_BASE}-ungzip") if(CMD_RESULT) cleanup() @@ -210,13 +240,7 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") message(STATUS " Input: ${INPUT}") message(STATUS " Output: ${OUTPUT_BASE}-gzip.gz") - execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${GZ_COMPRESS_COMMAND}" - -DINPUT=${INPUT} - -DOUTPUT=${OUTPUT_BASE}-gzip.gz - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) + exec_streams("${GZ_COMPRESS_COMMAND}" "${INPUT}" "${OUTPUT_BASE}-gzip.gz") if(CMD_RESULT) cleanup() @@ -233,13 +257,11 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") message(STATUS " Output: ${OUTPUT_BASE}-gzip") # Check decompress target can handle gzip compressed output - execute_process(COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${DECOMPRESS_COMMAND}" - -DINPUT=${OUTPUT_BASE}-gzip.gz - -DOUTPUT=${OUTPUT_BASE}-gzip - "-DSUCCESS_EXIT=${SUCCESS_EXIT}" - -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT) + if(FILEMODE) + exec_files("${DECOMPRESS_COMMAND}" "${OUTPUT_BASE}-gzip.gz") + else() + exec_streams("${DECOMPRESS_COMMAND}" "${OUTPUT_BASE}-gzip.gz" "${OUTPUT_BASE}-gzip") + endif() if(CMD_RESULT) cleanup() diff --git a/test/cmake/test-data.cmake b/test/cmake/test-data.cmake index 07013355a3..e60c356e46 100644 --- a/test/cmake/test-data.cmake +++ b/test/cmake/test-data.cmake @@ -34,6 +34,7 @@ set(TEST_CONFIGS -T # Direct store -0 # No compression -1 # Deflate quick + -2 # Deflate fast -4 # Deflate medium (lazy matches) "-5;-F" # Deflate medium (Z_FIXED) -6 # Deflate medium diff --git a/test/cmake/test-tools.cmake b/test/cmake/test-tools.cmake index afe4835d89..c2a683fbd9 100644 --- a/test/cmake/test-tools.cmake +++ b/test/cmake/test-tools.cmake @@ -1,5 +1,24 @@ # test-tools.cmake -- Tests targeting tool coverage +# Compress and decompress using file_compress/file_decompress, optionally also testing MMAP +add_test(NAME minigzip-file_compress + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIGZIP_COMMAND}" + -DFILEMODE=ON + -DGZIP_VERIFY=ON + -DTEST_NAME=minigzip-file_compress + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/data/paper-100k.pdf + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + +add_test(NAME minideflate-file_compress + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIDEFLATE_COMMAND}" + -DFILEMODE=ON + -DGZIP_VERIFY=OFF + -DTEST_NAME=minideflate-file_compress + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/data/paper-100k.pdf + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) + # Test --help and invalid parameters for our tools set(TEST_COMMAND ${MINIGZIP_COMMAND} "--help") add_test(NAME minigzip-help From 1382b88a14f407d725b16b11a6b286792ccdf066 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 14 May 2023 22:02:25 +0200 Subject: [PATCH 664/798] Fix z_size_t definition: - Zlib Compat: Move definition of z_size_t to zconf.h, so it is exported to applications. Always defined as size_t to follow zlib 1.2.13 behavior with STDC compilers. - Zlib-NG: Keeps internal definition of z_size_t in zbuild.h --- zbuild.h | 5 ----- zconf.h.in | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/zbuild.h b/zbuild.h index 27f784a99f..525a34d8d8 100644 --- a/zbuild.h +++ b/zbuild.h @@ -88,11 +88,6 @@ # define PREFIX3(x) z_ ## x # define PREFIX4(x) x ## 64 # define zVersion zlibVersion -# if defined(_WIN64) -# define z_size_t unsigned __int64 -# else -# define z_size_t unsigned long -# endif #else # define PREFIX(x) zng_ ## x # define PREFIX2(x) ZLIBNG_ ## x diff --git a/zconf.h.in b/zconf.h.in index 765e9c4e47..18c405e8f7 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -25,6 +25,8 @@ # define z_const #endif +typedef size_t z_size_t; + /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # define MAX_MEM_LEVEL 9 From 144b1d4cc5418eb50dfa1e1ca18d3b69ffd0c73c Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 15 May 2023 15:48:11 +0200 Subject: [PATCH 665/798] Remove refrences to z_size_t from zlib-ng.h, since we use size_t directly. --- zlib-ng.h.in | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 7f68f7a337..3696718241 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -1411,9 +1411,7 @@ size_t zng_gzfread(void *buf, size_t size, size_t nitems, gzFile file); /* Read and decompress up to nitems items of size size from file into buf, otherwise operating as gzread() does. This duplicates the interface of - stdio's fread(), with size_t request and return types. If the library - defines size_t, then z_size_t is identical to size_t. If not, then z_size_t - is an unsigned integer type that can contain a pointer. + stdio's fread(), with size_t request and return types. gzfread() returns the number of full items read of size size, or zero if the end of the file was reached and a full item could not be read, or if From 41c4879b8b90f3199b1e5a1f8fc373d3082e5820 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Tue, 16 May 2023 19:40:01 +0300 Subject: [PATCH 666/798] Move defining z_size_t to below including stddef.h and unistd.h in zconf.h. --- zconf.h.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zconf.h.in b/zconf.h.in index 18c405e8f7..074f025516 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -25,8 +25,6 @@ # define z_const #endif -typedef size_t z_size_t; - /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # define MAX_MEM_LEVEL 9 @@ -200,4 +198,6 @@ typedef PTRDIFF_TYPE ptrdiff_t; # endif #endif +typedef size_t z_size_t; + #endif /* ZCONF_H */ From ee68fc338f8a2175fc03bcf3095bc9f384698c29 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 16 May 2023 13:40:27 +0200 Subject: [PATCH 667/798] 2.1.1-Beta2 Changes since 2.1.0-Beta1: - Fix missing exported z_size_t type in zlib.h (zlib-compat mode). - Fix two Coverity warnings - Fix CMake GNUInstallDirs usage - Configure/CMake improvements for compilers with early AVX512-VNNI support (GCC8.0 etc) - Microptimalization for AVX512 implementation of CRC32 - Optimized deflate_rle compression, also added related test and benchmark. - Add testing of file_compress/file_uncompress in minigzip/minideflate - Add emulated RISC-V to CI test workflow - Add deflate_fast to switchlevels test - Fix abicheck CI test was not ignoring version string - Fix MinGW CI test, broken by Github Actions VM image updates --- Makefile.in | 2 +- zlib-ng.h.in | 8 ++++---- zlib.h.in | 8 ++++---- zutil.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile.in b/Makefile.in index 8ca8c81da7..902613e23e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.1.0.beta1 +VER=2.1.1.beta2 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 3696718241..3c2c60a549 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -48,12 +48,12 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.0.beta1" -#define ZLIBNG_VERNUM 0x02010010L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.1.beta2" +#define ZLIBNG_VERNUM 0x02010120L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 0 -#define ZLIBNG_VER_STATUS 0 /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_REVISION 1 +#define ZLIBNG_VER_STATUS 2 /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ /* diff --git a/zlib.h.in b/zlib.h.in index 6da533c402..3fd25adf32 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -49,12 +49,12 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.0.beta1" -#define ZLIBNG_VERNUM 0x02010010L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.1.beta2" +#define ZLIBNG_VERNUM 0x02010120L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 0 -#define ZLIBNG_VER_STATUS 1 /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_REVISION 1 +#define ZLIBNG_VER_STATUS 2 /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ #define ZLIB_VERSION "1.2.13.zlib-ng" diff --git a/zutil.c b/zutil.c index 0fd14f4ef3..2d753b4ad6 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char PREFIX3(vstring)[] = - " zlib-ng 2.1.0.beta1"; + " zlib-ng 2.1.1.beta2"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From eac8a2650fe26e9eea46144319b89b7ae124a872 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 31 May 2023 06:07:10 +0300 Subject: [PATCH 668/798] Add distclean target to arch/generic/Makefile.in --- arch/generic/Makefile.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/generic/Makefile.in b/arch/generic/Makefile.in index be8c185454..c717026f86 100644 --- a/arch/generic/Makefile.in +++ b/arch/generic/Makefile.in @@ -19,3 +19,6 @@ clean: rm -f *.o *.lo *~ \ rm -rf objs rm -f *.gcda *.gcno *.gcov + +distclean: clean + rm -f Makefile From 154441aeac2fa9d051e0f0d95d3846c910ef28d4 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 31 May 2023 07:30:57 +0300 Subject: [PATCH 669/798] Make sure file exists before adding it as dependency in configure. --- configure | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/configure b/configure index f84233e098..a7ecc370b6 100755 --- a/configure +++ b/configure @@ -2148,8 +2148,12 @@ sed < $SRCDIR/Makefile.in " /^ARCH_SHARED_OBJS *=/s#=.*#=$ARCH_SHARED_OBJS# " > Makefile -# Append header files dependences. +# Append header files dependencies. for file in $SRCDIR/*.c $SRCDIR/test/*.c $SRCDIR/test/fuzz/*.c $SRCDIR/$ARCHDIR/*.c $SRCDIR/tools/*.c; do + if test ! -f $file; then + continue + fi + short_name=$(echo $file | sed -e "s#$SRCDIR/##g") incs=$(grep -h include $file | sed -n 's/# *\include *"\(.*\.h\)".*/\1/p' | sort | uniq) includes=$(for i in $incs; do @@ -2222,8 +2226,12 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^PPCFLAGS *=/s#=.*#=$vmxflag# " > $ARCHDIR/Makefile -# Append header files dependences. +# Append header files dependencies. for file in $SRCDIR/$ARCHDIR/*.c; do + if test ! -f $file; then + continue + fi + incs=$(grep -h include $file | sed -n 's/# *\include *"\(.*\.h\)".*/\1/p' | sort | uniq) includes=$(for i in $incs; do # Check that the include file exists in the current dir, From bc6e56b79ff1fa0afac6ee7431cee427f600faef Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 31 May 2023 09:37:23 +0300 Subject: [PATCH 670/798] Add MIPS to GitHub workflows. --- .github/workflows/cmake.yml | 6 ++++++ .github/workflows/configure.yml | 7 +++++++ cmake/toolchain-mips.cmake | 29 +++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 cmake/toolchain-mips.cmake diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 2a148626a5..36f138f60f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -192,6 +192,12 @@ jobs: packages: qemu qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_compat_no_opt + - name: Ubuntu GCC MIPS + os: ubuntu-latest + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mips.cmake + packages: qemu qemu-user gcc-mips-linux-gnu g++-mips-linux-gnu libc-dev-mips-cross + codecov: ubuntu_gcc_mips + - name: Ubuntu GCC PPC os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 51861533e0..4b831917fe 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -100,6 +100,13 @@ jobs: chost: aarch64-linux-gnu packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross + - name: Ubuntu GCC MIPS + os: ubuntu-latest + compiler: mips-linux-gnu-gcc + configure-args: --warn + chost: mips-linux-gnu + packages: qemu qemu-user gcc-mips-linux-gnu libc-dev-mips-cross + - name: Ubuntu GCC PPC os: ubuntu-latest compiler: powerpc-linux-gnu-gcc diff --git a/cmake/toolchain-mips.cmake b/cmake/toolchain-mips.cmake new file mode 100644 index 0000000000..69a1025e34 --- /dev/null +++ b/cmake/toolchain-mips.cmake @@ -0,0 +1,29 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR mips) +set(CMAKE_SYSTEM_VERSION 1) + +if(NOT DEFINED CMAKE_C_COMPILER_TARGET) + set(CMAKE_C_COMPILER_TARGET mips-linux-gnu) +endif() +if(NOT DEFINED CMAKE_CXX_COMPILER_TARGET) + set(CMAKE_CXX_COMPILER_TARGET mips-linux-gnu) +endif() + +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-mips -L /usr/${CMAKE_C_COMPILER_TARGET}/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() From ad29d3b002aa7d880f5f1df10899f2abe3a32576 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 1 Jun 2023 09:22:24 +0300 Subject: [PATCH 671/798] distclean target should depend on clean target in arch directories. --- arch/arm/Makefile.in | 2 +- arch/power/Makefile.in | 2 +- arch/s390/Makefile.in | 2 +- arch/x86/Makefile.in | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/Makefile.in b/arch/arm/Makefile.in index abf6193fc0..717754760f 100644 --- a/arch/arm/Makefile.in +++ b/arch/arm/Makefile.in @@ -73,5 +73,5 @@ clean: rm -rf objs rm -f *.gcda *.gcno *.gcov -distclean: +distclean: clean rm -f Makefile diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index e9be6dddba..e2bec5e510 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -89,5 +89,5 @@ clean: rm -rf objs rm -f *.gcda *.gcno *.gcov -distclean: +distclean: clean rm -f Makefile diff --git a/arch/s390/Makefile.in b/arch/s390/Makefile.in index 39b5aae619..6b4fba7775 100644 --- a/arch/s390/Makefile.in +++ b/arch/s390/Makefile.in @@ -50,5 +50,5 @@ clean: rm -rf objs rm -f *.gcda *.gcno *.gcov -distclean: +distclean: clean rm -f Makefile diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index f0478bfdcc..7c052469b2 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -143,5 +143,5 @@ clean: rm -rf objs rm -f *.gcda *.gcno *.gcov -distclean: +distclean: clean rm -f Makefile From 5fe0c3a01f69574b4ff1a5112f63a91d53a88324 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 31 May 2023 10:19:05 +0300 Subject: [PATCH 672/798] Add MIPS64 to GitHub workflows. --- .github/workflows/cmake.yml | 6 ++++++ .github/workflows/configure.yml | 7 +++++++ cmake/toolchain-mips64.cmake | 29 +++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 cmake/toolchain-mips64.cmake diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 36f138f60f..f16ab99c76 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -198,6 +198,12 @@ jobs: packages: qemu qemu-user gcc-mips-linux-gnu g++-mips-linux-gnu libc-dev-mips-cross codecov: ubuntu_gcc_mips + - name: Ubuntu GCC MIPS64 + os: ubuntu-latest + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mips64.cmake + packages: qemu qemu-user gcc-mips64-linux-gnuabi64 g++-mips64-linux-gnuabi64 libc-dev-mips64-cross + codecov: ubuntu_gcc_mips64 + - name: Ubuntu GCC PPC os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 4b831917fe..02a36005f8 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -107,6 +107,13 @@ jobs: chost: mips-linux-gnu packages: qemu qemu-user gcc-mips-linux-gnu libc-dev-mips-cross + - name: Ubuntu GCC MIPS64 + os: ubuntu-latest + compiler: mips64-linux-gnuabi64-gcc + configure-args: --warn + chost: mips64-linux-gnuabi64 + packages: qemu qemu-user gcc-mips64-linux-gnuabi64 libc-dev-mips64-cross + - name: Ubuntu GCC PPC os: ubuntu-latest compiler: powerpc-linux-gnu-gcc diff --git a/cmake/toolchain-mips64.cmake b/cmake/toolchain-mips64.cmake new file mode 100644 index 0000000000..8ef3b6b009 --- /dev/null +++ b/cmake/toolchain-mips64.cmake @@ -0,0 +1,29 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR mips64) +set(CMAKE_SYSTEM_VERSION 1) + +if(NOT DEFINED CMAKE_C_COMPILER_TARGET) + set(CMAKE_C_COMPILER_TARGET mips64-linux-gnuabi64) +endif() +if(NOT DEFINED CMAKE_CXX_COMPILER_TARGET) + set(CMAKE_CXX_COMPILER_TARGET mips64-linux-gnuabi64) +endif() + +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-mips64 -L /usr/${CMAKE_C_COMPILER_TARGET}/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() From 1f51e8cdaff8a008c6a6b85c9f268b93674c8058 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 1 Jun 2023 12:09:56 +0300 Subject: [PATCH 673/798] distclean target in test directory should depend on clean target. --- test/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Makefile.in b/test/Makefile.in index d2658e7ce4..fd2b239aa8 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -78,5 +78,5 @@ clean: rm -f *.o *.gcda *.gcno *.gcov rm -f switchlevels$(EXE) gh1235$(EXE) -distclean: +distclean: clean rm -f Makefile From 8b9599e14e92c669989a44aef62d11e3b95e73de Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 2 Jun 2023 01:59:13 +0300 Subject: [PATCH 674/798] No indentation allowed for error function in test/Makefile.in --- test/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Makefile.in b/test/Makefile.in index fd2b239aa8..429e2c7708 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -19,7 +19,7 @@ check_cross_dep: ifneq (,$(findstring qemu,$(EMU_RUN))) QEMU_VER:=$(shell command -v $(EMU_RUN) --version 2> /dev/null) ifeq (,$(QEMU_VER)) - $(error You need QEMU to run tests on non-native platform) +$(error You need QEMU to run tests on non-native platform) endif endif From a3874ef0070b16eaed8c9923488bb2cca17fd110 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 2 Jun 2023 02:50:10 +0300 Subject: [PATCH 675/798] Add ABI files for MIPS/MIPS64. --- ...806c2a18c1281fc-mips-unknown-linux-gnu.abi | 1032 ++++++++++++++ ...8c1281fc-mips64-unknown-linux-gnuabi64.abi | 1030 ++++++++++++++ ...55e4baf80882311-mips-unknown-linux-gnu.abi | 1241 ++++++++++++++++ ...80882311-mips64-unknown-linux-gnuabi64.abi | 1250 +++++++++++++++++ 4 files changed, 4553 insertions(+) create mode 100644 test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-mips-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-mips64-unknown-linux-gnuabi64.abi create mode 100644 test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-mips-unknown-linux-gnu.abi create mode 100644 test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-mips64-unknown-linux-gnuabi64.abi diff --git a/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-mips-unknown-linux-gnu.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-mips-unknown-linux-gnu.abi new file mode 100644 index 0000000000..6a321b540a --- /dev/null +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-mips-unknown-linux-gnu.abi @@ -0,0 +1,1032 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-mips64-unknown-linux-gnuabi64.abi b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-mips64-unknown-linux-gnuabi64.abi new file mode 100644 index 0000000000..81925a88ca --- /dev/null +++ b/test/abi/zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc-mips64-unknown-linux-gnuabi64.abi @@ -0,0 +1,1030 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-mips-unknown-linux-gnu.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-mips-unknown-linux-gnu.abi new file mode 100644 index 0000000000..53e2b06b58 --- /dev/null +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-mips-unknown-linux-gnu.abi @@ -0,0 +1,1241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-mips64-unknown-linux-gnuabi64.abi b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-mips64-unknown-linux-gnuabi64.abi new file mode 100644 index 0000000000..3e4322f455 --- /dev/null +++ b/test/abi/zlib-ng-e4614ebcb9b3e5b108dc983c155e4baf80882311-mips64-unknown-linux-gnuabi64.abi @@ -0,0 +1,1250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 963898f4878a81e2c4f7f00941a313556eb1a3c8 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 2 Jun 2023 03:07:27 +0300 Subject: [PATCH 676/798] Update Package Check CI workflow. --- .github/workflows/pkgcheck.yml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 8888cf37e0..4e07f021be 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -27,7 +27,7 @@ jobs: os: ubuntu-latest chost: arm-linux-gnueabihf compiler: arm-linux-gnueabihf-gcc - cxx-compiler: g++-arm-linux-gnueabihf + cxx-compiler: arm-linux-gnueabihf-g++ cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake packages: qemu gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-dev-armhf-cross @@ -35,15 +35,31 @@ jobs: os: ubuntu-latest chost: aarch64-linux-gnu compiler: aarch64-linux-gnu-gcc - cxx-compiler: g++-aarch64-linux-gnu + cxx-compiler: aarch64-linux-gnu-g++ cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake packages: qemu gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross + - name: Ubuntu GCC MIPS + os: ubuntu-latest + chost: mips-linux-gnu + compiler: mips-linux-gnu-gcc + cxx-compiler: mips-linux-gnu-g++ + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mips.cmake + packages: qemu gcc-mips-linux-gnu g++-mips-linux-gnu libc6-dev-mips-cross + + - name: Ubuntu GCC MIPS64 + os: ubuntu-latest + chost: mips64-linux-gnuabi64 + compiler: mips64-linux-gnuabi64-gcc + cxx-compiler: mips64-linux-gnuabi64-g++ + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mips64.cmake + packages: qemu gcc-mips64-linux-gnuabi64 g++-mips64-linux-gnuabi64 libc6-dev-mips64-cross + - name: Ubuntu GCC PPC os: ubuntu-latest chost: powerpc-linux-gnu compiler: powerpc-linux-gnu-gcc - cxx-compiler: g++-powerpc-linux-gnu + cxx-compiler: powerpc-linux-gnu-g++ cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake packages: qemu gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc6-dev-powerpc-cross @@ -51,7 +67,7 @@ jobs: os: ubuntu-latest chost: powerpc64le-linux-gnu compiler: powerpc64le-linux-gnu-gcc - cxx-compiler: g++-powerpc64le-linux-gnu + cxx-compiler: powerpc64le-linux-gnu-g++ cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake packages: qemu gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc6-dev-ppc64el-cross From 69bd70a4c1dab90053dacb98e4dac9892d789da0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 4 Jun 2023 12:39:42 -0700 Subject: [PATCH 677/798] Remove COMMAND_ECHO statements only available in CMake 3.15. #1511 Instead use -DCMAKE_EXECUTE_PROCESS_COMMAND_ECHO=ON. --- test/cmake/compress-and-verify.cmake | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/cmake/compress-and-verify.cmake b/test/cmake/compress-and-verify.cmake index fa69773906..d2d9917a93 100644 --- a/test/cmake/compress-and-verify.cmake +++ b/test/cmake/compress-and-verify.cmake @@ -119,15 +119,13 @@ macro(exec_streams tcmd tsrc tdst) -DOUTPUT=${tdst} "-DSUCCESS_EXIT=${SUCCESS_EXIT}" -P ${CMAKE_CURRENT_LIST_DIR}/run-and-redirect.cmake - RESULT_VARIABLE CMD_RESULT - COMMAND_ECHO STDOUT) + RESULT_VARIABLE CMD_RESULT) endmacro() macro(exec_files tcmd tsrc) execute_process(COMMAND ${tcmd} ${tsrc} - RESULT_VARIABLE CMD_RESULT - COMMAND_ECHO STDOUT) + RESULT_VARIABLE CMD_RESULT) endmacro() # Compress input file @@ -189,8 +187,7 @@ if(COMPARE) # Compare decompressed output with original input file execute_process(COMMAND ${CMAKE_COMMAND} -E compare_files ${INPUT} ${OUTPUT_BASE} - RESULT_VARIABLE CMD_RESULT - COMMAND_ECHO STDOUT) + RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) diff(${INPUT} ${OUTPUT_BASE}) From f75c6856c32a0ade1f33e266fb370bac92d15fac Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Wed, 7 Jun 2023 20:08:08 +0200 Subject: [PATCH 678/798] 2.1.2 Release --- Makefile.in | 2 +- zlib-ng.h.in | 8 ++++---- zlib.h.in | 8 ++++---- zutil.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile.in b/Makefile.in index 902613e23e..deb3ebcd82 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.1.1.beta2 +VER=2.1.2 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 3c2c60a549..2abd320222 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -48,12 +48,12 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.1.beta2" -#define ZLIBNG_VERNUM 0x02010120L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.2" +#define ZLIBNG_VERNUM 0x020102F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 1 -#define ZLIBNG_VER_STATUS 2 /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_REVISION 2 +#define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ /* diff --git a/zlib.h.in b/zlib.h.in index 3fd25adf32..6788bf7781 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -49,12 +49,12 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.1.beta2" -#define ZLIBNG_VERNUM 0x02010120L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.2" +#define ZLIBNG_VERNUM 0x020102F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 1 -#define ZLIBNG_VER_STATUS 2 /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_REVISION 2 +#define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ #define ZLIB_VERSION "1.2.13.zlib-ng" diff --git a/zutil.c b/zutil.c index 2d753b4ad6..9ab667df8d 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char PREFIX3(vstring)[] = - " zlib-ng 2.1.1.beta2"; + " zlib-ng 2.1.2"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From 571c0672c0b66f8c1d3cbd47ba278caead06ccd2 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 9 Jun 2023 17:54:15 +0300 Subject: [PATCH 679/798] Add support for cross-compiling for Power9. --- .github/workflows/cmake.yml | 19 ++++++++++++++++++ cmake/toolchain-powerpc64-power9.cmake | 25 ++++++++++++++++++++++++ cmake/toolchain-powerpc64le-power9.cmake | 25 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 cmake/toolchain-powerpc64-power9.cmake create mode 100644 cmake/toolchain-powerpc64le-power9.cmake diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index f16ab99c76..d00ecb4c41 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -223,12 +223,31 @@ jobs: ldflags: -static codecov: ubuntu_gcc_ppc64 + - name: Ubuntu GCC PPC64 Power9 + os: ubuntu-latest + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64-power9.cmake + packages: qemu qemu-user gcc-powerpc64-linux-gnu g++-powerpc64-linux-gnu libc-dev-ppc64-cross + ldflags: -static + codecov: ubuntu_gcc_ppc64_power9 + - name: Ubuntu GCC PPC64LE os: ubuntu-20.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake packages: qemu qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc-dev-ppc64el-cross codecov: ubuntu_gcc_ppc64le + - name: Ubuntu GCC PPC64LE No VSX + os: ubuntu-latest + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le-power9.cmake -DWITH_POWER8=OFF -DWITH_POWER9=OFF + packages: qemu qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc-dev-ppc64el-cross + codecov: ubuntu_gcc_ppc64le_novsx + + - name: Ubuntu GCC PPC64LE Power9 + os: ubuntu-latest + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le-power9.cmake + packages: qemu qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc-dev-ppc64el-cross + codecov: ubuntu_gcc_ppc64le_power9 + - name: Ubuntu GCC SPARC64 os: ubuntu-20.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake diff --git a/cmake/toolchain-powerpc64-power9.cmake b/cmake/toolchain-powerpc64-power9.cmake new file mode 100644 index 0000000000..2ea190a4d1 --- /dev/null +++ b/cmake/toolchain-powerpc64-power9.cmake @@ -0,0 +1,25 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR ppc64) +set(CMAKE_SYSTEM_VERSION 1) + +set(CMAKE_C_COMPILER_TARGET powerpc64-linux-gnu) +set(CMAKE_CXX_COMPILER_TARGET powerpc64-linux-gnu) + +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64 -cpu power9 -L /usr/${CMAKE_C_COMPILER_TARGET}/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() diff --git a/cmake/toolchain-powerpc64le-power9.cmake b/cmake/toolchain-powerpc64le-power9.cmake new file mode 100644 index 0000000000..5ac8c7a9c1 --- /dev/null +++ b/cmake/toolchain-powerpc64le-power9.cmake @@ -0,0 +1,25 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR ppc64le) +set(CMAKE_SYSTEM_VERSION 1) + +set(CMAKE_C_COMPILER_TARGET powerpc64le-linux-gnu) +set(CMAKE_CXX_COMPILER_TARGET powerpc64le-linux-gnu) + +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64le -cpu power9 -L /usr/${CMAKE_C_COMPILER_TARGET}/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() From e5ab5890a89860a7f4115fca9b0fc7c778b26ef1 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 9 Jun 2023 22:03:18 +0300 Subject: [PATCH 680/798] Fix for PowerPC64 little-endian. --- arch/power/adler32_vmx.c | 7 ++++++- arch/power/compare256_power9.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index ef1649b589..3470c28a12 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -1,6 +1,6 @@ /* adler32_vmx.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011 Mark Adler - * Copyright (C) 2017-2021 Mika T. Lindqvist + * Copyright (C) 2017-2023 Mika T. Lindqvist * Copyright (C) 2021 Adam Stylinski * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,6 +8,7 @@ #ifdef PPC_VMX #include #include "zbuild.h" +#include "zendian.h" #include "adler32_p.h" #define vmx_zero() (vec_splat_u32(0)) @@ -34,7 +35,11 @@ static void vmx_accum32(uint32_t *s, const uint8_t *buf, size_t len) { vector unsigned int adacc, s2acc; vector unsigned int pair_vec = vec_ld(0, s); adacc = vec_perm(pair_vec, pair_vec, s0_perm); +#if BYTE_ORDER == LITTLE_ENDIAN + s2acc = vec_sro(pair_vec, shift_vec); +#else s2acc = vec_slo(pair_vec, shift_vec); +#endif vector unsigned int zero = vmx_zero(); vector unsigned int s3acc = zero; diff --git a/arch/power/compare256_power9.c b/arch/power/compare256_power9.c index 9b3e617014..be094350f8 100644 --- a/arch/power/compare256_power9.c +++ b/arch/power/compare256_power9.c @@ -10,7 +10,7 @@ /* Older versions of GCC misimplemented semantics for these bit counting builtins. * https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=3f30f2d1dbb3228b8468b26239fe60c2974ce2ac */ -#if defined(__GNUC__) && (__GNUC__ < 12) +#if defined(__GNUC__) && (__GNUC__ < 13) # define zng_vec_vctzlsbb(vc, len) __asm__ volatile("vctzlsbb %0, %1\n\t" : "=r" (len) : "v" (vc)) # define zng_vec_vclzlsbb(vc, len) __asm__ volatile("vclzlsbb %0, %1\n\t" : "=r" (len) : "v" (vc)) #else From 39136c20716a94188c1d041b9656315371d35a47 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Sun, 11 Jun 2023 18:38:12 +0300 Subject: [PATCH 681/798] Try to find system copy of googletest before trying to download it. * Don't use system copy if memory sanitizer is enabled --- test/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d434ec3083..a7919a9628 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -111,8 +111,6 @@ if(WITH_BENCHMARKS) endif() if(WITH_GTEST) - include(FetchContent) - # Google test requires at least C++11 set(CMAKE_CXX_STANDARD 11) @@ -125,9 +123,13 @@ if(WITH_GTEST) # Must set include and compile options before fetching googletest include_directories($ENV{LLVM_BUILD_DIR}/include $ENV{LLVM_BUILD_DIR}/include/c++/v1) add_compile_options(-stdlib=libc++ -g) + elseif(NOT TARGET GTest::GTest) + find_package(GTest) endif() if(NOT TARGET GTest::GTest) + include(FetchContent) + # Prevent overriding the parent project's compiler/linker settings for Windows set(gtest_force_shared_crt ON CACHE BOOL "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) From de1b640ffbd0b5b3eccc083fbe22124333824284 Mon Sep 17 00:00:00 2001 From: alexsifivetw Date: Tue, 16 May 2023 03:01:37 -0700 Subject: [PATCH 682/798] Optimize compare256 with rvv --- CMakeLists.txt | 5 +++ README.md | 2 +- arch/riscv/compare256_rvv.c | 47 +++++++++++++++++++++++++ cpu_features.h | 9 +++++ functable.c | 10 ++++++ test/benchmarks/benchmark_compare256.cc | 3 ++ test/test_compare256.cc | 3 ++ 7 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 arch/riscv/compare256_rvv.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 424fddf618..ef4f239b6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -731,6 +731,11 @@ if(WITH_OPTIM) add_definitions(-DRISCV_RVV) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/riscv_features.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c) + # FIXME: we will not set compile flags for riscv_features.c when + # the kernels update hwcap or hwprobe for riscv + set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/compare256_rvv.c) + list(APPEND ZLIB_ARCH_SRCS ${RVV_SRCS}) + set_property(SOURCE ${RVV_SRCS} PROPERTY COMPILE_FLAGS "${RISCVFLAG} ${NOLTOFLAG}") else() set(WITH_RVV OFF) endif() diff --git a/README.md b/README.md index 75b716b606..c83b8487f1 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Features * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, ACLE, & IBM Z * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX - * Compare256 implementations using SSE2, AVX2, Neon, & POWER9 + * Compare256 implementations using SSE2, AVX2, Neon, POWER9 & RVV * Inflate chunk copying using SSE2, SSSE3, AVX, Neon & VSX * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements diff --git a/arch/riscv/compare256_rvv.c b/arch/riscv/compare256_rvv.c new file mode 100644 index 0000000000..acb28035f3 --- /dev/null +++ b/arch/riscv/compare256_rvv.c @@ -0,0 +1,47 @@ +/* compare256_rvv.c - RVV version of compare256 + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef RISCV_RVV + +#include "../../zbuild.h" +#include "fallback_builtins.h" + +#include + +static inline uint32_t compare256_rvv_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + size_t vl; + long found_diff; + do { + vl = __riscv_vsetvl_e8m4(256 - len); + vuint8m4_t v_src0 = __riscv_vle8_v_u8m4(src0, vl); + vuint8m4_t v_src1 = __riscv_vle8_v_u8m4(src1, vl); + vbool2_t v_mask = __riscv_vmsne_vv_u8m4_b2(v_src0, v_src1, vl); + found_diff = __riscv_vfirst_m_b2(v_mask, vl); + if (found_diff >= 0) + return len + (uint32_t)found_diff; + src0 += vl, src1 += vl, len += vl; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_rvv(const uint8_t *src0, const uint8_t *src1) { + return compare256_rvv_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_rvv +#define COMPARE256 compare256_rvv_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_rvv +#define COMPARE256 compare256_rvv_static + +#include "match_tpl.h" + +#endif // RISCV_RVV diff --git a/cpu_features.h b/cpu_features.h index 647d027f6e..fb43d90a26 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -180,6 +180,9 @@ extern uint32_t compare256_neon(const uint8_t *src0, const uint8_t *src1); #ifdef POWER9 extern uint32_t compare256_power9(const uint8_t *src0, const uint8_t *src1); #endif +#ifdef RISCV_RVV +extern uint32_t compare256_rvv(const uint8_t *src0, const uint8_t *src1); +#endif #ifdef DEFLATE_H_ /* insert_string */ @@ -213,6 +216,9 @@ extern uint32_t longest_match_neon(deflate_state *const s, Pos cur_match); #ifdef POWER9 extern uint32_t longest_match_power9(deflate_state *const s, Pos cur_match); #endif +#ifdef RISCV_RVV +extern uint32_t longest_match_rvv(deflate_state *const s, Pos cur_match); +#endif /* longest_match_slow */ extern uint32_t longest_match_slow_c(deflate_state *const s, Pos cur_match); @@ -235,6 +241,9 @@ extern uint32_t longest_match_slow_neon(deflate_state *const s, Pos cur_match); #ifdef POWER9 extern uint32_t longest_match_slow_power9(deflate_state *const s, Pos cur_match); #endif +#ifdef RISCV_RVV +extern uint32_t longest_match_slow_rvv(deflate_state *const s, Pos cur_match); +#endif /* quick_insert_string */ extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); diff --git a/functable.c b/functable.c index d200982922..60d4137b37 100644 --- a/functable.c +++ b/functable.c @@ -202,6 +202,16 @@ static void init_functable(void) { #endif + // RISCV - RVV +#ifdef RISCV_RVV + if (cf.riscv.has_rvv) { + ft.compare256 = &compare256_rvv; + ft.longest_match = &longest_match_rvv; + ft.longest_match_slow = &longest_match_slow_rvv; + } +#endif + + // S390 #ifdef S390_CRC32_VX if (cf.s390.has_vx) diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 3ab04d2022..db5ba83f6c 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -82,3 +82,6 @@ BENCHMARK_COMPARE256(neon, compare256_neon, test_cpu_features.arm.has_neon); #ifdef POWER9 BENCHMARK_COMPARE256(power9, compare256_power9, test_cpu_features.power.has_arch_3_00); #endif +#ifdef RISCV_RVV +BENCHMARK_COMPARE256(rvv, compare256_rvv, test_cpu_features.riscv.has_rvv); +#endif diff --git a/test/test_compare256.cc b/test/test_compare256.cc index 0e656da371..8900902f91 100644 --- a/test/test_compare256.cc +++ b/test/test_compare256.cc @@ -81,3 +81,6 @@ TEST_COMPARE256(neon, compare256_neon, test_cpu_features.arm.has_neon) #ifdef POWER9 TEST_COMPARE256(power9, compare256_power9, test_cpu_features.power.has_arch_3_00) #endif +#ifdef RISCV_RVV +TEST_COMPARE256(rvv, compare256_rvv, test_cpu_features.riscv.has_rvv) +#endif From afd2a0c323c5c787c1f8a0597568be85f41ab281 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 20 May 2023 19:52:21 -0700 Subject: [PATCH 683/798] Minor code cleanup in deflate.c. --- deflate.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/deflate.c b/deflate.c index 3ea92a82dd..55abcf6217 100644 --- a/deflate.c +++ b/deflate.c @@ -478,9 +478,7 @@ int32_t Z_EXPORT PREFIX(deflateResetKeep)(PREFIX3(stream) *strm) { /* ========================================================================= */ int32_t Z_EXPORT PREFIX(deflateReset)(PREFIX3(stream) *strm) { - int ret; - - ret = PREFIX(deflateResetKeep)(strm); + int ret = PREFIX(deflateResetKeep)(strm); if (ret == Z_OK) lm_init(strm->state); return ret; @@ -692,9 +690,7 @@ Z_INTERNAL void PREFIX(flush_pending)(PREFIX3(stream) *strm) { deflate_state *s = strm->state; zng_tr_flush_bits(s); - len = s->pending; - if (len > strm->avail_out) - len = strm->avail_out; + len = MIN(s->pending, strm->avail_out); if (len == 0) return; @@ -1095,9 +1091,7 @@ int32_t Z_EXPORT PREFIX(deflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou * (See also flush_pending()). */ Z_INTERNAL unsigned PREFIX(read_buf)(PREFIX3(stream) *strm, unsigned char *buf, unsigned size) { - uint32_t len = strm->avail_in; - - len = MIN(len, size); + uint32_t len = MIN(strm->avail_in, size); if (len == 0) return 0; @@ -1109,11 +1103,10 @@ Z_INTERNAL unsigned PREFIX(read_buf)(PREFIX3(stream) *strm, unsigned char *buf, } else if (strm->state->wrap == 2) { functable.crc32_fold_copy(&strm->state->crc_fold, buf, strm->next_in, len); #endif + } else if (strm->state->wrap == 1) { + strm->adler = functable.adler32_fold_copy(strm->adler, buf, strm->next_in, len); } else { - if (strm->state->wrap == 1) - strm->adler = functable.adler32_fold_copy(strm->adler, buf, strm->next_in, len); - else - memcpy(buf, strm->next_in, len); + memcpy(buf, strm->next_in, len); } strm->next_in += len; strm->total_in += len; @@ -1234,11 +1227,9 @@ void Z_INTERNAL PREFIX(fill_window)(deflate_state *s) { } else if (str >= 1) { s->quick_insert_string(s, str + 2 - STD_MIN_MATCH); } - unsigned int count; + unsigned int count = s->insert; if (UNLIKELY(s->lookahead == 1)) { - count = s->insert - 1; - } else { - count = s->insert; + count -= 1; } if (count > 0) { s->insert_string(s, str, count); @@ -1313,8 +1304,6 @@ int32_t Z_EXPORT zng_deflateSetParams(zng_stream *strm, zng_deflate_param_value int version_error = 0; int buf_error = 0; int stream_error = 0; - int ret; - int val; /* Initialize the statuses. */ for (i = 0; i < count; i++) @@ -1354,8 +1343,8 @@ int32_t Z_EXPORT zng_deflateSetParams(zng_stream *strm, zng_deflate_param_value /* Apply changes, remember if there were errors. */ if (new_level != NULL || new_strategy != NULL) { - ret = PREFIX(deflateParams)(strm, new_level == NULL ? s->level : *(int *)new_level->buf, - new_strategy == NULL ? s->strategy : *(int *)new_strategy->buf); + int ret = PREFIX(deflateParams)(strm, new_level == NULL ? s->level : *(int *)new_level->buf, + new_strategy == NULL ? s->strategy : *(int *)new_strategy->buf); if (ret != Z_OK) { if (new_level != NULL) new_level->status = Z_STREAM_ERROR; @@ -1365,7 +1354,7 @@ int32_t Z_EXPORT zng_deflateSetParams(zng_stream *strm, zng_deflate_param_value } } if (new_reproducible != NULL) { - val = *(int *)new_reproducible->buf; + int val = *(int *)new_reproducible->buf; if (DEFLATE_CAN_SET_REPRODUCIBLE(strm, val)) { s->reproducible = val; } else { From 7cda3bf660b13f775f563740c9b99957a1383e01 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Mon, 12 Jun 2023 01:18:12 +0300 Subject: [PATCH 684/798] Use endianess-specific built-in function for gcc < 12 on PowerPC64 * Add support for cross-compiling using clang 13 and later for PowerPC64 little-endian and big-endian * Fix detection for availability of Power9 intrinsics --- .github/workflows/cmake.yml | 10 ++++++++++ arch/power/chunkset_power8.c | 2 +- arch/power/compare256_power9.c | 16 +++++++--------- arch/power/power_features.c | 4 ++++ cmake/detect-intrinsics.cmake | 14 ++++++++++++-- cmake/toolchain-powerpc64-clang.cmake | 16 ++++++++++++++++ cmake/toolchain-powerpc64le-clang.cmake | 16 ++++++++++++++++ configure | 14 +++++++++++++- 8 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 cmake/toolchain-powerpc64-clang.cmake create mode 100644 cmake/toolchain-powerpc64le-clang.cmake diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index d00ecb4c41..752d628d9e 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -230,6 +230,11 @@ jobs: ldflags: -static codecov: ubuntu_gcc_ppc64_power9 + - name: Ubuntu Clang PPC64 Power9 + os: ubuntu-latest + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64-clang.cmake + packages: qemu qemu-user clang binutils-powerpc64-linux-gnu libc-dev-ppc64-cross libgcc-11-dev-ppc64-cross libstdc++-11-dev-ppc64-cross + - name: Ubuntu GCC PPC64LE os: ubuntu-20.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake @@ -248,6 +253,11 @@ jobs: packages: qemu qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc-dev-ppc64el-cross codecov: ubuntu_gcc_ppc64le_power9 + - name: Ubuntu Clang PPC64LE Power9 + os: ubuntu-latest + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le-clang.cmake + packages: qemu qemu-user clang binutils-powerpc64le-linux-gnu libc-dev-ppc64el-cross libgcc-11-dev-ppc64el-cross libstdc++-11-dev-ppc64el-cross + - name: Ubuntu GCC SPARC64 os: ubuntu-20.04 cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index 443aae92f1..7cbb8029b3 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -29,7 +29,7 @@ static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { uint64_t tmp; memcpy(&tmp, from, sizeof(tmp)); - *chunk = (vector unsigned char)vec_splats(tmp); + *chunk = (vector unsigned char)vec_splats((unsigned long long)tmp); } static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { diff --git a/arch/power/compare256_power9.c b/arch/power/compare256_power9.c index be094350f8..9b0ddaf800 100644 --- a/arch/power/compare256_power9.c +++ b/arch/power/compare256_power9.c @@ -10,12 +10,14 @@ /* Older versions of GCC misimplemented semantics for these bit counting builtins. * https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=3f30f2d1dbb3228b8468b26239fe60c2974ce2ac */ -#if defined(__GNUC__) && (__GNUC__ < 13) -# define zng_vec_vctzlsbb(vc, len) __asm__ volatile("vctzlsbb %0, %1\n\t" : "=r" (len) : "v" (vc)) -# define zng_vec_vclzlsbb(vc, len) __asm__ volatile("vclzlsbb %0, %1\n\t" : "=r" (len) : "v" (vc)) -#else +#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 12) +#if BYTE_ORDER == LITTLE_ENDIAN # define zng_vec_vctzlsbb(vc, len) len = __builtin_vec_vctzlsbb(vc) -# define zng_vec_vclzlsbb(vc, len) len = __builtin_vec_vclzlsbb(vc) +#else +# define zng_vec_vctzlsbb(vc, len) len = __builtin_vec_vclzlsbb(vc) +#endif +#else +# define zng_vec_vctzlsbb(vc, len) len = vec_cntlz_lsbb(vc) #endif static inline uint32_t compare256_power9_static(const uint8_t *src0, const uint8_t *src1) { @@ -34,11 +36,7 @@ static inline uint32_t compare256_power9_static(const uint8_t *src0, const uint8 /* Since the index of matching bytes will contain only zeroes * on vc (since we used cmpne), counting the number of consecutive * bytes where LSB == 0 is the same as counting the length of the match. */ -#if BYTE_ORDER == LITTLE_ENDIAN zng_vec_vctzlsbb(vc, cmplen); -#else - zng_vec_vclzlsbb(vc, cmplen); -#endif if (cmplen != 16) return len + cmplen; diff --git a/arch/power/power_features.c b/arch/power/power_features.c index 003a4c6e3c..f73503734b 100644 --- a/arch/power/power_features.c +++ b/arch/power/power_features.c @@ -34,9 +34,13 @@ void Z_INTERNAL power_check_features(struct power_cpu_features *features) { hwcap2 = getauxval(AT_HWCAP2); #endif +#ifdef POWER8_VSX if (hwcap2 & PPC_FEATURE2_ARCH_2_07) features->has_arch_2_07 = 1; +#endif +#ifdef POWER9 if (hwcap2 & PPC_FEATURE2_ARCH_3_00) features->has_arch_3_00 = 1; #endif +#endif } diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index e9e6d36da8..9cbc590898 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -393,8 +393,18 @@ macro(check_power9_intrinsics) # Check if we have what we need for POWER9 optimizations set(CMAKE_REQUIRED_FLAGS "${POWER9FLAG} ${NATIVEFLAG}") check_c_source_compiles( - "int main() { - return 0; + "#include + #ifdef __FreeBSD__ + #include + #endif + int main() { + #ifdef __FreeBSD__ + unsigned long hwcap; + elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE2_ARCH_3_00); + #else + return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00); + #endif }" HAVE_POWER9_INTRIN ) diff --git a/cmake/toolchain-powerpc64-clang.cmake b/cmake/toolchain-powerpc64-clang.cmake new file mode 100644 index 0000000000..f986796f6b --- /dev/null +++ b/cmake/toolchain-powerpc64-clang.cmake @@ -0,0 +1,16 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR ppc64) +set(CMAKE_SYSTEM_VERSION 1) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_C_COMPILER_TARGET powerpc64-linux-gnu) +set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_CXX_COMPILER_TARGET powerpc64-linux-gnu) + +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64 -cpu power9 -L /usr/${CMAKE_C_COMPILER_TARGET}/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/cmake/toolchain-powerpc64le-clang.cmake b/cmake/toolchain-powerpc64le-clang.cmake new file mode 100644 index 0000000000..b3423c590d --- /dev/null +++ b/cmake/toolchain-powerpc64le-clang.cmake @@ -0,0 +1,16 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR ppc64le) +set(CMAKE_SYSTEM_VERSION 1) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_C_COMPILER_TARGET powerpc64le-linux-gnu) +set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_CXX_COMPILER_TARGET powerpc64le-linux-gnu) + +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64le -cpu power9 -L /usr/${CMAKE_C_COMPILER_TARGET}/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/configure b/configure index a7ecc370b6..9c0ea34314 100755 --- a/configure +++ b/configure @@ -1383,7 +1383,19 @@ EOF check_power9_intrinsics() { # Check whether features needed by POWER9 optimisations are available cat > $test.c << EOF -int main() { return 0; } +#ifdef __FreeBSD__ +#include +#endif +#include +int main() { +#ifdef __FreeBSD__ + unsigned long hwcap; + elf_aux_info(AT_HWCAP2, &hwcap, sizeof(hwcap)); + return (hwcap & PPC_FEATURE2_ARCH_3_00); +#else + return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_3_00); +#endif +} EOF if test $buildpower9 -eq 1 && try $CC -c $CFLAGS -mcpu=power9 $test.c; then HAVE_POWER9_INTRIN=1 From 8f045434d95fc442288d07331c5177c273858c50 Mon Sep 17 00:00:00 2001 From: Andrea Campanella Date: Fri, 16 Jun 2023 12:50:28 +0100 Subject: [PATCH 685/798] Update detect-arch.cmake Add Cortex plaform for ARM --- cmake/detect-arch.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/detect-arch.cmake b/cmake/detect-arch.cmake index 21c237d61a..95f8f45aec 100644 --- a/cmake/detect-arch.cmake +++ b/cmake/detect-arch.cmake @@ -51,7 +51,7 @@ endif() if("${ARCH}" MATCHES "(x86_64|AMD64|i[3-6]86)") set(BASEARCH "x86") set(BASEARCH_X86_FOUND TRUE) -elseif("${ARCH}" MATCHES "(arm(v[0-9])?|aarch64)") +elseif("${ARCH}" MATCHES "(arm(v[0-9])?|aarch64|cortex)") set(BASEARCH "arm") set(BASEARCH_ARM_FOUND TRUE) elseif("${ARCH}" MATCHES "ppc(64(le)?)?|powerpc(64(le)?)?") From 2f4ebe2bb68380366b90f1db1f3c5b32601130a0 Mon Sep 17 00:00:00 2001 From: alexsifivetw Date: Mon, 19 Jun 2023 03:05:11 -0700 Subject: [PATCH 686/798] Optimize slide_hash using RVV --- CMakeLists.txt | 2 +- arch/riscv/slide_hash_rvv.c | 34 ++++++++++++++++++++++++++ cpu_features.h | 3 +++ functable.c | 1 + test/benchmarks/benchmark_slidehash.cc | 4 ++- 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 arch/riscv/slide_hash_rvv.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ef4f239b6b..e92d3826f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -733,7 +733,7 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c) # FIXME: we will not set compile flags for riscv_features.c when # the kernels update hwcap or hwprobe for riscv - set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/compare256_rvv.c) + set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/compare256_rvv.c ${ARCHDIR}/slide_hash_rvv.c) list(APPEND ZLIB_ARCH_SRCS ${RVV_SRCS}) set_property(SOURCE ${RVV_SRCS} PROPERTY COMPILE_FLAGS "${RISCVFLAG} ${NOLTOFLAG}") else() diff --git a/arch/riscv/slide_hash_rvv.c b/arch/riscv/slide_hash_rvv.c new file mode 100644 index 0000000000..1164e89ba2 --- /dev/null +++ b/arch/riscv/slide_hash_rvv.c @@ -0,0 +1,34 @@ +/* slide_hash_rvv.c - RVV version of slide_hash + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef RISCV_RVV + +#include + +#include "../../zbuild.h" +#include "../../deflate.h" + +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { + size_t vl; + while (entries > 0) { + vl = __riscv_vsetvl_e16m4(entries); + vuint16m4_t v_tab = __riscv_vle16_v_u16m4(table, vl); + vuint16m4_t v_diff = __riscv_vsub_vx_u16m4(v_tab, wsize, vl); + vbool4_t mask = __riscv_vmsltu_vx_u16m4_b4(v_tab, wsize, vl); + v_tab = __riscv_vmerge_vxm_u16m4(v_diff, 0, mask, vl); + __riscv_vse16_v_u16m4(table, v_tab, vl); + table += vl, entries -= vl; + } +} + +Z_INTERNAL void slide_hash_rvv(deflate_state *s) { + uint16_t wsize = (uint16_t)s->w_size; + + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); +} + +#endif // RISCV_RVV diff --git a/cpu_features.h b/cpu_features.h index fb43d90a26..f47ddf0d48 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -267,6 +267,9 @@ extern void slide_hash_vmx(deflate_state *s); #if defined(POWER8_VSX) extern void slide_hash_power8(deflate_state *s); #endif +#if defined(RISCV_RVV) +extern void slide_hash_rvv(deflate_state *s); +#endif #ifdef X86_AVX2 extern void slide_hash_avx2(deflate_state *s); #endif diff --git a/functable.c b/functable.c index 60d4137b37..449edaa0b8 100644 --- a/functable.c +++ b/functable.c @@ -208,6 +208,7 @@ static void init_functable(void) { ft.compare256 = &compare256_rvv; ft.longest_match = &longest_match_rvv; ft.longest_match_slow = &longest_match_slow_rvv; + ft.slide_hash = &slide_hash_rvv; } #endif diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index 238cc1f658..b5ab456161 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -77,7 +77,9 @@ BENCHMARK_SLIDEHASH(power8, slide_hash_power8, test_cpu_features.power.has_arch_ #ifdef PPC_VMX BENCHMARK_SLIDEHASH(vmx, slide_hash_vmx, test_cpu_features.power.has_altivec); #endif - +#ifdef RISCV_RVV +BENCHMARK_SLIDEHASH(rvv, slide_hash_rvv, test_cpu_features.riscv.has_rvv); +#endif #ifdef X86_SSE2 BENCHMARK_SLIDEHASH(sse2, slide_hash_sse2, test_cpu_features.x86.has_sse2); #endif From e5a4a8ae6b5898689389fc7c874759c9b9328251 Mon Sep 17 00:00:00 2001 From: Fabian Vogt Date: Tue, 27 Jun 2023 09:47:04 +0200 Subject: [PATCH 687/798] Handle complete overlap in chunkcopy_safe Fixes #1525 --- inflate_p.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/inflate_p.h b/inflate_p.h index a007cd05df..eff73876da 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -161,6 +161,11 @@ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, uint64_t len, return out + len; } + /* Complete overlap: Source == destination */ + if (out == from) { + return out + len; + } + /* We are emulating a self-modifying copy loop here. To do this in a way that doesn't produce undefined behavior, * we have to get a bit clever. First if the overlap is such that src falls between dst and dst+len, we can do the * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest From 1b5908b8c99c17c5ceb13abdbdfeb33c7c0a8b89 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 27 Jun 2023 18:52:12 +0300 Subject: [PATCH 688/798] [ARM] Check that we have features.h before detecting float-abi * MacOS/arm64 is known to not have features.h --- CMakeLists.txt | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e92d3826f0..9b420769ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,24 +210,27 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(BASEARCH_ARM_FOUND) if("${ARCH}" MATCHES "arm" AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") # Auto-detect support for ARM floating point ABI - set(CMAKE_REQUIRED_FLAGS -mfloat-abi=softfp) - check_c_source_compiles( - "#include - int main() { return 0; }" - HAVE_FLOATABI_SOFTFP) - if(HAVE_FLOATABI_SOFTFP) - set(FLOATABI -mfloat-abi=softfp) - else() - set(CMAKE_REQUIRED_FLAGS -mfloat-abi=hard) + check_include_file(features.h HAVE_FEATURES_H) + if(HAVE_FEATURES_H) + set(CMAKE_REQUIRED_FLAGS -mfloat-abi=softfp) check_c_source_compiles( "#include int main() { return 0; }" - HAVE_FLOATABI_HARD) - if(HAVE_FLOATABI_HARD) - set(FLOATABI -mfloat-abi=hard) + HAVE_FLOATABI_SOFTFP) + if(HAVE_FLOATABI_SOFTFP) + set(FLOATABI -mfloat-abi=softfp) + else() + set(CMAKE_REQUIRED_FLAGS -mfloat-abi=hard) + check_c_source_compiles( + "#include + int main() { return 0; }" + HAVE_FLOATABI_HARD) + if(HAVE_FLOATABI_HARD) + set(FLOATABI -mfloat-abi=hard) + endif() endif() + set(CMAKE_REQUIRED_FLAGS) endif() - set(CMAKE_REQUIRED_FLAGS) if(FLOATABI) message(STATUS "ARM floating point arch: ${FLOATABI}") add_compile_options(${FLOATABI}) From eace956416883966f0ad8a525c5d284a933fd8f5 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 23 Jun 2023 04:32:58 +0300 Subject: [PATCH 689/798] Allow re-enabling @rpath on OS/X when using relative install prefix --- CMakeLists.txt | 23 ++++++++++++++++++++--- configure | 7 ++++++- test/pkgcheck.sh | 19 +++++++++++-------- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b420769ea..420a5c78d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -966,8 +966,15 @@ else() set(PC_INC_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") endif() +if(APPLE) + option(WITH_RPATH "Enable RPATH for shared library" OFF) +endif() if(NOT IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") - set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") + if(APPLE AND WITH_RPATH) + set(PC_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") + else() + set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") + endif() elseif(LIBDIR_POS EQUAL 0) string(SUBSTRING "${CMAKE_INSTALL_LIBDIR}" "${INSTALL_PREFIX_LEN}" "-1" LIBDIR_RELATIVE) set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${LIBDIR_RELATIVE}") @@ -1135,9 +1142,11 @@ if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) if(NOT APPLE) set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.map\"") + elseif(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}" OR NOT WITH_RPATH) + # Match configure/make's behavior (i.e. don't use @rpath on mac when using absolute path). + set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "@rpath/${CMAKE_INSTALL_FULL_LIBDIR}") else() - # Match configure/make's behavior (i.e. don't use @rpath on mac). - set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}") + set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "@rpath/${CMAKE_INSTALL_LIBDIR}") endif() endif() if(MSYS) @@ -1174,6 +1183,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h.in configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gzread.c.in ${CMAKE_CURRENT_BINARY_DIR}/gzread.c @ONLY) +# Fix install directory after generating zlib.pc/zlib-ng.pc +if (NOT IS_ABSOLUTE CMAKE_INSTALL_LIBDIR AND WITH_RPATH) + set(CMAKE_INSTALL_LIBDIR "/${CMAKE_INSTALL_LIBDIR}") +endif() if (NOT ZLIB_SYMBOL_PREFIX STREQUAL "") add_feature_info(ZLIB_SYMBOL_PREFIX ON "Publicly exported symbols have a custom prefix") @@ -1273,4 +1286,8 @@ endif() add_feature_info(INSTALL_UTILS INSTALL_UTILS "Copy minigzip and minideflate during install") +if(APPLE) + add_feature_info(WITH_RPATH WITH_RPATH "Enable RPATH for shared library") +endif() + FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) diff --git a/configure b/configure index 9c0ea34314..8714590e52 100755 --- a/configure +++ b/configure @@ -513,7 +513,12 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then SHAREDLIBM=${LIBNAME}.$VER1$shared_ext SHAREDTARGET=$SHAREDLIBV LDSHARED=${LDSHARED-"$cc"} - LDSHAREDFLAGS="-dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3" + case ${libdir} in + /*) + LDSHAREDFLAGS="-dynamiclib -install_name ${libdir}/${SHAREDLIBM} -compatibility_version ${VER1} -current_version ${VER3}" ;; + *) + LDSHAREDFLAGS="-dynamiclib -install_name @rpath/${libdir}/${SHAREDLIBM} -compatibility_version ${VER1} -current_version ${VER3}" ;; + esac if libtool -V 2>&1 | grep Apple > /dev/null; then AR="libtool" else diff --git a/test/pkgcheck.sh b/test/pkgcheck.sh index 87a4e61efd..629f98aded 100644 --- a/test/pkgcheck.sh +++ b/test/pkgcheck.sh @@ -47,10 +47,6 @@ _EOF_ set -ex -# Caller can also set CMAKE_ARGS or CONFIGURE_ARGS if desired -CMAKE_ARGS="-DCMAKE_INSTALL_LIBDIR=lib ${CMAKE_ARGS}" -CONFIGURE_ARGS=${CONFIGURE_ARGS} - case "$1" in --zlib-compat) suffix="" @@ -85,6 +81,11 @@ Darwin) sysctl -n machdep.cpu.features sysctl -n machdep.cpu.leaf7_features sysctl -n machdep.cpu.extfeatures + CMAKE_ARGS="-DCMAKE_INSTALL_LIBDIR=lib -DPKGCONFIG_INSTALL_DIR=/lib/pkgconfig -DWITH_RPATH=on ${CMAKE_ARGS}" + CONFIGURE_ARGS="--libdir=lib ${CONFIGURE_ARGS}" + ;; +*) + CMAKE_ARGS="-DCMAKE_INSTALL_LIBDIR=lib ${CMAKE_ARGS}" ;; esac @@ -117,7 +118,7 @@ cd .. # Original build system rm -rf btmp1 pkgtmp1 mkdir btmp1 pkgtmp1 -export DESTDIR=$(pwd)/pkgtmp1 +export DESTDIR=$(pwd)/pkgtmp1/ cd btmp1 case $(uname) in Darwin) @@ -130,13 +131,15 @@ cd btmp1 cd .. repack_ar() { - if ! cmp --silent pkgtmp1/usr/local/lib/libz$suffix.a pkgtmp2/usr/local/lib/libz$suffix.a + archive1=$(cd pkgtmp1; find . -type f -name '*.a'; cd ..) + archive2=$(cd pkgtmp2; find . -type f -name '*.a'; cd ..) + if ! cmp --silent pkgtmp1/$archive1 pkgtmp2/$archive2 then echo "libz$suffix.a does not match. Probably filenames differ (.o vs .c.o). Unpacking and renaming..." # Note: %% is posix shell syntax meaning "Remove Largest Suffix Pattern", see # https://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02 - cd pkgtmp1; ar x usr/local/lib/libz$suffix.a; rm usr/local/lib/libz$suffix.a; cd .. - cd pkgtmp2; ar x usr/local/lib/libz$suffix.a; rm usr/local/lib/libz$suffix.a; for a in *.c.o; do mv $a ${a%%.c.o}.o; done; cd .. + cd pkgtmp1; ar x $archive1; rm $archive1; cd .. + cd pkgtmp2; ar x $archive2; rm $archive2; for a in *.c.o; do mv $a ${a%%.c.o}.o; done; cd .. # Also, remove __.SYMDEF SORTED if present, as it has those funky .c.o names embedded in it. rm -f pkgtmp[12]/__.SYMDEF\ SORTED fi From cf89cf35037f152ce7adfeca864656de5d33ea1e Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Wed, 28 Jun 2023 17:49:17 +0200 Subject: [PATCH 690/798] 2.1.3 Release --- Makefile.in | 2 +- zlib-ng.h.in | 6 +++--- zlib.h.in | 6 +++--- zutil.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.in b/Makefile.in index deb3ebcd82..b7b7e644e6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.1.2 +VER=2.1.3 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 2abd320222..8ec2f04a55 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -48,11 +48,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.2" -#define ZLIBNG_VERNUM 0x020102F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.3" +#define ZLIBNG_VERNUM 0x020103F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 2 +#define ZLIBNG_VER_REVISION 3 #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ diff --git a/zlib.h.in b/zlib.h.in index 6788bf7781..71f114a24f 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -49,11 +49,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.2" -#define ZLIBNG_VERNUM 0x020102F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.3" +#define ZLIBNG_VERNUM 0x020103F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 2 +#define ZLIBNG_VER_REVISION 3 #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ diff --git a/zutil.c b/zutil.c index 9ab667df8d..7893916150 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char PREFIX3(vstring)[] = - " zlib-ng 2.1.2"; + " zlib-ng 2.1.3"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From 65fedde613138d0279215125e1942c71417fd141 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sat, 1 Jul 2023 14:52:22 +0300 Subject: [PATCH 691/798] Fix distclean target in Makefile.in --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index b7b7e644e6..316b742f1a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -373,7 +373,7 @@ maintainer-clean: distclean distclean: clean @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) distclean; fi @if [ -f test/Makefile ]; then $(MAKE) -C test distclean; fi - rm -f $(PKGFILE) configure.log zconf.h zconf.h.cmakein zlib$(SUFFIX).h zlib_name_mangling$(SUFFIX)}.h *.pc + rm -f $(PKGFILE) configure.log zconf.h zconf.h.cmakein zlib$(SUFFIX).h zlib_name_mangling$(SUFFIX).h *.pc gzread.c -@rm -f .DS_Store # Reset Makefile if building inside source tree @if [ -f Makefile.in ]; then \ From e23130bdead4a910ca7e4eb44be48ae2c4ccd523 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Thu, 6 Jul 2023 13:49:58 +0200 Subject: [PATCH 692/798] Define an empty __msan_unpoison() without Z_MEMORY_SANITIZER Currently all the usages of __msan_unpoison() have to be guarded by "#ifdef Z_MEMORY_SANITIZER". Simplify things by defining an empty __msan_unpoison() when the code is compiled without MSan. --- arch/arm/chunkset_neon.c | 2 -- arch/s390/dfltcc_detail.h | 4 ---- arch/x86/chunkset_avx2.c | 2 -- arch/x86/chunkset_ssse3.c | 2 -- zbuild.h | 4 ++++ 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 1890c91356..7891eabd2a 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -68,10 +68,8 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; *chunk_rem = lut_rem.remval; -#ifdef Z_MEMORY_SANITIZER /* See note in chunkset_ssse3.c for why this is ok */ __msan_unpoison(buf + dist, 16 - dist); -#endif /* This version of table is only available on aarch64 */ #if defined(_M_ARM64) || defined(__aarch64__) diff --git a/arch/s390/dfltcc_detail.h b/arch/s390/dfltcc_detail.h index 354c2f5550..362d94c337 100644 --- a/arch/s390/dfltcc_detail.h +++ b/arch/s390/dfltcc_detail.h @@ -166,9 +166,7 @@ static inline dfltcc_cc dfltcc(int fn, void *param, unsigned char **op1, size_t *len1, z_const unsigned char **op2, size_t *len2, void *hist) { unsigned char *t2 = op1 ? *op1 : NULL; -#ifdef Z_MEMORY_SANITIZER unsigned char *orig_t2 = t2; -#endif size_t t3 = len1 ? *len1 : 0; z_const unsigned char *t4 = op2 ? *op2 : NULL; size_t t5 = len2 ? *len2 : 0; @@ -203,7 +201,6 @@ static inline dfltcc_cc dfltcc(int fn, void *param, : "cc", "memory"); t2 = r2; t3 = r3; t4 = r4; t5 = r5; -#ifdef Z_MEMORY_SANITIZER switch (fn & DFLTCC_FN_MASK) { case DFLTCC_QAF: __msan_unpoison(param, DFLTCC_SIZEOF_QAF); @@ -220,7 +217,6 @@ static inline dfltcc_cc dfltcc(int fn, void *param, __msan_unpoison(orig_t2, t2 - orig_t2); break; } -#endif if (op1) *op1 = t2; diff --git a/arch/x86/chunkset_avx2.c b/arch/x86/chunkset_avx2.c index f309878b35..70620b9154 100644 --- a/arch/x86/chunkset_avx2.c +++ b/arch/x86/chunkset_avx2.c @@ -84,10 +84,8 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t * GPRs to begin with the 256 bit load is _probably_ just as inexpensive */ *chunk_rem = lut_rem.remval; -#ifdef Z_MEMORY_SANITIZER /* See note in chunkset_ssse3.c for why this is ok */ __msan_unpoison(buf + dist, 32 - dist); -#endif if (dist < 16) { /* This simpler case still requires us to shuffle in 128 bit lanes, so we must apply a static offset after diff --git a/arch/x86/chunkset_ssse3.c b/arch/x86/chunkset_ssse3.c index 0bd6263859..c06d1b37bd 100644 --- a/arch/x86/chunkset_ssse3.c +++ b/arch/x86/chunkset_ssse3.c @@ -68,14 +68,12 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; __m128i perm_vec, ret_vec; -#ifdef Z_MEMORY_SANITIZER /* Important to note: * This is _not_ to subvert the memory sanitizer but to instead unpoison some * bytes we willingly and purposefully load uninitialized that we swizzle over * in a vector register, anyway. If what we assume is wrong about what is used, * the memory sanitizer will still usefully flag it */ __msan_unpoison(buf + dist, 16 - dist); -#endif ret_vec = _mm_loadu_si128((__m128i*)buf); *chunk_rem = lut_rem.remval; diff --git a/zbuild.h b/zbuild.h index 525a34d8d8..d9559591b4 100644 --- a/zbuild.h +++ b/zbuild.h @@ -245,4 +245,8 @@ # endif #endif +#ifndef Z_MEMORY_SANITIZER +# define __msan_unpoison(a, size) do { Z_UNUSED(a); Z_UNUSED(size); } while (0) +#endif + #endif From 70da27b86ed5b74369f00ca033d9651c37a17f7e Mon Sep 17 00:00:00 2001 From: Leslie Zhai Date: Thu, 13 Jul 2023 19:39:22 +0800 Subject: [PATCH 693/798] Initial loongarch port --- cmake/detect-arch.c | 4 ++++ cmake/detect-arch.cmake | 3 +++ 2 files changed, 7 insertions(+) diff --git a/cmake/detect-arch.c b/cmake/detect-arch.c index ff1a05a253..903ae5f29f 100644 --- a/cmake/detect-arch.c +++ b/cmake/detect-arch.c @@ -101,6 +101,10 @@ #error archfound riscv32 #endif +// LOONGARCH +#elif defined(__loongarch_lp64) + #error archfound loongarch64 + // Emscripten (WebAssembly) #elif defined(__EMSCRIPTEN__) #error archfound wasm32 diff --git a/cmake/detect-arch.cmake b/cmake/detect-arch.cmake index 95f8f45aec..706d13f877 100644 --- a/cmake/detect-arch.cmake +++ b/cmake/detect-arch.cmake @@ -90,6 +90,9 @@ elseif("${ARCH}" MATCHES "rs6000") elseif("${ARCH}" MATCHES "riscv(32|64)") set(BASEARCH "riscv") set(BASEARCH_RISCV_FOUND TRUE) +elseif("${ARCH}" MATCHES "loongarch64") + set(BASEARCH "loongarch") + set(BASEARCH_LOONGARCH_FOUND TRUE) elseif("${ARCH}" MATCHES "wasm32") set(BASEARCH "wasm32") set(BASEARCH_WASM32_FOUND TRUE) From 8976caa3f066458b26ddb309e201d887fea49730 Mon Sep 17 00:00:00 2001 From: David Korth Date: Sat, 15 Jul 2023 10:13:20 -0400 Subject: [PATCH 694/798] Handle ARM64EC as ARM64. ARM64EC is a new ARM64 variant introduced in Windows 11 that uses an ABI similar to AMD64, which allows for better interoperability with emulated AMD64 applications. When enabled in MSVC, it defines _M_AMD64 and _M_ARM64EC, but not _M_ARM64, so we need to check for _M_ARM64EC. --- arch/arm/arm_features.c | 4 ++-- arch/arm/chunkset_neon.c | 2 +- arch/arm/crc32_acle.c | 2 +- arch/arm/neon_intrins.h | 4 ++-- cmake/detect-arch.c | 2 +- cmake/detect-arch.cmake | 2 +- cmake/detect-intrinsics.cmake | 4 ++-- configure | 4 ++-- fallback_builtins.h | 2 +- zbuild.h | 2 +- zendian.h | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/arm/arm_features.c b/arch/arm/arm_features.c index 7394351fa1..8ef8200099 100644 --- a/arch/arm/arm_features.c +++ b/arch/arm/arm_features.c @@ -45,7 +45,7 @@ static int arm_has_crc32() { } /* AArch64 has neon. */ -#if !defined(__aarch64__) && !defined(_M_ARM64) +#if !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) static inline int arm_has_neon() { #if defined(__linux__) && defined(ARM_AUXV_HAS_NEON) # ifdef HWCAP_ARM_NEON @@ -73,7 +73,7 @@ static inline int arm_has_neon() { #endif void Z_INTERNAL arm_check_features(struct arm_cpu_features *features) { -#if defined(__aarch64__) || defined(_M_ARM64) +#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) features->has_neon = 1; /* always available */ #else features->has_neon = arm_has_neon(); diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 7891eabd2a..f9a444b068 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -72,7 +72,7 @@ static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t __msan_unpoison(buf + dist, 16 - dist); /* This version of table is only available on aarch64 */ -#if defined(_M_ARM64) || defined(__aarch64__) +#if defined(_M_ARM64) || defined(_M_ARM64EC) || defined(__aarch64__) uint8x16_t ret_vec = vld1q_u8(buf); uint8x16_t perm_vec = vld1q_u8(permute_table + lut_rem.idx); diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index a4e54d7182..0c9b9b6596 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -33,7 +33,7 @@ Z_INTERNAL uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { buf4 = (const uint32_t *) buf; } -#if defined(__aarch64__) || defined(_M_ARM64) +#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) if ((len >= sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { c = __crc32w(c, *buf4++); len -= sizeof(uint32_t); diff --git a/arch/arm/neon_intrins.h b/arch/arm/neon_intrins.h index d6b57f6414..478697a6de 100644 --- a/arch/arm/neon_intrins.h +++ b/arch/arm/neon_intrins.h @@ -1,13 +1,13 @@ #ifndef ARM_NEON_INTRINS_H #define ARM_NEON_INTRINS_H -#ifdef _M_ARM64 +#if defined(_M_ARM64) || defined(_M_ARM64EC) # include #else # include #endif -#if defined(ARM_NEON) && !defined(__aarch64__) && !defined(_M_ARM64) +#if defined(ARM_NEON) && !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) /* Compatibility shim for the _high family of functions */ #define vmull_high_u8(a, b) vmull_u8(vget_high_u8(a), vget_high_u8(b)) #define vmlal_high_u8(a, b, c) vmlal_u8(a, vget_high_u8(b), vget_high_u8(c)) diff --git a/cmake/detect-arch.c b/cmake/detect-arch.c index 903ae5f29f..92590182c2 100644 --- a/cmake/detect-arch.c +++ b/cmake/detect-arch.c @@ -12,7 +12,7 @@ #error archfound i686 // ARM -#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) +#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC) #error archfound aarch64 #elif defined(__arm__) || defined(__arm) || defined(_M_ARM) || defined(__TARGET_ARCH_ARM) #if defined(__ARM64_ARCH_8__) || defined(__ARMv8__) || defined(__ARMv8_A__) diff --git a/cmake/detect-arch.cmake b/cmake/detect-arch.cmake index 706d13f877..dfdc6013ce 100644 --- a/cmake/detect-arch.cmake +++ b/cmake/detect-arch.cmake @@ -13,7 +13,7 @@ elseif(MSVC) set(ARCH "x86_64") elseif("${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARM" OR "${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARMV7") set(ARCH "arm") - elseif ("${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARM64") + elseif ("${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARM64" OR "${MSVC_C_ARCHITECTURE_ID}" STREQUAL "ARM64EC") set(ARCH "aarch64") endif() elseif(EMSCRIPTEN) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 9cbc590898..b0b0516e37 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -176,7 +176,7 @@ macro(check_neon_compiler_flag) # Check whether compiler supports NEON flag set(CMAKE_REQUIRED_FLAGS "${NEONFLAG} ${NATIVEFLAG}") check_c_source_compiles( - "#ifdef _M_ARM64 + "#if defined(_M_ARM64) || defined(_M_ARM64EC) # include #else # include @@ -199,7 +199,7 @@ macro(check_neon_ld4_intrinsics) # Check whether compiler supports loading 4 neon vecs into a register range set(CMAKE_REQUIRED_FLAGS "${NEONFLAG}") check_c_source_compiles( - "#ifdef _M_ARM64 + "#if defined(_M_ARM64) || defined(_M_ARM64EC) # include #else # include diff --git a/configure b/configure index 8714590e52..29a64badfd 100755 --- a/configure +++ b/configure @@ -1200,7 +1200,7 @@ EOF check_neon_compiler_flag() { # Check whether -mfpu=neon is available on ARM processors. cat > $test.c << EOF -#ifdef _M_ARM64 +#if defined(_M_ARM64) || defined(_M_ARM64EC) # include #else # include @@ -1225,7 +1225,7 @@ check_neon_ld4_intrinsics() { fi fi cat > $test.c << EOF -#ifdef _M_ARM64 +#if defined(_M_ARM64) || defined(_M_ARM64EC) # include #else # include diff --git a/fallback_builtins.h b/fallback_builtins.h index 447f9ac193..6e8ed9f400 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -2,7 +2,7 @@ #define FALLBACK_BUILTINS_H #if defined(_MSC_VER) && !defined(__clang__) -#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM64) +#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) #include #ifdef X86_FEATURES diff --git a/zbuild.h b/zbuild.h index d9559591b4..2f9dd6b1c0 100644 --- a/zbuild.h +++ b/zbuild.h @@ -221,7 +221,7 @@ # elif defined(__i386__) || defined(__i486__) || defined(__i586__) || \ defined(__i686__) || defined(_X86_) || defined(_M_IX86) # define UNALIGNED_OK -# elif defined(__aarch64__) || defined(_M_ARM64) +# elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) # if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) # define UNALIGNED_OK # define UNALIGNED64_OK diff --git a/zendian.h b/zendian.h index 3fdb13041a..28177a609f 100644 --- a/zendian.h +++ b/zendian.h @@ -27,7 +27,7 @@ #elif defined(_WIN32) # define LITTLE_ENDIAN 1234 # define BIG_ENDIAN 4321 -# if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined (_M_ARM) || defined (_M_ARM64) +# if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined (_M_ARM) || defined (_M_ARM64) || defined (_M_ARM64EC) # define BYTE_ORDER LITTLE_ENDIAN # else # error Unknown endianness! From 6eed7416ed38a7740da77e86f2e5be5e7bce586d Mon Sep 17 00:00:00 2001 From: alexsifivetw Date: Sat, 1 Jul 2023 10:40:06 -0700 Subject: [PATCH 695/798] Optimize adler32 using rvv --- CMakeLists.txt | 2 +- arch/riscv/adler32_rvv.c | 110 ++++++++++++++++++++++ cpu_features.h | 3 + functable.c | 1 + test/benchmarks/benchmark_adler32.cc | 4 + test/benchmarks/benchmark_adler32_copy.cc | 5 + test/test_adler32.cc | 2 + 7 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 arch/riscv/adler32_rvv.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 420a5c78d4..003e66db75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -736,7 +736,7 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c) # FIXME: we will not set compile flags for riscv_features.c when # the kernels update hwcap or hwprobe for riscv - set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/compare256_rvv.c ${ARCHDIR}/slide_hash_rvv.c) + set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/adler32_rvv.c ${ARCHDIR}/compare256_rvv.c ${ARCHDIR}/slide_hash_rvv.c) list(APPEND ZLIB_ARCH_SRCS ${RVV_SRCS}) set_property(SOURCE ${RVV_SRCS} PROPERTY COMPILE_FLAGS "${RISCVFLAG} ${NOLTOFLAG}") else() diff --git a/arch/riscv/adler32_rvv.c b/arch/riscv/adler32_rvv.c new file mode 100644 index 0000000000..c2ef40c16f --- /dev/null +++ b/arch/riscv/adler32_rvv.c @@ -0,0 +1,110 @@ +/* adler32_rvv.c - RVV version of adler32 + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef RISCV_RVV + +#include +#include + +#include "../../zbuild.h" +#include "../../adler32_p.h" + +Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) { + /* split Adler-32 into component sums */ + uint32_t sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + return adler32_len_1(adler, buf, sum2); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + return adler32_len_16(adler, buf, len, sum2); + } + + size_t left = len; + size_t vl = __riscv_vsetvlmax_e8m1(); + vl = vl > 256 ? 256 : vl; + vuint32m4_t v_buf32_accu = __riscv_vmv_v_x_u32m4(0, vl); + vuint32m4_t v_adler32_prev_accu = __riscv_vmv_v_x_u32m4(0, vl); + vuint16m2_t v_buf16_accu; + + /* + * We accumulate 8-bit data, and to prevent overflow, we have to use a 32-bit accumulator. + * However, adding 8-bit data into a 32-bit accumulator isn't efficient. We use 16-bit & 32-bit + * accumulators to boost performance. + * + * The block_size is the largest multiple of vl that <= 256, because overflow would occur when + * vl > 256 (255 * 256 <= UINT16_MAX). + * + * We accumulate 8-bit data into a 16-bit accumulator and then + * move the data into the 32-bit accumulator at the last iteration. + */ + size_t block_size = (256 / vl) * vl; + while (left >= block_size) { + v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); + size_t subprob = block_size; + while (subprob > 0) { + vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(buf, vl); + v_adler32_prev_accu = __riscv_vwaddu_wv_u32m4(v_adler32_prev_accu, v_buf16_accu, vl); + v_buf16_accu = __riscv_vwaddu_wv_u16m2(v_buf16_accu, v_buf8, vl); + buf += vl; + subprob -= vl; + } + v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, block_size / vl, v_buf32_accu, vl); + v_buf32_accu = __riscv_vwaddu_wv_u32m4(v_buf32_accu, v_buf16_accu, vl); + left -= block_size; + } + v_adler32_prev_accu = __riscv_vremu_vx_u32m4(v_adler32_prev_accu, BASE, vl); + + v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); + size_t res = left; + while (left >= vl) { + vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(buf, vl); + v_adler32_prev_accu = __riscv_vwaddu_wv_u32m4(v_adler32_prev_accu, v_buf16_accu, vl); + v_buf16_accu = __riscv_vwaddu_wv_u16m2(v_buf16_accu, v_buf8, vl); + buf += vl; + left -= vl; + } + v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, res / vl, v_buf32_accu, vl); + v_buf32_accu = __riscv_vwaddu_wv_u32m4(v_buf32_accu, v_buf16_accu, vl); + + vuint32m4_t v_seq = __riscv_vid_v_u32m4(vl); + vuint32m4_t v_rev_seq = __riscv_vrsub_vx_u32m4(v_seq, vl, vl); + vuint32m4_t v_sum32_accu = __riscv_vmul_vv_u32m4(v_buf32_accu, v_rev_seq, vl); + + v_sum32_accu = __riscv_vadd_vv_u32m4(v_sum32_accu, __riscv_vmul_vx_u32m4(v_adler32_prev_accu, vl, vl), vl); + + vuint32m1_t v_sum2_sum = __riscv_vmv_s_x_u32m1(0, vl); + v_sum2_sum = __riscv_vredsum_vs_u32m4_u32m1(v_sum32_accu, v_sum2_sum, vl); + uint32_t sum2_sum = __riscv_vmv_x_s_u32m1_u32(v_sum2_sum); + + sum2 += (sum2_sum + adler * (len - left)); + + vuint32m1_t v_adler_sum = __riscv_vmv_s_x_u32m1(0, vl); + v_adler_sum = __riscv_vredsum_vs_u32m4_u32m1(v_buf32_accu, v_adler_sum, vl); + uint32_t adler_sum = __riscv_vmv_x_s_u32m1_u32(v_adler_sum); + + adler += adler_sum; + + while (left--) { + adler += *buf++; + sum2 += adler; + } + + sum2 %= BASE; + adler %= BASE; + + return adler | (sum2 << 16); +} + +#endif // RISCV_RVV diff --git a/cpu_features.h b/cpu_features.h index f47ddf0d48..870f6e656c 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -50,6 +50,9 @@ extern uint32_t adler32_neon(uint32_t adler, const uint8_t *buf, size_t len); #ifdef PPC_VMX extern uint32_t adler32_vmx(uint32_t adler, const uint8_t *buf, size_t len); #endif +#ifdef RISCV_RVV +extern uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len); +#endif #ifdef X86_SSSE3 extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len); #endif diff --git a/functable.c b/functable.c index 449edaa0b8..6e195aceaf 100644 --- a/functable.c +++ b/functable.c @@ -205,6 +205,7 @@ static void init_functable(void) { // RISCV - RVV #ifdef RISCV_RVV if (cf.riscv.has_rvv) { + ft.adler32 = &adler32_rvv; ft.compare256 = &compare256_rvv; ft.longest_match = &longest_match_rvv; ft.longest_match_slow = &longest_match_slow_rvv; diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index 5b0b65d67b..0be3a707a5 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -75,6 +75,10 @@ BENCHMARK_ADLER32(vmx, adler32_vmx, test_cpu_features.power.has_altivec); BENCHMARK_ADLER32(power8, adler32_power8, test_cpu_features.power.has_arch_2_07); #endif +#ifdef RISCV_RVV +BENCHMARK_ADLER32(rvv, adler32_rvv, test_cpu_features.riscv.has_rvv); +#endif + #ifdef X86_SSSE3 BENCHMARK_ADLER32(ssse3, adler32_ssse3, test_cpu_features.x86.has_ssse3); #endif diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc index cbee780b76..9a4a5ff420 100644 --- a/test/benchmarks/benchmark_adler32_copy.cc +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -100,6 +100,11 @@ BENCHMARK_ADLER32_BASELINE_COPY(vmx_copy_baseline, adler32_vmx, test_cpu_feature BENCHMARK_ADLER32_BASELINE_COPY(power8, adler32_power8, test_cpu_features.power.has_arch_2_07); #endif +#ifdef RISCV_RVV +//BENCHMARK_ADLER32_COPY(rvv, adler32_rvv, test_cpu_features.riscv.has_rvv); +BENCHMARK_ADLER32_BASELINE_COPY(rvv, adler32_rvv, test_cpu_features.riscv.has_rvv); +#endif + #ifdef X86_SSE42 BENCHMARK_ADLER32_BASELINE_COPY(sse42_baseline, adler32_ssse3, test_cpu_features.x86.has_ssse3); BENCHMARK_ADLER32_COPY(sse42, adler32_fold_copy_sse42, test_cpu_features.x86.has_sse42); diff --git a/test/test_adler32.cc b/test/test_adler32.cc index 4dfe63f203..1ed6e22486 100644 --- a/test/test_adler32.cc +++ b/test/test_adler32.cc @@ -370,6 +370,8 @@ TEST_ADLER32(neon, adler32_neon, test_cpu_features.arm.has_neon) TEST_ADLER32(power8, adler32_power8, test_cpu_features.power.has_arch_2_07) #elif defined(PPC_VMX) TEST_ADLER32(vmx, adler32_vmx, test_cpu_features.power.has_altivec) +#elif defined(RISCV_RVV) +TEST_ADLER32(rvv, adler32_rvv, test_cpu_features.riscv.has_rvv) #endif #ifdef X86_SSSE3 From aaac4c186834959ecd7b242f67266ca458752894 Mon Sep 17 00:00:00 2001 From: alexsifivetw Date: Tue, 11 Jul 2023 05:47:29 -0700 Subject: [PATCH 696/798] Do mod BASE once each block of NMAX size --- arch/riscv/adler32_rvv.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/riscv/adler32_rvv.c b/arch/riscv/adler32_rvv.c index c2ef40c16f..0e78c92875 100644 --- a/arch/riscv/adler32_rvv.c +++ b/arch/riscv/adler32_rvv.c @@ -50,6 +50,8 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) * move the data into the 32-bit accumulator at the last iteration. */ size_t block_size = (256 / vl) * vl; + size_t nmax_limit = (NMAX / block_size); + size_t cnt = 0; while (left >= block_size) { v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); size_t subprob = block_size; @@ -63,9 +65,13 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, block_size / vl, v_buf32_accu, vl); v_buf32_accu = __riscv_vwaddu_wv_u32m4(v_buf32_accu, v_buf16_accu, vl); left -= block_size; + /* do modulo once each block of NMAX size */ + if (++cnt >= nmax_limit) { + v_adler32_prev_accu = __riscv_vremu_vx_u32m4(v_adler32_prev_accu, BASE, vl); + cnt = 0; + } } - v_adler32_prev_accu = __riscv_vremu_vx_u32m4(v_adler32_prev_accu, BASE, vl); - + /* the left len <= 256 now, we can use 16-bit accum safetly */ v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); size_t res = left; while (left >= vl) { @@ -76,6 +82,7 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) left -= vl; } v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, res / vl, v_buf32_accu, vl); + v_adler32_prev_accu = __riscv_vremu_vx_u32m4(v_adler32_prev_accu, BASE, vl); v_buf32_accu = __riscv_vwaddu_wv_u32m4(v_buf32_accu, v_buf16_accu, vl); vuint32m4_t v_seq = __riscv_vid_v_u32m4(vl); From a339d85c80e0509018cd7e692969f11514ae2067 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Tue, 18 Jul 2023 11:17:03 +0100 Subject: [PATCH 697/798] Move the AVX compatibility functions into a separate file --- arch/x86/adler32_avx2_tpl.h | 2 +- arch/x86/adler32_avx512_tpl.h | 2 +- arch/x86/adler32_avx512_vnni.c | 2 +- arch/x86/crc32_pclmulqdq_tpl.h | 2 +- arch/x86/x86_intrins.h | 87 ++++++++++++++++++++++++++++++++++ fallback_builtins.h | 83 -------------------------------- 6 files changed, 91 insertions(+), 87 deletions(-) create mode 100644 arch/x86/x86_intrins.h diff --git a/arch/x86/adler32_avx2_tpl.h b/arch/x86/adler32_avx2_tpl.h index a94f44b4f9..2104b053e5 100644 --- a/arch/x86/adler32_avx2_tpl.h +++ b/arch/x86/adler32_avx2_tpl.h @@ -7,7 +7,7 @@ #include #include "../../adler32_fold.h" #include "../../adler32_p.h" -#include "../../fallback_builtins.h" +#include "x86_intrins.h" #include "adler32_avx2_p.h" #ifdef X86_SSE42 diff --git a/arch/x86/adler32_avx512_tpl.h b/arch/x86/adler32_avx512_tpl.h index 7546afef5e..d92ad7f665 100644 --- a/arch/x86/adler32_avx512_tpl.h +++ b/arch/x86/adler32_avx512_tpl.h @@ -7,8 +7,8 @@ #include "../../adler32_p.h" #include "../../adler32_fold.h" #include "../../cpu_features.h" -#include "../../fallback_builtins.h" #include +#include "x86_intrins.h" #include "adler32_avx512_p.h" #ifdef X86_AVX512 diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index 8dcc93d050..771f7ebe04 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -12,9 +12,9 @@ #include "../../zbuild.h" #include "../../adler32_p.h" #include "../../cpu_features.h" -#include "../../fallback_builtins.h" #include #include "../../adler32_fold.h" +#include "x86_intrins.h" #include "adler32_avx512_p.h" #include "adler32_avx2_p.h" diff --git a/arch/x86/crc32_pclmulqdq_tpl.h b/arch/x86/crc32_pclmulqdq_tpl.h index 0d66663cb5..05d3b15257 100644 --- a/arch/x86/crc32_pclmulqdq_tpl.h +++ b/arch/x86/crc32_pclmulqdq_tpl.h @@ -28,7 +28,7 @@ #include "../../crc32_fold.h" #include "../../crc32_braid_p.h" -#include "../../fallback_builtins.h" +#include "x86_intrins.h" #include #ifdef X86_VPCLMULQDQ diff --git a/arch/x86/x86_intrins.h b/arch/x86/x86_intrins.h new file mode 100644 index 0000000000..52e1085d66 --- /dev/null +++ b/arch/x86/x86_intrins.h @@ -0,0 +1,87 @@ +#ifndef X86_INTRINS_H +#define X86_INTRINS_H + +/* Unfortunately GCC didn't support these things until version 10. + * Similarly, AppleClang didn't support them in Xcode 9.2 but did in 9.3. + */ +#ifdef __AVX2__ +#include + +#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 10) \ + || (defined(__apple_build_version__) && __apple_build_version__ < 9020039) +static inline __m256i _mm256_zextsi128_si256(__m128i a) { + __m128i r; + __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); + return _mm256_castsi128_si256(r); +} + +#ifdef __AVX512F__ +static inline __m512i _mm512_zextsi128_si512(__m128i a) { + __m128i r; + __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); + return _mm512_castsi128_si512(r); +} +#endif // __AVX512F__ +#endif // gcc/AppleClang version test + +#endif // __AVX2__ + +/* GCC <9 is missing some AVX512 intrinsics. + */ +#ifdef __AVX512F__ +#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 9) +#include + +#define PACK(c0, c1, c2, c3) (((int)(unsigned char)(c0) << 24) | ((int)(unsigned char)(c1) << 16) | \ + ((int)(unsigned char)(c2) << 8) | ((int)(unsigned char)(c3))) + +static inline __m512i _mm512_set_epi8(char __q63, char __q62, char __q61, char __q60, + char __q59, char __q58, char __q57, char __q56, + char __q55, char __q54, char __q53, char __q52, + char __q51, char __q50, char __q49, char __q48, + char __q47, char __q46, char __q45, char __q44, + char __q43, char __q42, char __q41, char __q40, + char __q39, char __q38, char __q37, char __q36, + char __q35, char __q34, char __q33, char __q32, + char __q31, char __q30, char __q29, char __q28, + char __q27, char __q26, char __q25, char __q24, + char __q23, char __q22, char __q21, char __q20, + char __q19, char __q18, char __q17, char __q16, + char __q15, char __q14, char __q13, char __q12, + char __q11, char __q10, char __q09, char __q08, + char __q07, char __q06, char __q05, char __q04, + char __q03, char __q02, char __q01, char __q00) { + return _mm512_set_epi32(PACK(__q63, __q62, __q61, __q60), PACK(__q59, __q58, __q57, __q56), + PACK(__q55, __q54, __q53, __q52), PACK(__q51, __q50, __q49, __q48), + PACK(__q47, __q46, __q45, __q44), PACK(__q43, __q42, __q41, __q40), + PACK(__q39, __q38, __q37, __q36), PACK(__q35, __q34, __q33, __q32), + PACK(__q31, __q30, __q29, __q28), PACK(__q27, __q26, __q25, __q24), + PACK(__q23, __q22, __q21, __q20), PACK(__q19, __q18, __q17, __q16), + PACK(__q15, __q14, __q13, __q12), PACK(__q11, __q10, __q09, __q08), + PACK(__q07, __q06, __q05, __q04), PACK(__q03, __q02, __q01, __q00)); +} + +#undef PACK + +#endif // gcc version test +#endif // __AVX512F__ + +/* Missing zero-extension AVX and AVX512 intrinsics. + * Fixed in Microsoft Visual Studio 2017 version 15.7 + * https://developercommunity.visualstudio.com/t/missing-zero-extension-avx-and-avx512-intrinsics/175737 + */ +#if defined(_MSC_VER) && _MSC_VER < 1914 +#ifdef __AVX2__ +static inline __m256i _mm256_zextsi128_si256(__m128i a) { + return _mm256_inserti128_si256(_mm256_setzero_si256(), a, 0); +} +#endif // __AVX2__ + +#ifdef __AVX512F__ +static inline __m512i _mm512_zextsi128_si512(__m128i a) { + return _mm512_inserti32x4(_mm512_setzero_si512(), a, 0); +} +#endif // __AVX512F__ +#endif // defined(_MSC_VER) && _MSC_VER < 1914 + +#endif // include guard X86_INTRINS_H diff --git a/fallback_builtins.h b/fallback_builtins.h index 6e8ed9f400..79072a1028 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -47,87 +47,4 @@ static __forceinline int __builtin_ctzll(unsigned long long value) { #endif // Microsoft AMD64/IA64/x86/ARM/ARM64 test #endif // _MSC_VER & !clang -/* Unfortunately GCC didn't support these things until version 10. - * Similarly, AppleClang didn't support them in Xcode 9.2 but did in 9.3. - */ -#ifdef __AVX2__ -#include - -#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 10) \ - || (defined(__apple_build_version__) && __apple_build_version__ < 9020039) -static inline __m256i _mm256_zextsi128_si256(__m128i a) { - __m128i r; - __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); - return _mm256_castsi128_si256(r); -} - -#ifdef __AVX512F__ -static inline __m512i _mm512_zextsi128_si512(__m128i a) { - __m128i r; - __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); - return _mm512_castsi128_si512(r); -} -#endif // __AVX512F__ -#endif // gcc/AppleClang version test - -#endif // __AVX2__ - -/* GCC <9 is missing some AVX512 intrinsics. - */ -#ifdef __AVX512F__ -#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 9) -#include - -#define PACK(c0, c1, c2, c3) (((int)(unsigned char)(c0) << 24) | ((int)(unsigned char)(c1) << 16) | \ - ((int)(unsigned char)(c2) << 8) | ((int)(unsigned char)(c3))) - -static inline __m512i _mm512_set_epi8(char __q63, char __q62, char __q61, char __q60, - char __q59, char __q58, char __q57, char __q56, - char __q55, char __q54, char __q53, char __q52, - char __q51, char __q50, char __q49, char __q48, - char __q47, char __q46, char __q45, char __q44, - char __q43, char __q42, char __q41, char __q40, - char __q39, char __q38, char __q37, char __q36, - char __q35, char __q34, char __q33, char __q32, - char __q31, char __q30, char __q29, char __q28, - char __q27, char __q26, char __q25, char __q24, - char __q23, char __q22, char __q21, char __q20, - char __q19, char __q18, char __q17, char __q16, - char __q15, char __q14, char __q13, char __q12, - char __q11, char __q10, char __q09, char __q08, - char __q07, char __q06, char __q05, char __q04, - char __q03, char __q02, char __q01, char __q00) { - return _mm512_set_epi32(PACK(__q63, __q62, __q61, __q60), PACK(__q59, __q58, __q57, __q56), - PACK(__q55, __q54, __q53, __q52), PACK(__q51, __q50, __q49, __q48), - PACK(__q47, __q46, __q45, __q44), PACK(__q43, __q42, __q41, __q40), - PACK(__q39, __q38, __q37, __q36), PACK(__q35, __q34, __q33, __q32), - PACK(__q31, __q30, __q29, __q28), PACK(__q27, __q26, __q25, __q24), - PACK(__q23, __q22, __q21, __q20), PACK(__q19, __q18, __q17, __q16), - PACK(__q15, __q14, __q13, __q12), PACK(__q11, __q10, __q09, __q08), - PACK(__q07, __q06, __q05, __q04), PACK(__q03, __q02, __q01, __q00)); -} - -#undef PACK - -#endif // gcc version test -#endif // __AVX512F__ - -/* Missing zero-extension AVX and AVX512 intrinsics. - * Fixed in Microsoft Visual Studio 2017 version 15.7 - * https://developercommunity.visualstudio.com/t/missing-zero-extension-avx-and-avx512-intrinsics/175737 - */ -#if defined(_MSC_VER) && _MSC_VER < 1914 -#ifdef __AVX2__ -static inline __m256i _mm256_zextsi128_si256(__m128i a) { - return _mm256_inserti128_si256(_mm256_setzero_si256(), a, 0); -} -#endif // __AVX2__ - -#ifdef __AVX512F__ -static inline __m512i _mm512_zextsi128_si512(__m128i a) { - return _mm512_inserti32x4(_mm512_setzero_si512(), a, 0); -} -#endif // __AVX512F__ -#endif // defined(_MSC_VER) && _MSC_VER < 1914 - #endif // include guard FALLBACK_BUILTINS_H From 887c4877b8f221be175d42cc3386c7b24a68bb15 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 21 Jul 2023 19:32:19 +0200 Subject: [PATCH 698/798] Configure: Make it possible to disable deflate_quick and deflate_medium also on non-x86 architectures. --- configure | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/configure b/configure index 29a64badfd..53aa012a99 100755 --- a/configure +++ b/configure @@ -1525,20 +1525,11 @@ EOF fi } -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - # Enable deflate_medium at level 1 - if test $without_new_strategies -eq 1; then - CFLAGS="${CFLAGS} -DNO_QUICK_STRATEGY" - SFLAGS="${SFLAGS} -DNO_QUICK_STRATEGY" - fi - # Enable deflate_medium at level 4-6 - if test $without_new_strategies -eq 1; then - CFLAGS="${CFLAGS} -DNO_MEDIUM_STRATEGY" - SFLAGS="${SFLAGS} -DNO_MEDIUM_STRATEGY" - fi - ;; -esac +# Check whether to disable deflate_medium and deflate_quick +if test $without_new_strategies -eq 1; then + CFLAGS="${CFLAGS} -DNO_QUICK_STRATEGY -DNO_MEDIUM_STRATEGY" + SFLAGS="${SFLAGS} -DNO_QUICK_STRATEGY -DNO_MEDIUM_STRATEGY" +fi ARCHDIR='arch/generic' ARCH_STATIC_OBJS='' From 828dde716b4666d681d2a6af748f7a1cd7a43fcf Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 29 Dec 2022 13:45:50 +0100 Subject: [PATCH 699/798] Expand support for symbol versioning to also allow multiple functions with the same name to exist with bindings to different versions. --- CMakeLists.txt | 3 +++ configure | 17 +++++++++++++++++ zbuild.h | 14 ++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 003e66db75..8d5d5ae9db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1140,6 +1140,9 @@ if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) set_target_properties(zlib PROPERTIES COMPILE_FLAGS "-fno-semantic-interposition") endif() if(NOT APPLE) + if(NOT ZLIB_COMPAT) + add_definitions(-DHAVE_SYMVER) + endif() set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.map\"") elseif(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}" OR NOT WITH_RPATH) diff --git a/configure b/configure index 53aa012a99..bb37b96640 100755 --- a/configure +++ b/configure @@ -567,6 +567,22 @@ else esac fi +# Symbol versioning +case "$uname" in + CYGWIN* | Cygwin* | cygwin* | MINGW* | mingw* | MSYS* | msys* | Darwin* | darwin*) + echo "Checking for Symbol versioning... No." + ;; + *) + if test $shared -eq 1; then + echo "Checking for Symbol versioning... Yes." + CFLAGS="${CFLAGS} -DHAVE_SYMVER" + SFLAGS="${SFLAGS} -DHAVE_SYMVER" + else + echo "Checking for Symbol versioning... No." + fi + ;; +esac + # Simplify some later conditionals case "$uname" in Linux* | linux*) @@ -2029,6 +2045,7 @@ EOF ;; esac +echo "Uname: $uname" echo "ARCH: ${ARCH}" echo "Using arch directory: ${ARCHDIR}" echo "Architecture-specific static object files:${ARCH_STATIC_OBJS}" diff --git a/zbuild.h b/zbuild.h index 2f9dd6b1c0..bb964d6c0a 100644 --- a/zbuild.h +++ b/zbuild.h @@ -119,6 +119,20 @@ # define Z_INTERNAL #endif +/* Symbol versioning helpers, allowing multiple versions of a function to exist. + * Functions using this must also be added to zlib-ng.map for each version. + * Double @@ means this is the default for newly compiled applications to link against. + * Single @ means this is kept for backwards compatibility. + * This is only used for Zlib-ng native API, and only on platforms supporting this. + */ +#if defined(HAVE_SYMVER) +# define ZSYMVER(func,alias,ver) __asm__(".symver " func ", " alias "@ZLIB_NG_" ver); +# define ZSYMVER_DEF(func,alias,ver) __asm__(".symver " func ", " alias "@@ZLIB_NG_" ver); +#else +# define ZSYMVER(func,alias,ver) +# define ZSYMVER_DEF(func,alias,ver) +#endif + #ifndef __cplusplus # define Z_REGISTER register #else From f0937b8a58be4dae44b6f2dcad6430838a41b74f Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sat, 29 Jul 2023 12:54:18 +0200 Subject: [PATCH 700/798] Fix typo found by codespell --- arch/riscv/adler32_rvv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/adler32_rvv.c b/arch/riscv/adler32_rvv.c index 0e78c92875..c9da34f3f8 100644 --- a/arch/riscv/adler32_rvv.c +++ b/arch/riscv/adler32_rvv.c @@ -71,7 +71,7 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) cnt = 0; } } - /* the left len <= 256 now, we can use 16-bit accum safetly */ + /* the left len <= 256 now, we can use 16-bit accum safely */ v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); size_t res = left; while (left >= vl) { From 2167377c46e1a1a117e97573dc8acdc95c2ec85e Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 21 Jul 2023 13:43:15 +0200 Subject: [PATCH 701/798] Clean up SSE4.2 support, and no longer use asm fallback or gcc builtin. Defines changing meaning: X86_SSE42 used to mean the compiler supports crc asm fallback. X86_SSE42_CRC_INTRIN used to mean compiler supports SSE4.2 intrinsics. X86_SSE42 now means compiler supports SSE4.2 intrinsics. This therefore also fixes the adler32_sse42 checks, since those were depending on SSE4.2 intrinsics but was mistakenly checking the X86_SSE42 define. Now the X86_SSE42 define actually means what it appears to. --- CMakeLists.txt | 5 +---- arch/x86/insert_string_sse42.c | 36 +++++---------------------------- cmake/detect-intrinsics.cmake | 23 +++------------------ configure | 37 ++++++++-------------------------- win32/Makefile.msc | 1 - 5 files changed, 17 insertions(+), 85 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d5d5ae9db..9fc865928e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -827,15 +827,12 @@ if(WITH_OPTIM) endif() if(WITH_SSE42) check_sse42_intrinsics() - if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) + if(HAVE_SSE42_INTRIN) add_definitions(-DX86_SSE42) set(SSE42_SRCS ${ARCHDIR}/adler32_sse42.c ${ARCHDIR}/insert_string_sse42.c) add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE42FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") - if(HAVE_SSE42CRC_INTRIN) - add_definitions(-DX86_SSE42_CRC_INTRIN) - endif() else() set(WITH_SSE42 OFF) endif() diff --git a/arch/x86/insert_string_sse42.c b/arch/x86/insert_string_sse42.c index 565d92f97c..ae092a7e47 100644 --- a/arch/x86/insert_string_sse42.c +++ b/arch/x86/insert_string_sse42.c @@ -5,38 +5,13 @@ * */ +#ifdef X86_SSE42 #include "../../zbuild.h" -#include -#ifdef _MSC_VER -# include -#endif +#include #include "../../deflate.h" -#ifdef X86_SSE42_CRC_INTRIN -# ifdef _MSC_VER -# define HASH_CALC(s, h, val)\ - h = _mm_crc32_u32(h, val) -# else -# define HASH_CALC(s, h, val)\ - h = __builtin_ia32_crc32si(h, val) -# endif -#else -# ifdef _MSC_VER -# define HASH_CALC(s, h, val) {\ - __asm mov edx, h\ - __asm mov eax, val\ - __asm crc32 eax, edx\ - __asm mov h, eax\ - } -# else -# define HASH_CALC(s, h, val) \ - __asm__ __volatile__ (\ - "crc32 %1,%0\n\t"\ - : "+r" (h)\ - : "r" (val)\ - ); -# endif -#endif +#define HASH_CALC(s, h, val)\ + h = _mm_crc32_u32(h, val) #define HASH_CALC_VAR h #define HASH_CALC_VAR_INIT uint32_t h = 0 @@ -45,6 +20,5 @@ #define INSERT_STRING insert_string_sse42 #define QUICK_INSERT_STRING quick_insert_string_sse42 -#ifdef X86_SSE42 -# include "../../insert_string_tpl.h" +#include "../../insert_string_tpl.h" #endif diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index b0b0516e37..f5cc06bf77 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -481,35 +481,18 @@ macro(check_sse42_intrinsics) set(SSE42FLAG "-msse4.2") endif() endif() - # Check whether compiler supports SSE4.2 CRC inline asm + # Check whether compiler supports SSE4.2 intrinsics set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( - "int main(void) { - unsigned val = 0, h = 0; - #if defined(_MSC_VER) - { __asm mov edx, h __asm mov eax, val __asm crc32 eax, edx __asm mov h, eax } - #else - __asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) ); - #endif - return (int)h; - }" - HAVE_SSE42CRC_INLINE_ASM - ) - # Check whether compiler supports SSE4.2 CRC intrinsics - check_c_source_compile_or_run( - "#include + "#include int main(void) { unsigned crc = 0; char c = 'c'; - #if defined(_MSC_VER) crc = _mm_crc32_u32(crc, c); - #else - crc = __builtin_ia32_crc32qi(crc, c); - #endif (void)crc; return 0; }" - HAVE_SSE42CRC_INTRIN + HAVE_SSE42_INTRIN ) set(CMAKE_REQUIRED_FLAGS) endmacro() diff --git a/configure b/configure index bb37b96640..7461a1dcec 100755 --- a/configure +++ b/configure @@ -1447,38 +1447,23 @@ EOF } check_sse42_intrinsics() { - # Check whether compiler supports SSE4.2 CRC inline asm - cat > $test.c << EOF -int main(void) { - unsigned val = 0, h = 0; - __asm__ __volatile__ ( "crc32 %1,%0" : "+r" (h) : "r" (val) ); - return (int) h; -} -EOF - if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 CRC inline assembly ... Yes." | tee -a configure.log - HAVE_SSE42CRC_INLINE_ASM=1 - else - echo "Checking for SSE4.2 CRC inline assembly ... No." | tee -a configure.log - HAVE_SSE42CRC_INLINE_ASM=0 - fi - - # Check whether compiler supports SSE4.2 CRC intrinsics + # Check whether compiler supports SSE4.2 intrinsics cat > $test.c << EOF +#include int main(void) { unsigned crc = 0; char c = 'c'; - crc = __builtin_ia32_crc32qi(crc, c); + crc = _mm_crc32_u32(crc, c); (void)crc; return 0; } EOF if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 CRC intrinsics ... Yes." | tee -a configure.log - HAVE_SSE42CRC_INTRIN=1 + echo "Checking for SSE4.2 intrinsics ... Yes." | tee -a configure.log + HAVE_SSE42_INTRIN=1 else - echo "Checking for SSE4.2 CRC intrinsics ... No." | tee -a configure.log - HAVE_SSE42CRC_INTRIN=0 + echo "Checking for SSE4.2 intrinsics ... No." | tee -a configure.log + HAVE_SSE42_INTRIN=0 fi } @@ -1613,15 +1598,9 @@ case "${ARCH}" in check_sse42_intrinsics - if test ${HAVE_SSE42CRC_INTRIN} -eq 1 || test ${HAVE_SSE42CRC_INLINE_ASM} -eq 1; then + if test ${HAVE_SSE42_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42" SFLAGS="${SFLAGS} -DX86_SSE42" - - if test ${HAVE_SSE42CRC_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE42_CRC_INTRIN" - SFLAGS="${SFLAGS} -DX86_SSE42_CRC_INTRIN" - fi - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_sse42.o insert_string_sse42.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_sse42.lo insert_string_sse42.lo" fi diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 9ed26f2834..3035072bec 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -31,7 +31,6 @@ WFLAGS = \ -DX86_PCLMULQDQ_CRC \ -DX86_SSE2 \ -DX86_SSE42 \ - -DX86_SSE42_CRC_INTRIN \ -DX86_SSSE3 \ -DX86_AVX2 From 4894be9c930b3a7f61bb1309d485199d0fa47bbc Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 20 Jul 2023 19:43:08 +0200 Subject: [PATCH 702/798] Move check_c_source_compile_or_run cmake macro to the only place it is used. --- CMakeLists.txt | 10 ---------- cmake/detect-intrinsics.cmake | 11 +++++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fc865928e..39a30ef585 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -486,16 +486,6 @@ if(NOT HAVE_PTRDIFF_T) endif() endif() -# Macro to check if source compiles -# (and, when compiling very natively, also runs). -macro(check_c_source_compile_or_run source flag) - if(CMAKE_CROSSCOMPILING OR NOT WITH_NATIVE_INSTRUCTIONS) - check_c_source_compiles("${source}" ${flag}) - else() - check_c_source_runs("${source}" ${flag}) - endif() -endmacro() - add_compile_options($<$:-DZLIB_DEBUG>) if(MSVC) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index f5cc06bf77..536c27fb72 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -1,6 +1,17 @@ # detect-intrinsics.cmake -- Detect compiler intrinsics support # Licensed under the Zlib license, see LICENSE.md for details +# Macro to check if source compiles +# (and, when compiling very natively, also runs). +macro(check_c_source_compile_or_run source flag) + if(CMAKE_CROSSCOMPILING OR NOT WITH_NATIVE_INSTRUCTIONS) + check_c_source_compiles("${source}" ${flag}) + else() + check_c_source_runs("${source}" ${flag}) + endif() +endmacro() + + macro(check_acle_compiler_flag) if(MSVC) # Both ARM and ARM64-targeting msvc support intrinsics, but From a7e9f0beef665042a73466f90c1ddcc984cdb4be Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 24 Jul 2023 09:37:57 +0200 Subject: [PATCH 703/798] Relative paths CMAKE_INSTALL_*, absolute paths CMAKE_INSTALL_FULL_*; use @rpath/libname as install name on macOS --- CMakeLists.txt | 46 ++-------------------------------------------- configure | 7 +------ test/pkgcheck.sh | 2 +- 3 files changed, 4 insertions(+), 51 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 39a30ef585..5dacc286a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -938,36 +938,8 @@ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) endif() endif() -# Refer to prefix symbolically to ease relocation by end user, -# as Makefile-generated .pc file does. -string(FIND "${CMAKE_INSTALL_INCLUDEDIR}" "${CMAKE_INSTALL_PREFIX}/" INCLUDEDIR_POS) -string(FIND "${CMAKE_INSTALL_LIBDIR}" "${CMAKE_INSTALL_PREFIX}/" LIBDIR_POS) -string(LENGTH "${CMAKE_INSTALL_PREFIX}/" INSTALL_PREFIX_LEN) - -if(NOT IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") - set(PC_INC_INSTALL_DIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") -elseif(INCLUDEDIR_POS EQUAL 0) - string(SUBSTRING "${CMAKE_INSTALL_INCLUDEDIR}" "${INSTALL_PREFIX_LEN}" "-1" INCLUDEDIR_RELATIVE) - set(PC_INC_INSTALL_DIR "\${prefix}/${INCLUDEDIR_RELATIVE}") -else() - set(PC_INC_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") -endif() - -if(APPLE) - option(WITH_RPATH "Enable RPATH for shared library" OFF) -endif() -if(NOT IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") - if(APPLE AND WITH_RPATH) - set(PC_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") - else() - set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") - endif() -elseif(LIBDIR_POS EQUAL 0) - string(SUBSTRING "${CMAKE_INSTALL_LIBDIR}" "${INSTALL_PREFIX_LEN}" "-1" LIBDIR_RELATIVE) - set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${LIBDIR_RELATIVE}") -else() - set(PC_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") -endif() +set(PC_INC_INSTALL_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}") +set(PC_LIB_INSTALL_DIR "${CMAKE_INSTALL_FULL_LIBDIR}") #============================================================================ # zlib @@ -1132,11 +1104,6 @@ if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) endif() set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.map\"") - elseif(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}" OR NOT WITH_RPATH) - # Match configure/make's behavior (i.e. don't use @rpath on mac when using absolute path). - set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "@rpath/${CMAKE_INSTALL_FULL_LIBDIR}") - else() - set_target_properties(zlib PROPERTIES INSTALL_NAME_DIR "@rpath/${CMAKE_INSTALL_LIBDIR}") endif() endif() if(MSYS) @@ -1173,11 +1140,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h.in configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gzread.c.in ${CMAKE_CURRENT_BINARY_DIR}/gzread.c @ONLY) -# Fix install directory after generating zlib.pc/zlib-ng.pc -if (NOT IS_ABSOLUTE CMAKE_INSTALL_LIBDIR AND WITH_RPATH) - set(CMAKE_INSTALL_LIBDIR "/${CMAKE_INSTALL_LIBDIR}") -endif() - if (NOT ZLIB_SYMBOL_PREFIX STREQUAL "") add_feature_info(ZLIB_SYMBOL_PREFIX ON "Publicly exported symbols have a custom prefix") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib_name_mangling${SUFFIX}.h.in @@ -1276,8 +1238,4 @@ endif() add_feature_info(INSTALL_UTILS INSTALL_UTILS "Copy minigzip and minideflate during install") -if(APPLE) - add_feature_info(WITH_RPATH WITH_RPATH "Enable RPATH for shared library") -endif() - FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) diff --git a/configure b/configure index 7461a1dcec..cc86f018e6 100755 --- a/configure +++ b/configure @@ -513,12 +513,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then SHAREDLIBM=${LIBNAME}.$VER1$shared_ext SHAREDTARGET=$SHAREDLIBV LDSHARED=${LDSHARED-"$cc"} - case ${libdir} in - /*) - LDSHAREDFLAGS="-dynamiclib -install_name ${libdir}/${SHAREDLIBM} -compatibility_version ${VER1} -current_version ${VER3}" ;; - *) - LDSHAREDFLAGS="-dynamiclib -install_name @rpath/${libdir}/${SHAREDLIBM} -compatibility_version ${VER1} -current_version ${VER3}" ;; - esac + LDSHAREDFLAGS="-dynamiclib -install_name @rpath/${SHAREDLIBM} -compatibility_version ${VER1} -current_version ${VER3}" if libtool -V 2>&1 | grep Apple > /dev/null; then AR="libtool" else diff --git a/test/pkgcheck.sh b/test/pkgcheck.sh index 629f98aded..6641b300a4 100644 --- a/test/pkgcheck.sh +++ b/test/pkgcheck.sh @@ -81,7 +81,7 @@ Darwin) sysctl -n machdep.cpu.features sysctl -n machdep.cpu.leaf7_features sysctl -n machdep.cpu.extfeatures - CMAKE_ARGS="-DCMAKE_INSTALL_LIBDIR=lib -DPKGCONFIG_INSTALL_DIR=/lib/pkgconfig -DWITH_RPATH=on ${CMAKE_ARGS}" + CMAKE_ARGS="-DCMAKE_INSTALL_LIBDIR=lib ${CMAKE_ARGS}" CONFIGURE_ARGS="--libdir=lib ${CONFIGURE_ARGS}" ;; *) From e13bc3af6892a1decb0260ce475d5b2aa9da94f4 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 24 Jul 2023 11:37:31 +0200 Subject: [PATCH 704/798] relocatable pc files by default, while allowing discouraged absolute paths for CMAKE_INSTALL_[LIB|INCLUDE]DIR --- CMakeLists.txt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dacc286a3..47562a3437 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -938,8 +938,19 @@ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) endif() endif() -set(PC_INC_INSTALL_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}") -set(PC_LIB_INSTALL_DIR "${CMAKE_INSTALL_FULL_LIBDIR}") +# The user is allowed (but discouraged) to set absolute CMAKE_INSTALL_*DIR paths. +# If they do, we copy these non-relocatable paths into the pkg-config file. +if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") + set(PC_INC_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") +else() + set(PC_INC_INSTALL_DIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") +endif() + +if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") + set(PC_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}") +else() + set(PC_LIB_INSTALL_DIR "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") +endif() #============================================================================ # zlib From 26a917d7b4c51beafa9a2d038c46bd15ea0ea175 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 24 Jul 2023 10:20:32 +0200 Subject: [PATCH 705/798] Remove relative configure --lib --- test/pkgcheck.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/pkgcheck.sh b/test/pkgcheck.sh index 6641b300a4..94a67a191e 100644 --- a/test/pkgcheck.sh +++ b/test/pkgcheck.sh @@ -81,11 +81,6 @@ Darwin) sysctl -n machdep.cpu.features sysctl -n machdep.cpu.leaf7_features sysctl -n machdep.cpu.extfeatures - CMAKE_ARGS="-DCMAKE_INSTALL_LIBDIR=lib ${CMAKE_ARGS}" - CONFIGURE_ARGS="--libdir=lib ${CONFIGURE_ARGS}" - ;; -*) - CMAKE_ARGS="-DCMAKE_INSTALL_LIBDIR=lib ${CMAKE_ARGS}" ;; esac From e9a48a2ecb1c70e014b3a0eb5c6bc612213b2b52 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 29 May 2023 12:43:58 -0700 Subject: [PATCH 706/798] Simplify deflate stream/state check. --- deflate.c | 13 ++----------- deflate.h | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/deflate.c b/deflate.c index 55abcf6217..978a389b97 100644 --- a/deflate.c +++ b/deflate.c @@ -340,21 +340,12 @@ int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int /* ========================================================================= * Check for a valid deflate stream state. Return 0 if ok, 1 if not. */ -static int deflateStateCheck (PREFIX3(stream) *strm) { +static int deflateStateCheck(PREFIX3(stream) *strm) { deflate_state *s; if (strm == NULL || strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) return 1; s = strm->state; - if (s == NULL || s->strm != strm || (s->status != INIT_STATE && -#ifdef GZIP - s->status != GZIP_STATE && - s->status != EXTRA_STATE && - s->status != NAME_STATE && - s->status != COMMENT_STATE && - s->status != HCRC_STATE && -#endif - s->status != BUSY_STATE && - s->status != FINISH_STATE)) + if (s == NULL || s->strm != strm || (s->status < INIT_STATE || s->status > MAX_STATE)) return 1; return 0; } diff --git a/deflate.h b/deflate.h index e4b971f88a..8001b47c99 100644 --- a/deflate.h +++ b/deflate.h @@ -51,16 +51,21 @@ #define END_BLOCK 256 /* end of block literal code */ -#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#define INIT_STATE 1 /* zlib header -> BUSY_STATE */ #ifdef GZIP -# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ -# define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ -# define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ -# define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ -# define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ +# define GZIP_STATE 4 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +# define EXTRA_STATE 5 /* gzip extra block -> NAME_STATE */ +# define NAME_STATE 6 /* gzip file name -> COMMENT_STATE */ +# define COMMENT_STATE 7 /* gzip comment -> HCRC_STATE */ +# define HCRC_STATE 8 /* gzip header CRC -> BUSY_STATE */ +#endif +#define BUSY_STATE 2 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 3 /* stream complete */ +#ifdef GZIP +# define MAX_STATE HCRC_STATE +#else +# define MAX_STATE FINISH_STATE #endif -#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ -#define FINISH_STATE 666 /* stream complete */ /* Stream status */ #define HASH_BITS 16u /* log2(HASH_SIZE) */ From 04e8561bde09e7138e7259e6dec6ef7be04faed1 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 6 Aug 2023 12:55:29 +0200 Subject: [PATCH 707/798] Fix typos found by codespell --- test/benchmarks/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md index 5dce7f51bc..964b198cfe 100644 --- a/test/benchmarks/README.md +++ b/test/benchmarks/README.md @@ -22,14 +22,14 @@ There are two different benchmarks, micro and macro. ### Benchmark benchmark_zlib These are microbenchmarks intended to test lower level subfunctions of the library. -Benchmarks include impelementations of: +Benchmarks include implementations of: - Adler32 - CRC - 256 byte comparisons - SIMD accelerated "slide hash" routine By default these benchmarks report things on the nanosecond scale and are small enough -to measure very minute diferences. +to measure very minute differences. ### Benchmark benchmark_zlib_apps These benchmarks measure applications of zlib as a whole. Currently the only examples From 3605d984d82db5c6dc9f0ac3b07f257edd4c1979 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 6 Aug 2023 13:11:03 +0200 Subject: [PATCH 708/798] Avoid unnecessary line continuations --- test/minideflate.c | 26 +++++++++++++------------- test/minigzip.c | 20 ++++++++++---------- test/switchlevels.c | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index 987e6121ba..87513df380 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -205,22 +205,22 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ } void show_help(void) { - printf("Usage: minideflate [-c][-d][-k] [-f|-h|-R|-F] [-m level] [-r/-t size] [-s flush] [-w bits] [-0 to -9] [input file]\n\n" \ - " -c : write to standard output\n" \ - " -d : decompress\n" \ - " -k : keep input file\n" \ - " -f : compress with Z_FILTERED\n" \ - " -h : compress with Z_HUFFMAN_ONLY\n" \ - " -R : compress with Z_RLE\n" \ - " -F : compress with Z_FIXED\n" \ - " -m : memory level (1 to 8)\n" \ - " -w : window bits..\n" \ + printf("Usage: minideflate [-c][-d][-k] [-f|-h|-R|-F] [-m level] [-r/-t size] [-s flush] [-w bits] [-0 to -9] [input file]\n\n" + " -c : write to standard output\n" + " -d : decompress\n" + " -k : keep input file\n" + " -f : compress with Z_FILTERED\n" + " -h : compress with Z_HUFFMAN_ONLY\n" + " -R : compress with Z_RLE\n" + " -F : compress with Z_FIXED\n" + " -m : memory level (1 to 8)\n" + " -w : window bits..\n" " : -1 to -15 for raw deflate\n" " : 0 to 15 for deflate (adler32)\n" " : 16 to 31 for gzip (crc32)\n" - " -s : flush type (0 to 5)\n" \ - " -r : read buffer size\n" \ - " -t : write buffer size\n" \ + " -s : flush type (0 to 5)\n" + " -r : read buffer size\n" + " -t : write buffer size\n" " -0 to -9 : compression level\n\n"); } diff --git a/test/minigzip.c b/test/minigzip.c index d55f5086be..2615433ce7 100644 --- a/test/minigzip.c +++ b/test/minigzip.c @@ -265,16 +265,16 @@ void file_uncompress(char *file, int keep) { } void show_help(void) { - printf("Usage: minigzip [-c] [-d] [-k] [-f|-h|-R|-F|-T] [-A] [-0 to -9] [files...]\n\n" \ - " -c : write to standard output\n" \ - " -d : decompress\n" \ - " -k : keep input files\n" \ - " -f : compress with Z_FILTERED\n" \ - " -h : compress with Z_HUFFMAN_ONLY\n" \ - " -R : compress with Z_RLE\n" \ - " -F : compress with Z_FIXED\n" \ - " -T : stored raw\n" \ - " -A : auto detect type\n" \ + printf("Usage: minigzip [-c] [-d] [-k] [-f|-h|-R|-F|-T] [-A] [-0 to -9] [files...]\n\n" + " -c : write to standard output\n" + " -d : decompress\n" + " -k : keep input files\n" + " -f : compress with Z_FILTERED\n" + " -h : compress with Z_HUFFMAN_ONLY\n" + " -R : compress with Z_RLE\n" + " -F : compress with Z_FIXED\n" + " -T : stored raw\n" + " -A : auto detect type\n" " -0 to -9 : compression level\n\n"); } diff --git a/test/switchlevels.c b/test/switchlevels.c index a065dbcff0..b31bc0f95c 100644 --- a/test/switchlevels.c +++ b/test/switchlevels.c @@ -111,7 +111,7 @@ static int compress_chunk(PREFIX3(stream) *strm, int level, int size, int last) void show_help(void) { - printf("Usage: switchlevels [-w bits] level1 size1 [level2 size2 ...]\n\n" \ + printf("Usage: switchlevels [-w bits] level1 size1 [level2 size2 ...]\n\n" " -w : window bits (8 to 15 for gzip, -8 to -15 for zlib)\n\n"); } From e841518da7f4861cb0a275583da0cec13714802c Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 6 Aug 2023 13:19:10 +0200 Subject: [PATCH 709/798] Discard trailing whitespaces --- arch/riscv/adler32_rvv.c | 2 +- arch/riscv/compare256_rvv.c | 2 +- arch/riscv/riscv_features.h | 2 +- test/benchmarks/benchmark_png_shared.h | 20 ++++++++++---------- test/example.c | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arch/riscv/adler32_rvv.c b/arch/riscv/adler32_rvv.c index c9da34f3f8..9442f28003 100644 --- a/arch/riscv/adler32_rvv.c +++ b/arch/riscv/adler32_rvv.c @@ -45,7 +45,7 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) * * The block_size is the largest multiple of vl that <= 256, because overflow would occur when * vl > 256 (255 * 256 <= UINT16_MAX). - * + * * We accumulate 8-bit data into a 16-bit accumulator and then * move the data into the 32-bit accumulator at the last iteration. */ diff --git a/arch/riscv/compare256_rvv.c b/arch/riscv/compare256_rvv.c index acb28035f3..0fd6082c44 100644 --- a/arch/riscv/compare256_rvv.c +++ b/arch/riscv/compare256_rvv.c @@ -21,7 +21,7 @@ static inline uint32_t compare256_rvv_static(const uint8_t *src0, const uint8_t vuint8m4_t v_src1 = __riscv_vle8_v_u8m4(src1, vl); vbool2_t v_mask = __riscv_vmsne_vv_u8m4_b2(v_src0, v_src1, vl); found_diff = __riscv_vfirst_m_b2(v_mask, vl); - if (found_diff >= 0) + if (found_diff >= 0) return len + (uint32_t)found_diff; src0 += vl, src1 += vl, len += vl; } while (len < 256); diff --git a/arch/riscv/riscv_features.h b/arch/riscv/riscv_features.h index f933fc9acb..c76e967c36 100644 --- a/arch/riscv/riscv_features.h +++ b/arch/riscv/riscv_features.h @@ -2,7 +2,7 @@ * * Copyright (C) 2023 SiFive, Inc. All rights reserved. * Contributed by Alex Chiang - * + * * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/test/benchmarks/benchmark_png_shared.h b/test/benchmarks/benchmark_png_shared.h index 926b4d964f..bde679e7d3 100644 --- a/test/benchmarks/benchmark_png_shared.h +++ b/test/benchmarks/benchmark_png_shared.h @@ -55,21 +55,21 @@ static void init_compressible(png_bytep buf, size_t num_pix) { int32_t green_stop = num_pix; for (int32_t x = 0; i < red_stop; x += 3, ++i) { - buf[x] = 255; + buf[x] = 255; buf[x + 1] = 0; - buf[x + 2] = 0; + buf[x + 2] = 0; } for (int32_t x = 3 * i; i < blue_stop; x+= 3, ++i) { - buf[x] = 0; - buf[x + 1] = 255; - buf[x + 2] = 0; + buf[x] = 0; + buf[x + 1] = 255; + buf[x + 2] = 0; } for (int32_t x = 3 * i; i < green_stop; x += 3, ++i) { - buf[x] = 0; - buf[x + 1] = 0; - buf[x + 2] = 255; + buf[x] = 0; + buf[x + 1] = 0; + buf[x + 2] = 255; } } @@ -112,7 +112,7 @@ static void read_from_pngdat(png_structp png, png_bytep out, png_size_t bytes_to static inline int decode_png(png_parse_dat *dat, png_bytepp out_bytes, size_t in_size, uint32_t &width, uint32_t &height) { png_structp png = NULL; png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - + if (!png) abort(); png_infop info = NULL; info = png_create_info_struct(png); @@ -128,7 +128,7 @@ static inline int decode_png(png_parse_dat *dat, png_bytepp out_bytes, size_t in if (color_type != PNG_COLOR_TYPE_RGB) { fprintf(stderr, "expected an 8 bpp RGB image\n"); abort(); - } + } if (im_size > in_size) { *out_bytes = (png_bytep)realloc(*out_bytes, im_size); diff --git a/test/example.c b/test/example.c index b500af92c6..d0e38c9080 100644 --- a/test/example.c +++ b/test/example.c @@ -543,14 +543,14 @@ void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *unc } CHECK_ERR(err, "inflate with dict"); } - + err = PREFIX(inflateGetDictionary)(&d_stream, NULL, &check_dictionary_len); CHECK_ERR(err, "inflateGetDictionary"); #ifndef S390_DFLTCC_INFLATE if (check_dictionary_len < sizeof(dictionary)) error("bad dictionary length\n"); #endif - + err = PREFIX(inflateGetDictionary)(&d_stream, check_dictionary, &check_dictionary_len); CHECK_ERR(err, "inflateGetDictionary"); #ifndef S390_DFLTCC_INFLATE From 73bbb54cf6686a81710a1326c4cf1cfee9a49784 Mon Sep 17 00:00:00 2001 From: Dimitri Papadopoulos <3234522+DimitriPapadopoulos@users.noreply.github.com> Date: Sun, 6 Aug 2023 13:27:51 +0200 Subject: [PATCH 710/798] Discard repeated words --- arch/x86/adler32_ssse3.c | 2 +- inftrees.h | 2 +- insert_string_tpl.h | 4 ++-- test/fuzz/fuzzer_minigzip.c | 2 +- test/minigzip.c | 2 +- zlib.h.in | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 99ce795823..ae819d632e 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -54,7 +54,7 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const uint8_t *buf, size_t len if (len < 16 + align_offset) { /* Let's eat the cost of this one unaligned load so that * we don't completely skip over the vectorization. Doing - * 16 bytes at a time unaligned is is better than 16 + <= 15 + * 16 bytes at a time unaligned is better than 16 + <= 15 * sums */ vbuf = _mm_loadu_si128((__m128i*)buf); len -= 16; diff --git a/inftrees.h b/inftrees.h index eeae9c6ac4..ad2be151f2 100644 --- a/inftrees.h +++ b/inftrees.h @@ -44,7 +44,7 @@ typedef struct { examples/enough.c found in the zlib distributions. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 10 15" for literal/length codes - returns returns 1332, and "enough 30 9 15" for distance codes returns 592. + returns 1332, and "enough 30 9 15" for distance codes returns 592. The initial root table size (10 or 9) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and diff --git a/insert_string_tpl.h b/insert_string_tpl.h index 4acd67fd62..c84617730a 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -43,7 +43,7 @@ /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * IN assertion: all calls to UPDATE_HASH are made with consecutive * input characters, so that a running hash key can be computed from the * previous key instead of complete recalculation each time. */ @@ -81,7 +81,7 @@ Z_INTERNAL Pos QUICK_INSERT_STRING(deflate_state *const s, uint32_t str) { * Insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. - * IN assertion: all calls to to INSERT_STRING are made with consecutive + * IN assertion: all calls to INSERT_STRING are made with consecutive * input characters and the first STD_MIN_MATCH bytes of str are valid * (except for the last STD_MIN_MATCH-1 bytes of the input file). */ diff --git a/test/fuzz/fuzzer_minigzip.c b/test/fuzz/fuzzer_minigzip.c index 819148d2b3..b59c69bd04 100644 --- a/test/fuzz/fuzzer_minigzip.c +++ b/test/fuzz/fuzzer_minigzip.c @@ -109,7 +109,7 @@ void gz_compress(FILE *in, gzFile out) { #ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ /* Try compressing the input file at once using mmap. Return Z_OK if - * if success, Z_ERRNO otherwise. + * success, Z_ERRNO otherwise. */ int gz_compress_mmap(FILE *in, gzFile out) { int len; diff --git a/test/minigzip.c b/test/minigzip.c index 2615433ce7..537f64bbab 100644 --- a/test/minigzip.c +++ b/test/minigzip.c @@ -129,7 +129,7 @@ void gz_compress(FILE *in, gzFile out) { #ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ /* Try compressing the input file at once using mmap. Return Z_OK if - * if success, Z_ERRNO otherwise. + * success, Z_ERRNO otherwise. */ int gz_compress_mmap(FILE *in, gzFile out) { int len; diff --git a/zlib.h.in b/zlib.h.in index 71f114a24f..45b6c8e092 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -924,7 +924,7 @@ Z_EXTERN int Z_EXPORT inflateSync(z_stream *strm); inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. - In the success case, the application may save the current current value of + In the success case, the application may save the current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. From c7d98c239a749ebc86322044016f158e0e0b4e3f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 8 Aug 2023 17:06:18 -0700 Subject: [PATCH 711/798] Remove inert check for HAVE_ACLE_FLAG in check_acle_compiler_flag. --- cmake/detect-intrinsics.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 536c27fb72..33ffc28bb2 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -21,7 +21,7 @@ macro(check_acle_compiler_flag) endif() else() if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") - if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) + if(NOT NATIVEFLAG) set(ACLEFLAG "-march=armv8-a+crc" CACHE INTERNAL "Compiler option to enable ACLE support") endif() endif() From ca7573297ac5ce3b4f1f447766c72bd937705466 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 8 Aug 2023 17:06:39 -0700 Subject: [PATCH 712/798] Clean up extra whitespaces at line endings in check_rvv_intrinsics. --- cmake/detect-intrinsics.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 33ffc28bb2..f10c51774b 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -374,9 +374,9 @@ macro(check_rvv_intrinsics) set(CMAKE_REQUIRED_FLAGS "${RISCVFLAG} ${NATIVEFLAG}") check_c_source_compiles( "#include - int main() { - return 0; - }" + int main() { + return 0; + }" HAVE_RVV_INTRIN ) set(CMAKE_REQUIRED_FLAGS) From 0cb2b376ab840f7e7677558e9132273947cc8ae6 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 12 Aug 2023 16:23:12 +0200 Subject: [PATCH 713/798] Remove partially broken march=native support from Configure. Remove pkgcheck comparison of march=native builds between CMake and Configure. --- .github/workflows/pkgcheck.yml | 7 ---- configure | 64 +++++----------------------------- 2 files changed, 8 insertions(+), 63 deletions(-) diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 4e07f021be..e8483c717c 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -76,13 +76,6 @@ jobs: compiler: clang cxx-compiler: clang++ - - name: macOS Clang Native - os: macOS-11 - compiler: clang - cxx-compiler: clang++ - cmake-args: -DWITH_NATIVE_INSTRUCTIONS=ON - configure-args: --native - - name: macOS Clang Symbol Prefix os: macOS-11 compiler: clang diff --git a/configure b/configure index cc86f018e6..71b3074371 100755 --- a/configure +++ b/configure @@ -101,7 +101,6 @@ builddfltccdeflate=0 builddfltccinflate=0 buildcrc32vx=1 floatabi= -native=0 forcesse2=0 # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal # instruction scheduling unless you specify a reasonable -mtune= target @@ -175,7 +174,6 @@ case "$1" in echo ' [--without-crc32-vx] Build without vectorized CRC32 on IBM Z' | tee -a configure.log echo ' [--with-reduced-mem] Reduced memory usage for special cases (reduces performance)' | tee -a configure.log echo ' [--force-sse2] Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log - echo ' [--native] Compiles with full instruction set supported on this host' | tee -a configure.log exit 0 ;; -p*=* | --prefix=*) prefix=$(echo $1 | sed 's/.*=//'); shift ;; -e*=* | --eprefix=*) exec_prefix=$(echo $1 | sed 's/.*=//'); shift ;; @@ -208,7 +206,6 @@ case "$1" in --without-crc32-vx) buildcrc32vx=0; shift ;; --with-reduced-mem) reducedmem=1; shift ;; --force-sse2) forcesse2=1; shift ;; - -n | --native) native=1; shift ;; -a*=* | --archs=*) ARCHS=$(echo $1 | sed 's/.*=//'); shift ;; --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;; @@ -256,19 +253,6 @@ case $($cc -v 2>&1) in *clang*) gcc=1 ;; esac -if test $native -eq 1; then - avx512flag="" - avx512vnniflag="" - avx2flag="" - sse2flag="" - ssse3flag="" - sse42flag="" - pclmulflag="" - vpclmulflag="" - xsaveflag="" - noltoflag="" -fi - if test $build32 -eq 1; then CFLAGS="${CFLAGS} -m32" SFLAGS="${SFLAGS} -m32" @@ -333,11 +317,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then ARCH=$CC_ARCH fi ;; arm | armeb) - if test $native -eq 0; then ARCH=arm - else - ARCH=native - fi if test "${uname}" = "eabi"; then # No ACLE support uname=arm @@ -347,25 +327,15 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then fi fi if test $buildacle -eq 1; then - if test $native -eq 0; then - ARCH=armv8-a+crc - fi + ARCH=armv8-a+crc fi ;; armv8l) - if test $native -eq 0; then - ARCH=armv8-a - else - ARCH=native - fi ;; + ARCH=armv8-a ;; aarch64 | aarch64_be | arm64) if test "${uname}" = "elf"; then uname=aarch64 fi - if test $native -eq 0; then - ARCH=aarch64 - else - ARCH=native - fi ;; + ARCH=aarch64 ;; powerpc | ppc) ARCH=powerpc ;; powerpc64 | ppc64) @@ -380,16 +350,6 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then fi CFLAGS="${CFLAGS} -Wall" SFLAGS="${CFLAGS} -fPIC" - if test $native -eq 1; then - case $ARCH in - powerpc*) - NATIVE_FLAG="-mcpu=native" ;; - *) - NATIVE_FLAG="-march=native" ;; - esac - CFLAGS="${CFLAGS} ${NATIVE_FLAG}" - SFLAGS="${SFLAGS} ${NATIVE_FLAG}" - fi if test "$warn" -eq 1; then CFLAGS="${CFLAGS} -Wextra" fi @@ -950,7 +910,7 @@ else fi # Check for -fno-lto compiler support -if test $gcc -eq 1 -a $without_optimizations -eq 0 -a $native -eq 0; then +if test $gcc -eq 1 -a $without_optimizations -eq 0; then cat > $test.c < Date: Thu, 20 Jul 2023 19:26:06 +0200 Subject: [PATCH 714/798] Simplify handling of march=native in CMakeLits.txt --- CMakeLists.txt | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 47562a3437..322d7fc6df 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,10 +168,6 @@ if(CMAKE_C_COMPILER_ID MATCHES "^Intel") set(WARNFLAGS_MAINTAINER /W5) set(WARNFLAGS_DISABLE) endif() - if(WITH_NATIVE_INSTRUCTIONS) - message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") - set(WITH_NATIVE_INSTRUCTIONS OFF) - endif() elseif(MSVC) # Minimum supported MSVC version is 1800 = Visual Studio 12.0/2013 # See also https://cmake.org/cmake/help/latest/variable/MSVC_VERSION.html @@ -190,23 +186,13 @@ elseif(MSVC) if(NOT "${ARCH}" MATCHES "aarch64") set(NEONFLAG "/arch:VFPv4") endif() - endif() - if(WITH_NATIVE_INSTRUCTIONS) - message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") - set(WITH_NATIVE_INSTRUCTIONS OFF) endif() elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") # Enable warnings in GCC and Clang set(WARNFLAGS -Wall) set(WARNFLAGS_MAINTAINER -Wextra) set(WARNFLAGS_DISABLE) - if(WITH_NATIVE_INSTRUCTIONS) - if(BASEARCH_PPC_FOUND) - set(NATIVEFLAG "-mcpu=native") - else() - set(NATIVEFLAG "-march=native") - endif() - else() + if(NOT WITH_NATIVE_INSTRUCTIONS) if(BASEARCH_ARM_FOUND) if("${ARCH}" MATCHES "arm" AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") # Auto-detect support for ARM floating point ABI @@ -252,14 +238,25 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(MINGW) list(APPEND WARNFLAGS_DISABLE -Wno-pedantic-ms-format) endif() -else() - if(WITH_NATIVE_INSTRUCTIONS) +endif() + +# Set native march/mcpu +if(WITH_NATIVE_INSTRUCTIONS) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(BASEARCH_PPC_FOUND) + set(NATIVEFLAG "-mcpu=native") + else() + set(NATIVEFLAG "-march=native") + endif() + # Apply flag to all source files and compilation checks + add_compile_options(${NATIVEFLAG}) + else() message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration") set(WITH_NATIVE_INSTRUCTIONS OFF) endif() endif() -# Disable LTO +# Force disable LTO if WITH_NATIVE_INSTRUCTIONS is not active if(NOT WITH_NATIVE_INSTRUCTIONS) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) foreach(_cfg_name IN LISTS CMAKE_CONFIGURATION_TYPES) @@ -292,12 +289,6 @@ if(NOT WITH_CODE_COVERAGE AND NOT MSVC AND NOT CMAKE_C_FLAGS MATCHES "([\\/\\-]O CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") endif() -# Set native instruction set compiler flag -if(WITH_NATIVE_INSTRUCTIONS AND DEFINED NATIVEFLAG) - # Apply flag to all source files and compilation checks - add_compile_options(${NATIVEFLAG}) -endif() - # # Check for standard/system includes # From 3553873d425a8ec4a5f94820b8becfe821e2658e Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 14 Aug 2023 14:12:55 +0200 Subject: [PATCH 715/798] Add CPack capability --- CMakeLists.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 322d7fc6df..1e4d82237f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1241,3 +1241,20 @@ endif() add_feature_info(INSTALL_UTILS INSTALL_UTILS "Copy minigzip and minideflate during install") FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) + +#============================================================================ +# CPack +#============================================================================ +set(CPACK_GENERATOR "TGZ") +set(CPACK_SOURCE_GENERATOR "TGZ") +set(CPACK_SOURCE_IGNORE_FILES .git/ _CPack_Packages/ "${PROJECT_BINARY_DIR}/") + +set(CPACK_PACKAGE_NAME "zlib${SUFFIX}") +set(CPACK_PACKAGE_VERSION ${ZLIB_FULL_VERSION}) +set(CPACK_PACKAGE_DIRECTORY "${PROJECT_BINARY_DIR}/package") + +if("${PROJECT_BINARY_DIR}" STREQUAL "${PROJECT_SOURCE_DIR}") + message(WARNING "Building to source folder is not recommended. Cpack will be unable to generate source package.") +endif() + +include(CPack) From 44cc37f154f3307a035648f9deb5d723bdd1bbe3 Mon Sep 17 00:00:00 2001 From: Paul Marquess Date: Mon, 21 Aug 2023 13:41:24 -0700 Subject: [PATCH 716/798] Remove duplicate "the" in zlib.h. --- zlib-ng.h.in | 2 +- zlib.h.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 8ec2f04a55..353f0f44cb 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -720,7 +720,7 @@ int32_t zng_deflateParams(zng_stream *strm, int32_t level, int32_t strategy); Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). + applied to the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if diff --git a/zlib.h.in b/zlib.h.in index 45b6c8e092..4367c1c4be 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -734,7 +734,7 @@ Z_EXTERN int Z_EXPORT deflateParams(z_stream *strm, int level, int strategy); Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be - applied to the the data compressed after deflateParams(). + applied to the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if From 3bef206e2cfce57ed3e923ecbc1c2209af89dd73 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Mon, 21 Aug 2023 13:43:46 -0700 Subject: [PATCH 717/798] Correct comment in zlib.h on os setting in gzip header. The comment said that the os is set to 255, when in fact it has been set to the current os since zlib 1.2.3. Or at least our best guess at the os made at compile time. --- zlib-ng.h.in | 5 +++-- zlib.h.in | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 353f0f44cb..5d8f0a90a6 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -807,8 +807,9 @@ int32_t zng_deflateSetHeader(zng_stream *strm, zng_gz_headerp head); gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. diff --git a/zlib.h.in b/zlib.h.in index 4367c1c4be..ad58e21102 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -816,8 +816,9 @@ Z_EXTERN int Z_EXPORT deflateSetHeader(z_stream *strm, gz_headerp head); gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). + the time set to zero, and os set to the current operating system, with no + extra, name, or comment fields. The gzip header is returned to the default + state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. From 10f51f6096429f20c189b7e8b603fd32478a0a71 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Mon, 21 Aug 2023 13:45:31 -0700 Subject: [PATCH 718/798] Document in zlib.h the initialization of stream fields by the Init and Reset functions. --- zlib-ng.h.in | 12 +++++++----- zlib.h.in | 12 +++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 5d8f0a90a6..de2d4fade1 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -228,8 +228,8 @@ int32_t zng_deflateInit(zng_stream *strm, int32_t level); /* Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to NULL, deflateInit updates them to use default - allocation functions. + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. total_in, total_out, adler, and msg are initialized. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all @@ -381,8 +381,9 @@ int32_t zng_inflateInit(zng_stream *strm); the caller. In the current version of inflate, the provided input is not read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the - first call). If zalloc and zfree are set to NULL, inflateInit updates - them to use default allocation functions. + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, or Z_STREAM_ERROR if the parameters are invalid, such as a null @@ -688,7 +689,7 @@ int32_t zng_deflateReset(zng_stream *strm); This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been - set unchanged. + set unchanged. total_in, total_out, adler, and msg are initialized. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). @@ -945,6 +946,7 @@ int32_t zng_inflateReset(zng_stream *strm); This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). diff --git a/zlib.h.in b/zlib.h.in index ad58e21102..69b7d424e3 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -239,8 +239,8 @@ Z_EXTERN int Z_EXPORT deflateInit (z_stream *strm, int level); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to NULL, deflateInit updates them to use default - allocation functions. + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. total_in, total_out, adler, and msg are initialized. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all @@ -392,8 +392,9 @@ Z_EXTERN int Z_EXPORT inflateInit (z_stream *strm); the caller. In the current version of inflate, the provided input is not read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the - first call). If zalloc and zfree are set to NULL, inflateInit updates - them to use default allocation functions. + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. total_in, total_out, adler, and + msg are initialized. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the @@ -703,7 +704,7 @@ Z_EXTERN int Z_EXPORT deflateReset(z_stream *strm); This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been - set unchanged. + set unchanged. total_in, total_out, adler, and msg are initialized. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). @@ -951,6 +952,7 @@ Z_EXTERN int Z_EXPORT inflateReset(z_stream *strm); This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. + total_in, total_out, adler, and msg are initialized. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being NULL). From faf6cf70cd622b66b1599c36d192601f95780fb9 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Mon, 21 Aug 2023 13:47:27 -0700 Subject: [PATCH 719/798] Avoid compiler complaints if _TIME_BITS defined when building zlib. zlib does not use time_t, so _TIME_BITS is irrelevant. However it may be defined anyway as part of a sledgehammer indiscriminately applied to all builds. --- gzguts.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gzguts.h b/gzguts.h index fe09270639..a663844b69 100644 --- a/gzguts.h +++ b/gzguts.h @@ -9,9 +9,8 @@ # ifndef _LARGEFILE_SOURCE # define _LARGEFILE_SOURCE 1 # endif -# ifdef _FILE_OFFSET_BITS -# undef _FILE_OFFSET_BITS -# endif +# undef _FILE_OFFSET_BITS +# undef _TIME_BITS #endif #if defined(HAVE_VISIBILITY_INTERNAL) From 135cdad8ca64ec38407fcd3515515574f2015dcf Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Mon, 21 Aug 2023 13:48:56 -0700 Subject: [PATCH 720/798] Fix bug when gzungetc() is used immediately after gzopen(). --- gzread.c.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gzread.c.in b/gzread.c.in index 67a21a3e4d..1fc7b370fd 100644 --- a/gzread.c.in +++ b/gzread.c.in @@ -445,6 +445,10 @@ int Z_EXPORT PREFIX(gzungetc)(int c, gzFile file) { return -1; state = (gz_state *)file; + /* in case this was just opened, set up the input buffer */ + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + /* check that we're reading and that there's no (serious) error */ if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR)) return -1; From fe44e1f1dfa7698b8f42a6eeb392548d3fdf9a81 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Mon, 21 Aug 2023 13:49:50 -0700 Subject: [PATCH 721/798] Fix bug when using gzflush() with a very small buffer. --- gzlib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gzlib.c b/gzlib.c index e1290fc611..e613837efb 100644 --- a/gzlib.c +++ b/gzlib.c @@ -274,8 +274,8 @@ int Z_EXPORT PREFIX(gzbuffer)(gzFile file, unsigned size) { /* check and set requested size */ if ((size << 1) < size) return -1; /* need to be able to double it */ - if (size < 2) - size = 2; /* need two bytes to check magic header */ + if (size < 8) + size = 8; /* needed to behave well with flushing */ state->want = size; return 0; } From 830dc147efe3f5e4e914025a972b07af6cd83143 Mon Sep 17 00:00:00 2001 From: Mark Adler Date: Mon, 21 Aug 2023 13:50:29 -0700 Subject: [PATCH 722/798] Clarify requirement in zlib.h to avoid multiple flush markers. --- zlib-ng.h.in | 4 ++-- zlib.h.in | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zlib-ng.h.in b/zlib-ng.h.in index de2d4fade1..b3fdf87d9c 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -318,8 +318,8 @@ int32_t zng_deflate(zng_stream *strm, int32_t flush); with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was diff --git a/zlib.h.in b/zlib.h.in index 69b7d424e3..8e69214775 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -330,8 +330,8 @@ Z_EXTERN int Z_EXPORT deflate(z_stream *strm, int flush); with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. + avail_out is greater than six when the flush marker begins, in order to avoid + repeated flush markers upon calling deflate() again when avail_out == 0. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was From 7030ac70cb705d3790a943b600c3bcbb67689f44 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 22 Aug 2023 20:37:16 -0700 Subject: [PATCH 723/798] Updated zlib compat version to 1.3. --- zlib.h.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/zlib.h.in b/zlib.h.in index 8e69214775..ed25ccc646 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -57,11 +57,11 @@ extern "C" { #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ -#define ZLIB_VERSION "1.2.13.zlib-ng" -#define ZLIB_VERNUM 0x12df +#define ZLIB_VERSION "1.3.0.zlib-ng" +#define ZLIB_VERNUM 0x130f #define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 13 +#define ZLIB_VER_MINOR 3 +#define ZLIB_VER_REVISION 0 #define ZLIB_VER_SUBREVISION 15 /* 15=fork (0xf) */ /* From e14004fa063fa9d63b394fc4e9f43b18c6412502 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 21 Aug 2023 10:13:10 +0200 Subject: [PATCH 724/798] use dash not bash for portability --- configure | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/configure b/configure index 71b3074371..aa427a4027 100755 --- a/configure +++ b/configure @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/bin/sh # configure script for zlib. # # Normally configure builds both a static and a shared library. @@ -243,7 +243,7 @@ int main() {return getchar();} EOF cc=${CC-${CROSS_PREFIX}gcc} -echo -n "Checking for compiler... " | tee -a configure.log +printf "Checking for compiler... " | tee -a configure.log case "$cc" in *gcc*) gcc=1 ;; *clang*) gcc=1 ;; @@ -361,7 +361,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then SFLAGS="${SFLAGS} -DNDEBUG" fi if test -z "$uname"; then - uname=$((uname -s || echo unknown) 2>/dev/null) + uname=$( (uname -s || echo unknown) 2>/dev/null) fi case "$uname" in Linux* | linux* | GNU | GNU/* | solaris*) @@ -443,7 +443,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then fi RC="${CROSS_PREFIX}windres" RCFLAGS="-I ${BUILDDIR}" - if [ "$CC" == "mingw32-gcc" ]; then + if [ "$CC" = "mingw32-gcc" ]; then case $ARCH in i386 | i486 | i586 | i686) RCFLAGS="${RCFLAGS} -F pe-i386";; esac; @@ -458,7 +458,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then HP-UX*) LDSHARED=${LDSHARED-"$cc"} LDSHAREDFLAGS="-shared" - case $((uname -m || echo unknown) 2>/dev/null) in + case $( (uname -m || echo unknown) 2>/dev/null) in ia64) shared_ext='.so' SHAREDLIB='${LIBNAME}.so' ;; @@ -494,14 +494,14 @@ else gcc=0 echo "$CC" | tee -a configure.log if test -z "$uname"; then - uname=$((uname -sr || echo unknown) 2>/dev/null) + uname=$( (uname -sr || echo unknown) 2>/dev/null) fi case "$uname" in HP-UX*) SFLAGS=${CFLAGS-"-O +z"} CFLAGS=${CFLAGS-"-O"} LDSHARED=${LDSHARED-"ld"} LDSHAREDFLAGS="-b" - case $((uname -m || echo unknown) 2>/dev/null) in + case $( (uname -m || echo unknown) 2>/dev/null) in ia64) shared_ext='.so' SHAREDLIB='${LIBNAME}.so' ;; @@ -598,7 +598,7 @@ extern int getchar(); int hello() {return getchar();} EOF if test $shared -eq 1; then - echo -n "Checking for shared library support... " | tee -a configure.log + printf "Checking for shared library support... " | tee -a configure.log # we must test in two steps (cc then ld), required at least on SunOS 4.x if try $CC -w -c $SFLAGS $test.c && try $LDSHARED $LDSHAREDFLAGS $LDFLAGS -o $test$shared_ext $test.o $LDSHAREDLIBC; then @@ -755,7 +755,7 @@ fi # Rename @ZLIB_SYMBOL_PREFIX@ to $symbol_prefix in gzread.c, zlib.h and zlib_name_mangling.h sed < $SRCDIR/gzread.c.in "s/@ZLIB_SYMBOL_PREFIX@/$symbol_prefix/g" > gzread.c sed < $SRCDIR/zlib${SUFFIX}.h.in "s/@ZLIB_SYMBOL_PREFIX@/$symbol_prefix/g" > zlib${SUFFIX}.h -if [[ ! -z $symbol_prefix ]]; then +if [ ! -z "$symbol_prefix" ]; then sed < $SRCDIR/zlib_name_mangling${SUFFIX}.h.in "s/@ZLIB_SYMBOL_PREFIX@/$symbol_prefix/g" > zlib_name_mangling${SUFFIX}.h else # symbol_prefix is not set, copy the empty mangling header @@ -785,7 +785,7 @@ fi echo >> configure.log # check for ptrdiff_t and save result in zconf.h -echo -n "Checking for ptrdiff_t... " | tee -a configure.log +printf "Checking for ptrdiff_t... " | tee -a configure.log cat > $test.c < int fun(ptrdiff_t *a) { (void)a; return 0; } @@ -797,7 +797,7 @@ else sed < zconf${SUFFIX}.h "/^#ifdef NEED_PTRDIFF_T.* may be/s/def NEED_PTRDIFF_T\(.*\) may be/ 1\1 was/" > zconf${SUFFIX}.temp.h mv zconf${SUFFIX}.temp.h zconf${SUFFIX}.h - echo -n "Checking for sizeof(void *)... " | tee -a configure.log + printf "Checking for sizeof(void *)... " | tee -a configure.log cat > $test.c < #define COMPILE_TIME_ASSERT(pred) struct s { int x: (pred) ? 1 : -1; } @@ -835,7 +835,7 @@ if test $compat -eq 1; then esac fi -if [[ ! -z $DEFFILE ]]; then +if [ ! -z "$DEFFILE" ]; then mkdir -p win32 sed < $SRCDIR/$DEFFILE.in "s/@ZLIB_SYMBOL_PREFIX@/$symbol_prefix/g" > $DEFFILE fi @@ -1447,14 +1447,14 @@ EOF check_vgfma_intrinsics() { # Check whether "VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE" intrinsic is available - echo -n "Checking for -mzarch... " | tee -a configure.log + printf "Checking for -mzarch... " | tee -a configure.log if try $CC -x c -c /dev/null -o /dev/null -mzarch; then echo Yes. | tee -a configure.log vgfmaflag="${vgfmaflag} -mzarch" else echo No. | tee -a configure.log fi - echo -n "Checking for -fzvector... " | tee -a configure.log + printf "Checking for -fzvector... " | tee -a configure.log if try $CC -x c -c /dev/null -o /dev/null -fzvector; then echo Yes. | tee -a configure.log vgfmaflag="${vgfmaflag} -fzvector" @@ -1471,7 +1471,7 @@ int main(void) { return c[0]; } EOF - echo -n "Checking for VGFMA support... " | tee -a configure.log + printf "Checking for VGFMA support... " | tee -a configure.log if try $CC -c $CFLAGS $vgfmaflag $test.c; then HAVE_VGFMA_INTRIN=1 echo "Yes." | tee -a configure.log @@ -2111,11 +2111,11 @@ for file in $SRCDIR/*.c $SRCDIR/test/*.c $SRCDIR/test/fuzz/*.c $SRCDIR/$ARCHDIR/ # Check that the include file exists in the current dir, # otherwise it may be one of the system include header. if test -e $SRCDIR/$i; then - echo -n " \$(SRCDIR)/$i" + printf " \$(SRCDIR)/$i" fi # We also need to check whether the include file is in the ARCHDIR. if test -e $SRCDIR/$ARCHDIR/$i; then - echo -n " \$(SRCDIR)/$ARCHDIR/$i" + printf " \$(SRCDIR)/$ARCHDIR/$i" fi done) obj=$(basename $(echo $file | sed -e 's/\.c/\.o/g' -e 's#^\./##g')) @@ -2188,11 +2188,11 @@ for file in $SRCDIR/$ARCHDIR/*.c; do # Check that the include file exists in the current dir, # otherwise it may be one of the system include header. if test -e $SRCDIR/$i; then - echo -n " \$(SRCTOP)/$i" + printf " \$(SRCTOP)/$i" fi # We also need to check whether the include file is in the ARCHDIR. if test -e $SRCDIR/$ARCHDIR/$i; then - echo -n " \$(SRCDIR)/$i" + printf " \$(SRCDIR)/$i" fi done) obj=$(basename $(echo $file | sed -e 's/\.c/\.o/g' -e 's#^\./##g')) From 74ac49dbf3444ac9826d2344cb3ad667a015ac12 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 21 Aug 2023 12:19:36 +0200 Subject: [PATCH 725/798] also fix SC2288 --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index aa427a4027..ea6d163be0 100755 --- a/configure +++ b/configure @@ -563,7 +563,7 @@ if ($CC -c $CFLAGS $test.c) 2>/dev/null; then try() { show $* - test "$(\( $* \) 2>&1 | tee -a configure.log)" = "" + test "$( ($*) 2>&1 | tee -a configure.log)" = "" } echo - using any output from compiler to indicate an error >> configure.log else From 2f15a6961a75174cd95142816b58ad5fc655c209 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 21 Aug 2023 12:27:35 +0200 Subject: [PATCH 726/798] $@ over $* --- configure | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configure b/configure index ea6d163be0..c146a1fd2e 100755 --- a/configure +++ b/configure @@ -227,13 +227,13 @@ test=ztest$$ # put arguments in log, also put test file in log if used in arguments show() { - case "$*" in + case "$@" in *$test.c*) echo "=== $test.c ===" >> configure.log cat $test.c >> configure.log echo "===" >> configure.log;; esac - echo $* >> configure.log + echo "$@" >> configure.log } # check for gcc vs. cc and set compile and link flags based on the system identified by uname @@ -562,15 +562,15 @@ EOF if ($CC -c $CFLAGS $test.c) 2>/dev/null; then try() { - show $* - test "$( ($*) 2>&1 | tee -a configure.log)" = "" + show "$@" + test "$( ("$@") 2>&1 | tee -a configure.log)" = "" } echo - using any output from compiler to indicate an error >> configure.log else try() { - show $* - ( $* ) >> configure.log 2>&1 + show "$@" + ( "$@" ) >> configure.log 2>&1 ret=$? if test $ret -ne 0; then echo "(exit code $ret)" >> configure.log From b7ac8479353f8e64c71cace5f8f76494fed6fad9 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 21 Aug 2023 11:10:29 +0200 Subject: [PATCH 727/798] configure: ensure instructions are not optimized out before assembler is run --- configure | 107 +++++++++++++++--------------------------------------- 1 file changed, 30 insertions(+), 77 deletions(-) diff --git a/configure b/configure index c146a1fd2e..74290c6a55 100755 --- a/configure +++ b/configure @@ -994,12 +994,8 @@ fi # Check for __builtin_ctz() support in compiler cat > $test.c << EOF -int main(void) { - unsigned int zero = 0; - long test = __builtin_ctz(zero); - (void)test; - return 0; -} +long f(unsigned int x) { return __builtin_ctz(x); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} $test.c $LDSHAREDLIBC; then echo "Checking for __builtin_ctz ... Yes." | tee -a configure.log @@ -1011,12 +1007,8 @@ fi # Check for __builtin_ctzll() support in compiler cat > $test.c << EOF -int main(void) { - unsigned long long zero = 0; - long test = __builtin_ctzll(zero); - (void)test; - return 0; -} +long f(unsigned long long x) { return __builtin_ctzll(x); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} $test.c $LDSHAREDLIBC; then echo "Checking for __builtin_ctzll ... Yes." | tee -a configure.log @@ -1030,13 +1022,11 @@ check_avx2_intrinsics() { # Check whether compiler supports AVX2 intrinsics cat > $test.c << EOF #include -int main(void) { - __m256i x = _mm256_set1_epi16(2); +__m256i f(__m256i x) { const __m256i y = _mm256_set1_epi16(1); - x = _mm256_subs_epu16(x, y); - (void)x; - return 0; + return _mm256_subs_epu16(x, y); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${avx2flag} $test.c; then echo "Checking for AVX2 intrinsics ... Yes." | tee -a configure.log @@ -1051,16 +1041,11 @@ check_avx512_intrinsics() { # Check whether compiler supports AVX512 intrinsics cat > $test.c << EOF #include -int main(void) { - __m512i x = _mm512_set1_epi8(2); - const __m512i y = _mm512_set_epi32(0x1020304, 0x5060708, 0x90a0b0c, 0xd0e0f10, - 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, - 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, - 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40); - x = _mm512_sub_epi8(x, y); - (void)x; - return 0; +__m512i f(__m512i y) { + __m512i x = _mm512_set1_epi8(2); + return _mm512_sub_epi8(x, y); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${avx512flag} $test.c; then echo "Checking for AVX512 intrinsics ... Yes." | tee -a configure.log @@ -1104,17 +1089,11 @@ check_avx512vnni_intrinsics() { # Check whether compiler supports AVX512-VNNI intrinsics cat > $test.c << EOF #include -int main(void) { - __m512i x = _mm512_set1_epi8(2); - const __m512i y = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64); +__m512i f(__m512i x, __m512i y) { __m512i z = _mm512_setzero_epi32(); - z = _mm512_dpbusd_epi32(z, x, y); - (void)z; - return 0; + return _mm512_dpbusd_epi32(z, x, y); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${avx512vnniflag} $test.c; then echo "Checking for AVX512VNNI intrinsics ... Yes." | tee -a configure.log @@ -1129,12 +1108,8 @@ check_mask_intrinsics() { # Check whether compiler supports AVX512 k-mask intrinsics cat > $test.c << EOF #include -int main(void) { - __mmask16 a = 0xFF; - a = _knot_mask16(a); - (void)a; - return 0; -} +__mmask16 f(__mmask16 x) { return _knot_mask16(x); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${avx512flag} $test.c; then echo "Checking for AVX512 k-mask intrinsics ... Yes." | tee -a configure.log @@ -1201,12 +1176,8 @@ check_neon_ld4_intrinsics() { #else # include #endif -int main(void) { - int stack_var[16]; - int32x4x4_t v = vld1q_s32_x4(stack_var); - (void)v; - return 0; -} +int32x4x4_t f(int var[16]) { return vld1q_s32_x4(var); } +int main(void) { return 0; } EOF if try $CC -c $CFLAGS $neonflag $test.c; then NEON_HAS_LD4=1 @@ -1222,13 +1193,8 @@ check_pclmulqdq_intrinsics() { cat > $test.c << EOF #include #include -int main(void) { - __m128i a = _mm_setzero_si128(); - __m128i b = _mm_setzero_si128(); - __m128i c = _mm_clmulepi64_si128(a, b, 0x10); - (void)c; - return 0; -} +__m128i f(__m128i a, __m128i b) { return _mm_clmulepi64_si128(a, b, 0x10); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${pclmulflag} $test.c; then echo "Checking for PCLMULQDQ intrinsics ... Yes." | tee -a configure.log @@ -1269,9 +1235,8 @@ check_xsave_intrinsics() { #else # include #endif -int main(void) { - return _xgetbv(0); -} +unsigned int f(unsigned int a) { return _xgetbv(a); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${xsaveflag} $test.c; then echo "Checking for XSAVE intrinsics ... Yes." | tee -a configure.log @@ -1386,11 +1351,8 @@ check_sse2_intrinsics() { # Check whether compiler supports SSE2 intrinsics cat > $test.c << EOF #include -int main(void) { - __m128i zero = _mm_setzero_si128(); - (void)zero; - return 0; -} +__m128i f(__m128i x, __m128i y) { return _mm_sad_epu8(x, y); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${sse2flag} $test.c; then echo "Checking for SSE2 intrinsics ... Yes." | tee -a configure.log @@ -1405,13 +1367,8 @@ check_sse42_intrinsics() { # Check whether compiler supports SSE4.2 intrinsics cat > $test.c << EOF #include -int main(void) { - unsigned crc = 0; - char c = 'c'; - crc = _mm_crc32_u32(crc, c); - (void)crc; - return 0; -} +unsigned int f(unsigned int a, unsigned int b) { return _mm_crc32_u32(a, b); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then echo "Checking for SSE4.2 intrinsics ... Yes." | tee -a configure.log @@ -1426,15 +1383,11 @@ check_ssse3_intrinsics() { # Check whether compiler supports SSSE3 intrinsics cat > $test.c << EOF #include -int main(void) -{ - __m128i u, v, w; - u = _mm_set1_epi32(1); - v = _mm_set1_epi32(2); - w = _mm_hadd_epi32(u, v); - (void)w; - return 0; +__m128i f(__m128i u) { + __m128i v = _mm_set1_epi32(1); + return _mm_hadd_epi32(u, v); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${ssse3flag} $test.c; then echo "Checking for SSSE3 intrinsics ... Yes." | tee -a configure.log From cf029967c2956cb2d40d04da86d0f4d6b48d4879 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 21 Aug 2023 11:27:01 +0200 Subject: [PATCH 728/798] another --- configure | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/configure b/configure index 74290c6a55..e54db18ab0 100755 --- a/configure +++ b/configure @@ -1210,13 +1210,11 @@ check_vpclmulqdq_intrinsics() { cat > $test.c << EOF #include #include -int main(void) { - __m512i a = _mm512_setzero_si512(); +__m512i f(__m512i a) { __m512i b = _mm512_setzero_si512(); - __m512i c = _mm512_clmulepi64_epi128(a, b, 0x10); - (void)c; - return 0; + return _mm512_clmulepi64_epi128(a, b, 0x10); } +int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${vpclmulflag} $test.c; then echo "Checking for VPCLMULQDQ intrinsics ... Yes." | tee -a configure.log From 120fe069d33ccd38107852039f339a6923349186 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 21 Aug 2023 13:14:32 +0200 Subject: [PATCH 729/798] Do the same for detect-intrinsics.cmake --- cmake/detect-intrinsics.cmake | 118 ++++++++++++---------------------- 1 file changed, 40 insertions(+), 78 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index f10c51774b..d8a3c285df 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -73,28 +73,19 @@ macro(check_avx512_intrinsics) set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include - int main(void) { - __m512i x = _mm512_set1_epi8(2); - const __m512i y = _mm512_set_epi32(0x1020304, 0x5060708, 0x90a0b0c, 0xd0e0f10, - 0x11121314, 0x15161718, 0x191a1b1c, 0x1d1e1f20, - 0x21222324, 0x25262728, 0x292a2b2c, 0x2d2e2f30, - 0x31323334, 0x35363738, 0x393a3b3c, 0x3d3e3f40); - x = _mm512_sub_epi8(x, y); - (void)x; - return 0; - }" + __m512i f(__m512i y) { + __m512i x = _mm512_set1_epi8(2); + return _mm512_sub_epi8(x, y); + } + int main(void) { return 0; }" HAVE_AVX512_INTRIN ) # Evidently both GCC and clang were late to implementing these check_c_source_compile_or_run( "#include - int main(void) { - __mmask16 a = 0xFF; - a = _knot_mask16(a); - (void)a; - return 0; - }" + __mmask16 f(__mmask16 x) { return _knot_mask16(x); } + int main(void) { return 0; }" HAVE_MASK_INTRIN ) set(CMAKE_REQUIRED_FLAGS) @@ -128,17 +119,11 @@ macro(check_avx512vnni_intrinsics) set(CMAKE_REQUIRED_FLAGS "${AVX512VNNIFLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include - int main(void) { - __m512i x = _mm512_set1_epi8(2); - const __m512i y = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64); + __m512i f(__m512i x, __m512i y) { __m512i z = _mm512_setzero_epi32(); - z = _mm512_dpbusd_epi32(z, x, y); - (void)z; - return 0; - }" + return _mm512_dpbusd_epi32(z, x, y); + } + int main(void) { return 0; }" HAVE_AVX512VNNI_INTRIN ) set(CMAKE_REQUIRED_FLAGS) @@ -162,13 +147,11 @@ macro(check_avx2_intrinsics) set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include - int main(void) { - __m256i x = _mm256_set1_epi16(2); + __m256i f(__m256i x) { const __m256i y = _mm256_set1_epi16(1); - x = _mm256_subs_epu16(x, y); - (void)x; - return 0; - }" + return _mm256_subs_epu16(x, y); + } + int main(void) { return 0; }" HAVE_AVX2_INTRIN ) set(CMAKE_REQUIRED_FLAGS) @@ -215,12 +198,8 @@ macro(check_neon_ld4_intrinsics) #else # include #endif - int main(void) { - int stack_var[16]; - int32x4x4_t v = vld1q_s32_x4(stack_var); - (void)v; - return 0; - }" + int32x4x4_t f(int var[16]) { return vld1q_s32_x4(var); } + int main(void) { return 0; }" NEON_HAS_LD4) set(CMAKE_REQUIRED_FLAGS) endmacro() @@ -237,13 +216,9 @@ macro(check_pclmulqdq_intrinsics) set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include - int main(void) { - __m128i a = _mm_setzero_si128(); - __m128i b = _mm_setzero_si128(); - __m128i c = _mm_clmulepi64_si128(a, b, 0x10); - (void)c; - return 0; - }" + #include + __m128i f(__m128i a, __m128i b) { return _mm_clmulepi64_si128(a, b, 0x10); } + int main(void) { return 0; }" HAVE_PCLMULQDQ_INTRIN ) set(CMAKE_REQUIRED_FLAGS) @@ -263,13 +238,12 @@ macro(check_vpclmulqdq_intrinsics) set(CMAKE_REQUIRED_FLAGS "${VPCLMULFLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include - int main(void) { - __m512i a = _mm512_setzero_si512(); + #include + __m512i f(__m512i a) { __m512i b = _mm512_setzero_si512(); - __m512i c = _mm512_clmulepi64_epi128(a, b, 0x10); - (void)c; - return 0; - }" + return _mm512_clmulepi64_epi128(a, b, 0x10); + } + int main(void) { return 0; }" HAVE_VPCLMULQDQ_INTRIN ) set(CMAKE_REQUIRED_FLAGS) @@ -442,11 +416,8 @@ macro(check_sse2_intrinsics) set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include - int main(void) { - __m128i zero = _mm_setzero_si128(); - (void)zero; - return 0; - }" + __m128i f(__m128i x, __m128i y) { return _mm_sad_epu8(x, y); } + int main(void) { return 0; }" HAVE_SSE2_INTRIN ) set(CMAKE_REQUIRED_FLAGS) @@ -468,14 +439,11 @@ macro(check_ssse3_intrinsics) set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include - int main(void) { - __m128i u, v, w; - u = _mm_set1_epi32(1); - v = _mm_set1_epi32(2); - w = _mm_hadd_epi32(u, v); - (void)w; - return 0; - }" + __m128i f(__m128i u) { + __m128i v = _mm_set1_epi32(1); + return _mm_hadd_epi32(u, v); + } + int main(void) { return 0; }" HAVE_SSSE3_INTRIN ) endmacro() @@ -496,13 +464,8 @@ macro(check_sse42_intrinsics) set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include - int main(void) { - unsigned crc = 0; - char c = 'c'; - crc = _mm_crc32_u32(crc, c); - (void)crc; - return 0; - }" + unsigned int f(unsigned int a, unsigned int b) { return _mm_crc32_u32(a, b); } + int main(void) { return 0; }" HAVE_SSE42_INTRIN ) set(CMAKE_REQUIRED_FLAGS) @@ -540,13 +503,12 @@ macro(check_xsave_intrinsics) set(CMAKE_REQUIRED_FLAGS "${XSAVEFLAG} ${NATIVEFLAG}") check_c_source_compiles( "#ifdef _WIN32 - # include - #else - # include - #endif - int main(void) { - return _xgetbv(0); - }" + # include + #else + # include + #endif + unsigned int f(unsigned int a) { return _xgetbv(a); } + int main(void) { return 0; }" HAVE_XSAVE_INTRIN FAIL_REGEX "not supported") set(CMAKE_REQUIRED_FLAGS) endmacro() From ca2d4e5adcba46931915519814f001b8eb7cde6a Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Tue, 29 Aug 2023 14:31:12 +0200 Subject: [PATCH 730/798] cast _xgetbv to int to silence conversion warning --- cmake/detect-intrinsics.cmake | 2 +- configure | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index d8a3c285df..bc938fc234 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -507,7 +507,7 @@ macro(check_xsave_intrinsics) #else # include #endif - unsigned int f(unsigned int a) { return _xgetbv(a); } + unsigned int f(unsigned int a) { return (int) _xgetbv(a); } int main(void) { return 0; }" HAVE_XSAVE_INTRIN FAIL_REGEX "not supported") set(CMAKE_REQUIRED_FLAGS) diff --git a/configure b/configure index e54db18ab0..1c3c5da73a 100755 --- a/configure +++ b/configure @@ -1233,7 +1233,7 @@ check_xsave_intrinsics() { #else # include #endif -unsigned int f(unsigned int a) { return _xgetbv(a); } +unsigned int f(unsigned int a) { return (int) _xgetbv(a); } int main(void) { return 0; } EOF if try ${CC} ${CFLAGS} ${xsaveflag} $test.c; then From b3643707ab92b6515878b23082f1303fd61af01d Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Mon, 28 Aug 2023 19:48:56 -0700 Subject: [PATCH 731/798] Allow ACLE to be enabled on all ARM architecture versions --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e4d82237f..cc42f1a33a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -615,7 +615,7 @@ if(WITH_OPTIM) endif() list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm_features.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/arm_features.c) - if(WITH_ACLE AND NOT "${ARCH}" MATCHES "armv[2-7]") + if(WITH_ACLE) check_acle_compiler_flag() if(HAVE_ACLE_FLAG) add_definitions(-DARM_ACLE) @@ -715,7 +715,7 @@ if(WITH_OPTIM) add_definitions(-DRISCV_RVV) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/riscv_features.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c) - # FIXME: we will not set compile flags for riscv_features.c when + # FIXME: we will not set compile flags for riscv_features.c when # the kernels update hwcap or hwprobe for riscv set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/adler32_rvv.c ${ARCHDIR}/compare256_rvv.c ${ARCHDIR}/slide_hash_rvv.c) list(APPEND ZLIB_ARCH_SRCS ${RVV_SRCS}) From f0ffa3d57af0323c0073cf775f02780a16982a1e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 8 Sep 2023 10:05:43 -0700 Subject: [PATCH 732/798] Clean up detection on ARM variants and allow ACLE on all ARM archs. --- configure | 278 ++++++++++++++++-------------------------------------- 1 file changed, 80 insertions(+), 198 deletions(-) diff --git a/configure b/configure index 1c3c5da73a..52e72f51a1 100755 --- a/configure +++ b/configure @@ -317,17 +317,9 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then ARCH=$CC_ARCH fi ;; arm | armeb) - ARCH=arm + ARCH=arm if test "${uname}" = "eabi"; then - # No ACLE support uname=arm - if test $buildacle -eq 1; then - echo ACLE support not available - buildacle=0 - fi - fi - if test $buildacle -eq 1; then - ARCH=armv8-a+crc fi ;; armv8l) ARCH=armv8-a ;; @@ -1128,14 +1120,13 @@ EOF if try $CC -c $CFLAGS -march=armv8-a+crc $test.c; then ACLE_AVAILABLE=1 echo "Check whether -march=armv8-a+crc works ... Yes." | tee -a configure.log + acleflag="-march=armv8-a+crc" else echo "Check whether -march=armv8-a+crc works ... No." | tee -a configure.log if try $CC -c $CFLAGS -march=armv8-a+crc+simd $test.c; then ACLE_AVAILABLE=1 echo "Check whether -march=armv8-a+crc+simd works ... Yes." | tee -a configure.log - if test "$ARCH" = "armv8-a+crc"; then - ARCH=armv8-a+crc+simd - fi + acleflag="-march=armv8-a+crc+simd" else ACLE_AVAILABLE=0 echo "Check whether -march=armv8-a+crc+simd works ... No." | tee -a configure.log @@ -1144,7 +1135,12 @@ EOF } check_neon_compiler_flag() { - # Check whether -mfpu=neon is available on ARM processors. + if test "$ARCH" = "aarch64"; then + neonflag="-march=armv8-a+simd" + else + neonflag="-mfpu=neon" + fi + # Check whether neon flag is available on ARM processors. cat > $test.c << EOF #if defined(_M_ARM64) || defined(_M_ARM64EC) # include @@ -1153,23 +1149,16 @@ check_neon_compiler_flag() { #endif int main() { return 0; } EOF - if try $CC -c $CFLAGS -mfpu=neon $test.c; then - MFPU_NEON_AVAILABLE=1 - echo "Check whether -mfpu=neon is available ... Yes." | tee -a configure.log + if try $CC -c $CFLAGS $neonflag $test.c; then + NEON_AVAILABLE=1 + echo "Check whether $neonflag is available ... Yes." | tee -a configure.log else - MFPU_NEON_AVAILABLE=0 - echo "Check whether -mfpu=neon is available ... No." | tee -a configure.log + NEON_AVAILABLE=0 + echo "Check whether $neonflag is available ... No." | tee -a configure.log fi } check_neon_ld4_intrinsics() { - if test $buildneon -eq 1; then - if test "$CC_ARCH" = "aarch64" || test "$CC_ARCH" = "aarch64_be" || test "$CC_ARCH" = "arm64"; then - neonflag="-march=armv8-a+simd" - elif test $MFPU_NEON_AVAILABLE -eq 1; then - neonflag="-mfpu=neon" - fi - fi cat > $test.c << EOF #if defined(_M_ARM64) || defined(_M_ARM64EC) # include @@ -1563,8 +1552,16 @@ case "${ARCH}" in ;; # ARM specific optimizations - arm*) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=arm + arm* | aarch64) + case "${ARCH}" in + arm*) + [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=arm + ;; + aarch64) + [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=aarch64 + ;; + esac + ARCHDIR=arch/arm if test $without_optimizations -eq 0; then @@ -1574,52 +1571,69 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} arm_features.lo" if test $LINUX -eq 1; then - cat > $test.c < $test.c < int main() { return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); } EOF - if try $CC -c $CFLAGS $test.c; then - CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" - SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" - else - cat > $test.c < $test.c < #include int main() { return (getauxval(AT_HWCAP2) & HWCAP2_CRC32); } +EOF + if try $CC -c $CFLAGS $test.c; then + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32 -DARM_ASM_HWCAP" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32 -DARM_ASM_HWCAP" + else + echo "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + fi + fi + else + cat > $test.c < +int main() { + return (getauxval(AT_HWCAP) & HWCAP_CRC32); +} EOF if try $CC -c $CFLAGS $test.c; then - CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32 -DARM_ASM_HWCAP" - SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32 -DARM_ASM_HWCAP" + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" else - echo "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + echo "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log fi fi - cat > $test.c < $test.c < int main() { return (getauxval(AT_HWCAP) & HWCAP_ARM_NEON); } EOF - if try $CC -c $CFLAGS $test.c; then - CFLAGS="${CFLAGS} -DARM_AUXV_HAS_NEON" - SFLAGS="${SFLAGS} -DARM_AUXV_HAS_NEON" - else - cat > $test.c < $test.c < int main() { return (getauxval(AT_HWCAP) & HWCAP_NEON); } EOF - if try $CC -c $CFLAGS $test.c; then - CFLAGS="${CFLAGS} -DARM_AUXV_HAS_NEON" - SFLAGS="${SFLAGS} -DARM_AUXV_HAS_NEON" - else - echo "Neither HWCAP_ARM_NEON or HWCAP_NEON present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + if try $CC -c $CFLAGS $test.c; then + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_NEON" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_NEON" + else + echo "Neither HWCAP_ARM_NEON or HWCAP_NEON present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + fi fi fi fi @@ -1648,169 +1662,37 @@ EOF fi if test $without_optimizations -eq 0; then - check_acle_compiler_flag - check_neon_compiler_flag - check_neon_ld4_intrinsics - fi - - case "${ARCH}" in - armv[345]*) - if test $without_optimizations -eq 0; then - if test $buildacle -eq 1; then - echo ACLE support not available - fi - - if test $buildneon -eq 1; then - echo NEON support not available - fi - fi - ;; - armv6l | armv6hl) - if test $without_optimizations -eq 0; then - if test $buildacle -eq 1; then - echo ACLE support not available - fi - - if test $buildneon -eq 1; then - echo NEON support not available - fi - fi - ;; - arm | armv7*) - if test $without_optimizations -eq 0; then - if test $buildacle -eq 1; then - echo ACLE support not available - fi - - if test $buildneon -eq 1; then - CFLAGS="${CFLAGS} -DARM_NEON" - SFLAGS="${SFLAGS} -DARM_NEON" - - if test $MFPU_NEON_AVAILABLE -eq 1; then - neonflag="-mfpu=neon" - fi + if test $buildacle -eq 1; then + check_acle_compiler_flag - if test $NEON_HAS_LD4 -eq 1; then - CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" - SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" - fi + if test $ACLE_AVAILABLE -eq 1; then + CFLAGS="${CFLAGS} -DARM_ACLE" + SFLAGS="${SFLAGS} -DARM_ACLE" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" - fi + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" fi - ;; - armv8-a | armv8-a+simd) - if test $without_optimizations -eq 0; then - if test $buildacle -eq 1; then - echo ACLE support not available - fi + fi - if test $buildneon -eq 1; then - CFLAGS="${CFLAGS} -DARM_NEON" - SFLAGS="${SFLAGS} -DARM_NEON" + if test $buildneon -eq 1; then + check_neon_compiler_flag - if test $MFPU_NEON_AVAILABLE -eq 1;then - neonflag="-mfpu=neon" - fi + if test $NEON_AVAILABLE -eq 1; then + CFLAGS="${CFLAGS} -DARM_NEON" + SFLAGS="${SFLAGS} -DARM_NEON" - if test $NEON_HAS_LD4 -eq 1; then - CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" - SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" - fi + check_neon_ld4_intrinsics - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" + if test $NEON_HAS_LD4 -eq 1; then + CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" + SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" fi - fi - ;; - armv8-a+crc | armv8-a+crc+simd | armv8.[1234]-a | armv8.[1234]-a+simd) - acleflag="-march=${ARCH}" - - if test $without_optimizations -eq 0; then - if test $ACLE_AVAILABLE -eq 1; then - CFLAGS="${CFLAGS} -DARM_ACLE" - SFLAGS="${SFLAGS} -DARM_ACLE" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" - fi - - if test $buildneon -eq 1; then - CFLAGS="${CFLAGS} -DARM_NEON" - SFLAGS="${SFLAGS} -DARM_NEON" - - if test $MFPU_NEON_AVAILABLE -eq 1;then - neonflag="-mfpu=neon" - fi - - if test $NEON_HAS_LD4 -eq 1; then - CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" - SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" - fi - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" - fi - fi - ;; - esac - - ;; - # 64-bit ARM specific optimizations - aarch64) - [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=aarch64 - ARCHDIR=arch/arm - - ARCH="armv8-a" - - if test $without_optimizations -eq 0; then - check_neon_ld4_intrinsics - - CFLAGS="${CFLAGS} -DARM_FEATURES" - SFLAGS="${SFLAGS} -DARM_FEATURES" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} arm_features.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} arm_features.lo" - - if test $LINUX -eq 1; then - cat > $test.c < -int main() { - return (getauxval(AT_HWCAP) & HWCAP_CRC32); -} -EOF - if try $CC -c $CFLAGS $test.c; then - CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" - SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" - else - echo "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi fi - - if test $NEON_HAS_LD4 -eq 1; then - CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" - SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" - fi - - if test $buildacle -eq 1; then - ARCH="${ARCH}+crc" - CFLAGS="${CFLAGS} -DARM_ACLE" - SFLAGS="${SFLAGS} -DARM_ACLE" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" - fi - - if test $buildneon -eq 1; then - ARCH="${ARCH}+simd" - CFLAGS="${CFLAGS} -DARM_NEON" - SFLAGS="${SFLAGS} -DARM_NEON" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" - fi fi - - neonflag="-march=${ARCH}" - acleflag="-march=${ARCH}" ;; powerpc*) case "${ARCH}" in From 881aa3e60e9030912f3ee550ad57314db0ab9eb3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 29 Aug 2023 01:25:44 -0700 Subject: [PATCH 733/798] Merge both without_optimizations sections in configure for arm. --- configure | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/configure b/configure index 52e72f51a1..b6339fbccb 100755 --- a/configure +++ b/configure @@ -1564,6 +1564,28 @@ case "${ARCH}" in ARCHDIR=arch/arm + cat > $test.c << EOF +int main() { return 0; } +EOF + if try $CC -w -c $SFLAGS $test.c -mfloat-abi=softfp && + try $LDSHARED $LDSHAREDFLAGS $LDFLAGS -o $test$shared_ext $test.o $LDSHAREDLIBC; then + floatabi="-mfloat-abi=softfp" + else + if try $CC -w -c $SFLAGS $test.c -mfloat-abi=hard && + try $LDSHARED $LDSHAREDFLAGS $LDFLAGS -o $test$shared_ext $test.o $LDSHAREDLIBC; then + floatabi="-mfloat-abi=hard" + fi + fi + + if [ -z $floatabi ]; then + echo "ARM floating point arch not auto-detected" | tee -a configure.log + else + echo "ARM floating point arch: ${floatabi}" | tee -a configure.log + + CFLAGS="${CFLAGS} ${floatabi}" + SFLAGS="${SFLAGS} ${floatabi}" + fi + if test $without_optimizations -eq 0; then CFLAGS="${CFLAGS} -DARM_FEATURES" SFLAGS="${SFLAGS} -DARM_FEATURES" @@ -1637,31 +1659,7 @@ EOF fi fi fi - fi - - cat > $test.c << EOF -int main() { return 0; } -EOF - if try $CC -w -c $SFLAGS $test.c -mfloat-abi=softfp && - try $LDSHARED $LDSHAREDFLAGS $LDFLAGS -o $test$shared_ext $test.o $LDSHAREDLIBC; then - floatabi="-mfloat-abi=softfp" - else - if try $CC -w -c $SFLAGS $test.c -mfloat-abi=hard && - try $LDSHARED $LDSHAREDFLAGS $LDFLAGS -o $test$shared_ext $test.o $LDSHAREDLIBC; then - floatabi="-mfloat-abi=hard" - fi - fi - - if [ -z $floatabi ]; then - echo "ARM floating point arch not auto-detected" | tee -a configure.log - else - echo "ARM floating point arch: ${floatabi}" | tee -a configure.log - CFLAGS="${CFLAGS} ${floatabi}" - SFLAGS="${SFLAGS} ${floatabi}" - fi - - if test $without_optimizations -eq 0; then if test $buildacle -eq 1; then check_acle_compiler_flag From 7ecbaa25fce25e458d6f09d8b3c27b4b1e7c4112 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 29 Aug 2023 01:27:44 -0700 Subject: [PATCH 734/798] Use consistent NEON_AVAILABLE variable across CMake/configure. --- CMakeLists.txt | 2 +- cmake/detect-intrinsics.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc42f1a33a..3679f9d6cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -631,7 +631,7 @@ if(WITH_OPTIM) endif() if(WITH_NEON) check_neon_compiler_flag() - if(MFPU_NEON_AVAILABLE) + if(NEON_AVAILABLE) add_definitions(-DARM_NEON) set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/compare256_neon.c ${ARCHDIR}/slide_hash_neon.c) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index bc938fc234..2358c5788c 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -176,7 +176,7 @@ macro(check_neon_compiler_flag) # include #endif int main() { return 0; }" - MFPU_NEON_AVAILABLE FAIL_REGEX "not supported") + NEON_AVAILABLE FAIL_REGEX "not supported") set(CMAKE_REQUIRED_FLAGS) endmacro() From 4838f0e9677eedfba4e1eafbc63141b001429cfc Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 30 Aug 2023 07:29:46 -0700 Subject: [PATCH 735/798] Merge 32-bit arm hardware flag detection sections in configure and cmake --- CMakeLists.txt | 30 ++++++++++++++---------------- configure | 30 ++++++++++++++---------------- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3679f9d6cd..f74c0e454d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -548,7 +548,20 @@ if(WITH_OPTIM) if(BASEARCH_ARM_FOUND) add_definitions(-DARM_FEATURES) if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - if(NOT "${ARCH}" MATCHES "aarch64") + if("${ARCH}" MATCHES "aarch64") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & HWCAP_CRC32); + }" + ARM_AUXV_HAS_CRC32 + ) + if(ARM_AUXV_HAS_CRC32) + add_definitions(-DARM_AUXV_HAS_CRC32) + else() + message(STATUS "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") + endif() + else() check_c_source_compiles( "#include int main() { @@ -573,21 +586,6 @@ if(WITH_OPTIM) message(STATUS "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") endif() endif() - else() - check_c_source_compiles( - "#include - int main() { - return (getauxval(AT_HWCAP) & HWCAP_CRC32); - }" - ARM_AUXV_HAS_CRC32 - ) - if(ARM_AUXV_HAS_CRC32) - add_definitions(-DARM_AUXV_HAS_CRC32) - else() - message(STATUS "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime.") - endif() - endif() - if(NOT "${ARCH}" MATCHES "aarch64") check_c_source_compiles( "#include int main() { diff --git a/configure b/configure index b6339fbccb..4618054872 100755 --- a/configure +++ b/configure @@ -1593,7 +1593,20 @@ EOF ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} arm_features.lo" if test $LINUX -eq 1; then - if test "$ARCH" != "aarch64"; then + if test "$ARCH" = "aarch64"; then + cat > $test.c < +int main() { + return (getauxval(AT_HWCAP) & HWCAP_CRC32); +} +EOF + if try $CC -c $CFLAGS $test.c; then + CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" + SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" + else + echo "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log + fi + else cat > $test.c < int main() { @@ -1618,22 +1631,7 @@ EOF echo "HWCAP2_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log fi fi - else - cat > $test.c < -int main() { - return (getauxval(AT_HWCAP) & HWCAP_CRC32); -} -EOF - if try $CC -c $CFLAGS $test.c; then - CFLAGS="${CFLAGS} -DARM_AUXV_HAS_CRC32" - SFLAGS="${SFLAGS} -DARM_AUXV_HAS_CRC32" - else - echo "HWCAP_CRC32 not present in sys/auxv.h; cannot detect support at runtime." | tee -a configure.log - fi - fi - if test "$ARCH" != "aarch64"; then cat > $test.c < int main() { From 1c1e728637025cf1d13d99718ccb2d5cb1e9dfaa Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 19 May 2023 15:16:24 +0100 Subject: [PATCH 736/798] Use GCC cpuid intrinsics with MinGW --- arch/x86/x86_features.c | 8 ++++---- cmake/detect-intrinsics.cmake | 2 +- configure | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/x86_features.c b/arch/x86/x86_features.c index 3272e3fdd9..8d11564c24 100644 --- a/arch/x86/x86_features.c +++ b/arch/x86/x86_features.c @@ -10,7 +10,7 @@ #include "../../zbuild.h" #include "x86_features.h" -#ifdef _WIN32 +#ifdef _MSC_VER # include #else // Newer versions of GCC and clang come with cpuid.h @@ -20,7 +20,7 @@ #include static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _WIN32 +#ifdef _MSC_VER unsigned int registers[4]; __cpuid((int *)registers, info); @@ -34,7 +34,7 @@ static inline void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, } static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _WIN32 +#ifdef _MSC_VER unsigned int registers[4]; __cpuidex((int *)registers, info, subinfo); @@ -48,7 +48,7 @@ static inline void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, } static inline uint64_t xgetbv(unsigned int xcr) { -#ifdef _WIN32 +#ifdef _MSC_VER return _xgetbv(xcr); #else uint32_t eax, edx; diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 2358c5788c..a4a28b445a 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -502,7 +502,7 @@ macro(check_xsave_intrinsics) endif() set(CMAKE_REQUIRED_FLAGS "${XSAVEFLAG} ${NATIVEFLAG}") check_c_source_compiles( - "#ifdef _WIN32 + "#ifdef _MSC_VER # include #else # include diff --git a/configure b/configure index 4618054872..d96455e6c1 100755 --- a/configure +++ b/configure @@ -1217,7 +1217,7 @@ EOF check_xsave_intrinsics() { # Check whether compiler supports XSAVE intrinsics cat > $test.c << EOF -#ifdef _WIN32 +#ifdef _MSC_VER # include #else # include From 6edb09aeae97663f43870c7aca5906302b7f6ae0 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Fri, 19 May 2023 15:17:41 +0100 Subject: [PATCH 737/798] Always include strings.h when strcasecmp is used --- test/minideflate.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index 87513df380..61fbe43cb6 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -13,16 +13,18 @@ #if defined(_WIN32) || defined(__CYGWIN__) # include # include -# include # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) -# ifdef _MSC_VER -# define strcasecmp _stricmp -# endif #else -# include # define SET_BINARY_MODE(file) #endif +#ifdef _MSC_VER +# include +# define strcasecmp _stricmp +#else +# include +#endif + #define CHECK_ERR(err, msg) { \ if (err != Z_OK) { \ fprintf(stderr, "%s error: %d\n", msg, err); \ From 16fe1f885ef33553ce3bd92762eef58ab526a1ab Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Wed, 12 Jul 2023 18:48:48 +0100 Subject: [PATCH 738/798] Add ARMv6 version of slide_hash --- CMakeLists.txt | 24 ++++++++ README.md | 3 +- arch/arm/Makefile.in | 8 +++ arch/arm/acle_intrins.h | 27 +++++++++ arch/arm/arm_features.c | 18 ++++++ arch/arm/arm_features.h | 1 + arch/arm/slide_hash_armv6.c | 47 +++++++++++++++ cmake/detect-intrinsics.cmake | 40 +++++++++++++ configure | 82 ++++++++++++++++++++++++++ cpu_features.h | 6 +- functable.c | 9 +++ test/benchmarks/benchmark_slidehash.cc | 3 + win32/Makefile.arm | 8 +++ 13 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 arch/arm/acle_intrins.h create mode 100644 arch/arm/slide_hash_armv6.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f74c0e454d..6cccb4659a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,6 +101,7 @@ set_property(CACHE WITH_SANITIZER PROPERTY STRINGS "Memory" "Address" "Undefined if(BASEARCH_ARM_FOUND) option(WITH_ACLE "Build with ACLE" ON) option(WITH_NEON "Build with NEON intrinsics" ON) + option(WITH_ARMV6 "Build with ARMv6 SIMD" ON) elseif(BASEARCH_PPC_FOUND) option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON) option(WITH_POWER8 "Build with optimisations for POWER8" ON) @@ -128,6 +129,7 @@ mark_as_advanced(FORCE ZLIB_SYMBOL_PREFIX WITH_REDUCED_MEM WITH_ACLE WITH_NEON + WITH_ARMV6 WITH_DFLTCC_DEFLATE WITH_DFLTCC_INFLATE WITH_CRC32_VX @@ -292,6 +294,10 @@ endif() # # Check for standard/system includes # +check_include_file(arm_acle.h HAVE_ARM_ACLE_H) +if(HAVE_ARM_ACLE_H) + add_definitions(-DHAVE_ARM_ACLE_H) +endif() check_include_file(sys/auxv.h HAVE_SYS_AUXV_H) if(HAVE_SYS_AUXV_H) add_definitions(-DHAVE_SYS_AUXV_H) @@ -648,6 +654,23 @@ if(WITH_OPTIM) set(WITH_NEON OFF) endif() endif() + if(WITH_ARMV6) + check_armv6_compiler_flag() + if(HAVE_ARMV6_INLINE_ASM OR HAVE_ARMV6_INTRIN) + add_definitions(-DARM_SIMD) + set(ARMV6_SRCS ${ARCHDIR}/slide_hash_armv6.c) + set_property(SOURCE ${ARMV6_SRCS} PROPERTY COMPILE_FLAGS "${ARMV6FLAG} ${NOLTOFLAG}") + list(APPEND ZLIB_ARCH_SRCS ${ARMV6_SRCS}) + add_feature_info(ARMV6 1 "Support ARMv6 SIMD instructions in slide_hash, using \"${ARMV6FLAG}\"") + if(HAVE_ARMV6_INTRIN) + add_definitions(-DARM_SIMD_INTRIN) + endif() + else() + set(WITH_ARMV6 OFF) + endif() + else() + set(WITH_ARMV6 OFF) + endif() elseif(BASEARCH_PPC_FOUND) # Common arch detection code if(WITH_ALTIVEC) @@ -1215,6 +1238,7 @@ add_feature_info(WITH_INFLATE_ALLOW_INVALID_DIST WITH_INFLATE_ALLOW_INVALID_DIST if(BASEARCH_ARM_FOUND) add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE") add_feature_info(WITH_NEON WITH_NEON "Build with NEON intrinsics") + add_feature_info(WITH_ARMV6 WITH_ARMV6 "Build with ARMv6 SIMD") elseif(BASEARCH_PPC_FOUND) add_feature_info(WITH_ALTIVEC WITH_ALTIVEC "Build with AltiVec optimisations") add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8") diff --git a/README.md b/README.md index c83b8487f1..dfd461a014 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Features * Adler32 implementation using SSSE3, AVX2, AVX512, AVX512-VNNI, Neon, VMX & VSX * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, ACLE, & IBM Z * Hash table implementation using CRC32-C intrinsics on x86 and ARM - * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX + * Slide hash implementations using SSE2, AVX2, ARMv6, Neon, VMX & VSX * Compare256 implementations using SSE2, AVX2, Neon, POWER9 & RVV * Inflate chunk copying using SSE2, SSSE3, AVX, Neon & VSX * Support for hardware-accelerated deflate using IBM Z DFLTCC @@ -194,6 +194,7 @@ Advanced Build Options | WITH_VPCLMULQDQ | --without-vpclmulqdq | Build with VPCLMULQDQ intrinsics | ON | | WITH_ACLE | --without-acle | Build with ACLE intrinsics | ON | | WITH_NEON | --without-neon | Build with NEON intrinsics | ON | +| WITH_ARMV6 | --without-armv6 | Build with ARMv6 intrinsics | ON | | WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | ON | | WITH_POWER8 | --without-power8 | Build with POWER8 optimisations | ON | | WITH_RVV | | Build with RVV intrinsics | ON | diff --git a/arch/arm/Makefile.in b/arch/arm/Makefile.in index 717754760f..9d05b00b54 100644 --- a/arch/arm/Makefile.in +++ b/arch/arm/Makefile.in @@ -10,6 +10,7 @@ SUFFIX= ACLEFLAG= NEONFLAG= +ARMV6FLAG= NOLTOFLAG= SRCDIR=. @@ -23,6 +24,7 @@ all: \ compare256_neon.o compare256_neon.lo \ crc32_acle.o crc32_acle.lo \ slide_hash_neon.o slide_hash_neon.lo \ + slide_hash_armv6.o slide_hash_armv6.lo \ insert_string_acle.o insert_string_acle.lo adler32_neon.o: @@ -61,6 +63,12 @@ slide_hash_neon.o: slide_hash_neon.lo: $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_neon.c +slide_hash_armv6.o: + $(CC) $(CFLAGS) $(ARMV6FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_armv6.c + +slide_hash_armv6.lo: + $(CC) $(SFLAGS) $(ARMV6FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_armv6.c + insert_string_acle.o: $(CC) $(CFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c diff --git a/arch/arm/acle_intrins.h b/arch/arm/acle_intrins.h new file mode 100644 index 0000000000..e9eef12dfb --- /dev/null +++ b/arch/arm/acle_intrins.h @@ -0,0 +1,27 @@ +#ifndef ARM_ACLE_INTRINS_H +#define ARM_ACLE_INTRINS_H + +#include +#ifdef _MSC_VER +# include +#elif defined(HAVE_ARM_ACLE_H) +# include +#endif + +#ifdef ARM_SIMD +#ifdef _MSC_VER +typedef uint32_t uint16x2_t; + +#define __uqsub16 _arm_uqsub16 +#elif !defined(ARM_SIMD_INTRIN) +typedef uint32_t uint16x2_t; + +static inline uint16x2_t __uqsub16(uint16x2_t __a, uint16x2_t __b) { + uint16x2_t __c; + __asm__ __volatile__("uqsub16\t%0, %1, %2" : "=r" (__c) : "r"(__a), "r"(__b)); + return __c; +} +#endif +#endif + +#endif // include guard ARM_ACLE_INTRINS_H diff --git a/arch/arm/arm_features.c b/arch/arm/arm_features.c index 8ef8200099..a0e070ba95 100644 --- a/arch/arm/arm_features.c +++ b/arch/arm/arm_features.c @@ -72,10 +72,28 @@ static inline int arm_has_neon() { } #endif +/* AArch64 does not have ARMv6 SIMD. */ +#if !defined(__aarch64__) && !defined(_M_ARM64) && !defined(_M_ARM64EC) +static inline int arm_has_simd() { +#if defined(__linux__) && defined(HAVE_SYS_AUXV_H) + const char *platform = (const char *)getauxval(AT_PLATFORM); + return strncmp(platform, "v6l", 3) == 0 + || strncmp(platform, "v7l", 3) == 0 + || strncmp(platform, "v8l", 3) == 0; +#elif defined(ARM_NOCHECK_SIMD) + return 1; +#else + return 0; +#endif +} +#endif + void Z_INTERNAL arm_check_features(struct arm_cpu_features *features) { #if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) + features->has_simd = 0; /* never available */ features->has_neon = 1; /* always available */ #else + features->has_simd = arm_has_simd(); features->has_neon = arm_has_neon(); #endif features->has_crc32 = arm_has_crc32(); diff --git a/arch/arm/arm_features.h b/arch/arm/arm_features.h index 6fcd8d3eb5..eca078e310 100644 --- a/arch/arm/arm_features.h +++ b/arch/arm/arm_features.h @@ -6,6 +6,7 @@ #define ARM_H_ struct arm_cpu_features { + int has_simd; int has_neon; int has_crc32; }; diff --git a/arch/arm/slide_hash_armv6.c b/arch/arm/slide_hash_armv6.c new file mode 100644 index 0000000000..0a2eeccf92 --- /dev/null +++ b/arch/arm/slide_hash_armv6.c @@ -0,0 +1,47 @@ +/* slide_hash_armv6.c -- Optimized hash table shifting for ARMv6 with support for SIMD instructions + * Copyright (C) 2023 Cameron Cawley + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#if defined(ARM_SIMD) +#include "acle_intrins.h" +#include "../../zbuild.h" +#include "../../deflate.h" + +/* SIMD version of hash_chain rebase */ +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { + Z_REGISTER uint16x2_t v; + uint16x2_t p0, p1, p2, p3; + Z_REGISTER size_t n; + + size_t size = entries*sizeof(table[0]); + Assert((size % (sizeof(uint16x2_t) * 4) == 0), "hash table size err"); + + Assert(sizeof(Pos) == 2, "Wrong Pos size"); + v = wsize | (wsize << 16); + + n = size / (sizeof(uint16x2_t) * 4); + do { + p0 = *((const uint16x2_t *)(table)); + p1 = *((const uint16x2_t *)(table+2)); + p2 = *((const uint16x2_t *)(table+4)); + p3 = *((const uint16x2_t *)(table+6)); + p0 = __uqsub16(p0, v); + p1 = __uqsub16(p1, v); + p2 = __uqsub16(p2, v); + p3 = __uqsub16(p3, v); + *((uint16x2_t *)(table)) = p0; + *((uint16x2_t *)(table+2)) = p1; + *((uint16x2_t *)(table+4)) = p2; + *((uint16x2_t *)(table+6)) = p3; + table += 8; + } while (--n); +} + +Z_INTERNAL void slide_hash_armv6(deflate_state *s) { + unsigned int wsize = s->w_size; + + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); +} +#endif diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index a4a28b445a..04830fe613 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -44,6 +44,46 @@ macro(check_acle_compiler_flag) endif() endmacro() +macro(check_armv6_compiler_flag) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + check_c_compiler_flag("-march=armv6" HAVE_MARCH_ARMV6) + if(HAVE_MARCH_ARMV6) + set(ARMV6FLAG "-march=armv6" CACHE INTERNAL "Compiler option to enable ARMv6 support") + endif() + endif() + endif() + # Check whether compiler supports ARMv6 inline asm + set(CMAKE_REQUIRED_FLAGS "${ARMV6FLAG} ${NATIVEFLAG}") + check_c_source_compile_or_run( + "unsigned int f(unsigned int a, unsigned int b) { + unsigned int c; + __asm__ __volatile__ ( \"uqsub16 %0, %1, %2\" : \"=r\" (c) : \"r\" (a), \"r\" (b) ); + return (int)c; + } + int main(void) { return 0; }" + HAVE_ARMV6_INLINE_ASM + ) + # Check whether compiler supports ARMv6 intrinsics + check_c_source_compile_or_run( + "#if defined(_MSC_VER) + #include + #else + #include + #endif + unsigned int f(unsigned int a, unsigned int b) { + #if defined(_MSC_VER) + return _arm_uqsub16(a, b); + #else + return __uqsub16(a, b); + #endif + } + int main(void) { return 0; }" + HAVE_ARMV6_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + macro(check_avx512_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "Intel") if(CMAKE_HOST_UNIX OR APPLE) diff --git a/configure b/configure index d96455e6c1..29de72cecf 100755 --- a/configure +++ b/configure @@ -93,6 +93,7 @@ build32=0 build64=0 buildvpclmulqdq=1 buildacle=1 +buildarmv6=1 buildaltivec=1 buildpower8=1 buildpower9=1 @@ -115,6 +116,7 @@ vpclmulflag="-mvpclmulqdq -mavx512f" xsaveflag="-mxsave" acleflag= neonflag= +armv6flag= noltoflag="-fno-lto" vgfmaflag="-march=z13" vmxflag="-maltivec" @@ -167,6 +169,7 @@ case "$1" in echo ' [--without-new-strategies] Compiles without using new additional deflate strategies' | tee -a configure.log echo ' [--without-acle] Compiles without ARM C Language Extensions' | tee -a configure.log echo ' [--without-neon] Compiles without ARM Neon SIMD instruction set' | tee -a configure.log + echo ' [--without-armv6] Compiles without ARMv6 SIMD instruction set' | tee -a configure.log echo ' [--without-altivec] Compiles without PPC AltiVec support' | tee -a configure.log echo ' [--without-power8] Compiles without Power8 instruction set' | tee -a configure.log echo ' [--with-dfltcc-deflate] Use DEFLATE CONVERSION CALL instruction for compression on IBM Z' | tee -a configure.log @@ -198,6 +201,7 @@ case "$1" in --without-vpclmulqdq) buildvpclmulqdq=0; shift ;; --without-acle) buildacle=0; shift ;; --without-neon) buildneon=0; shift ;; + --without-armv6) buildarmv6=0; shift ;; --without-altivec) buildaltivec=0 ; shift ;; --without-power8) buildpower8=0 ; shift ;; --without-power9) buildpower9=0 ; shift ;; @@ -1177,6 +1181,52 @@ EOF fi } +check_armv6_intrinsics() { + # Check whether -march=armv6 works correctly + cat > $test.c << EOF +int main() { return 0; } +EOF + if try $CC -c $CFLAGS -march=armv6 $test.c; then + armv6flag=-march=armv6 + echo "Check whether -march=armv6 works ... Yes." | tee -a configure.log + else + echo "Check whether -march=armv6 works ... No." | tee -a configure.log + fi + + # Check whether compiler supports ARMv6 inline asm + cat > $test.c << EOF +unsigned int f(unsigned int a, unsigned int b) { + unsigned int c; + __asm__ __volatile__ ( "uqsub16 %0, %1, %2" : "=r" (c) : "r" (a), "r" (b) ); + return c; +} +int main(void) { return 0; } +EOF + if try ${CC} ${CFLAGS} ${armv6flag} $test.c; then + echo "Checking for ARMv6 inline assembly ... Yes." | tee -a configure.log + HAVE_ARMV6_INLINE_ASM=1 + else + echo "Checking for ARMv6 inline assembly ... No." | tee -a configure.log + HAVE_ARMV6_INLINE_ASM=0 + fi + + # Check whether compiler supports ARMv6 intrinsics + cat > $test.c << EOF +#include +unsigned int f(unsigned int a, unsigned int b) { + return __uqsub16(a, b); +} +int main(void) { return 0; } +EOF + if try ${CC} ${CFLAGS} ${armv6flag} $test.c; then + echo "Checking for ARMv6 intrinsics ... Yes." | tee -a configure.log + HAVE_ARMV6_INTRIN=1 + else + echo "Checking for ARMv6 intrinsics ... No." | tee -a configure.log + HAVE_ARMV6_INTRIN=0 + fi +} + check_pclmulqdq_intrinsics() { # Check whether compiler supports PCLMULQDQ intrinsics cat > $test.c << EOF @@ -1592,6 +1642,18 @@ EOF ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} arm_features.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} arm_features.lo" + cat > $test.c < +EOF + if try $CC -c $CFLAGS $test.c; then + echo "Checking for arm_acle.h... Yes." | tee -a configure.log + CFLAGS="${CFLAGS} -DHAVE_ARM_ACLE_H" + SFLAGS="${SFLAGS} -DHAVE_ARM_ACLE_H" + else + echo "Checking for arm_acle.h... No." | tee -a configure.log + fi + + if test $LINUX -eq 1; then if test "$ARCH" = "aarch64"; then cat > $test.c <> configure.log echo xsaveflag = $xsaveflag >> configure.log echo acleflag = $acleflag >> configure.log echo neonflag = $neonflag >> configure.log +echo armv6flag = $armv6flag >> configure.log echo ARCHDIR = ${ARCHDIR} >> configure.log echo ARCH_STATIC_OBJS = ${ARCH_STATIC_OBJS} >> configure.log echo ARCH_SHARED_OBJS = ${ARCH_SHARED_OBJS} >> configure.log @@ -2001,6 +2082,7 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^XSAVEFLAG *=/s#=.*#=$xsaveflag# /^ACLEFLAG *=/s#=.*#=$acleflag# /^NEONFLAG *=/s#=.*#=$neonflag# +/^ARMV6FLAG *=/s#=.*#=$armv6flag# /^NOLTOFLAG *=/s#=.*#=$noltoflag# /^VGFMAFLAG *=/s#=.*#=$vgfmaflag# /^PPCFLAGS *=/s#=.*#=$vmxflag# diff --git a/cpu_features.h b/cpu_features.h index 870f6e656c..faca52ad4f 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -261,7 +261,11 @@ typedef void (*slide_hash_func)(deflate_state *s); #ifdef X86_SSE2 extern void slide_hash_sse2(deflate_state *s); -#elif defined(ARM_NEON) +#endif +#if defined(ARM_SIMD) +extern void slide_hash_armv6(deflate_state *s); +#endif +#if defined(ARM_NEON) extern void slide_hash_neon(deflate_state *s); #endif #if defined(PPC_VMX) diff --git a/functable.c b/functable.c index 6e195aceaf..3ef840cffc 100644 --- a/functable.c +++ b/functable.c @@ -142,6 +142,15 @@ static void init_functable(void) { #endif + // ARM - SIMD +#ifdef ARM_SIMD +# ifndef ARM_NOCHECK_SIMD + if (cf.arm.has_simd) +# endif + { + ft.slide_hash = &slide_hash_armv6; + } +#endif // ARM - NEON #ifdef ARM_NEON # ifndef ARM_NOCHECK_NEON diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index b5ab456161..e098c815e8 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -68,6 +68,9 @@ class slide_hash: public benchmark::Fixture { BENCHMARK_SLIDEHASH(c, slide_hash_c, 1); +#ifdef ARM_SIMD +BENCHMARK_SLIDEHASH(armv6, slide_hash_armv6, test_cpu_features.arm.has_simd); +#endif #ifdef ARM_NEON BENCHMARK_SLIDEHASH(neon, slide_hash_neon, test_cpu_features.arm.has_neon); #endif diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 7d3f1b58a9..34dfe6bba6 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -41,6 +41,7 @@ WITH_GZFILEOP = yes ZLIB_COMPAT = WITH_ACLE = WITH_NEON = +WITH_ARMV6 = WITH_VFPV3 = NEON_ARCH = /arch:VFPv4 SUFFIX = @@ -110,6 +111,13 @@ WFLAGS = $(WFLAGS) \ # OBJS = $(OBJS) adler32_neon.obj chunkset_neon.obj compare256_neon.obj slide_hash_neon.obj !endif +!if "$(WITH_ARMV6)" != "" +WFLAGS = $(WFLAGS) \ + -DARM_SIMD \ + -DARM_NOCHECK_SIMD \ + # +OBJS = $(OBJS) slide_hash_armv6.obj +!endif # targets all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ From 401aeb8b867d27ebbcdb44c49a727935ab707103 Mon Sep 17 00:00:00 2001 From: Deniz Bahadir Date: Fri, 15 Sep 2023 15:46:56 +0200 Subject: [PATCH 739/798] Fix examining value of GENERATOR_IS_MULTI_CONFIG CMake does not define a variable GENERATOR_IS_MULTI_CONFIG by default. Instead it sets a global property of that name. In order to examine its value it first has to be retrieved and stored into a (local) variable, which is what this commit does. fixes: #1574 Signed-off-by: Deniz Bahadir --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cccb4659a..bf0423b956 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ endif() # Make sure we use an appropriate BUILD_TYPE by default, "Release" to be exact # this should select the maximum generic optimisation on the current platform (i.e. -O3 for gcc/clang) +get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(NOT GENERATOR_IS_MULTI_CONFIG) if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING From 3eb7cd2d8a5bc63f9fb65ad6f87912a562b523ec Mon Sep 17 00:00:00 2001 From: Deniz Bahadir Date: Fri, 15 Sep 2023 18:23:27 +0200 Subject: [PATCH 740/798] Match CMAKE_GENERATOR_TOOLSET variable case-insensitive The Visual Studio CMake generator allows to select different toolsets. One of these toolsets is Clang-Cl. However, the generator does accept the toolset name case-agnostic, so it could be "ClangCl", but also "Clangcl" or "clangcl" or ... This value will be stored verbatim in variable CMAKE_GENERATOR_TOOLSET by CMake. Therefore, this variable must be matched case-insensitive, which is what this commit does. fixes: #1576 Signed-off-by: Deniz Bahadir --- cmake/detect-intrinsics.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 04830fe613..1076bae112 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -96,7 +96,7 @@ macro(check_avx512_intrinsics) # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal # instruction scheduling unless you specify a reasonable -mtune= target set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl") - if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "ClangCl") + if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "[Cc][Ll][Aa][Nn][Gg][Cc][Ll]") check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) if(HAVE_CASCADE_LAKE) set(AVX512FLAG "${AVX512FLAG} -mtune=cascadelake") @@ -141,7 +141,7 @@ macro(check_avx512vnni_intrinsics) elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) set(AVX512VNNIFLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx512vnni") - if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "ClangCl") + if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "[Cc][Ll][Aa][Nn][Gg][Cc][Ll]") check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) if(HAVE_CASCADE_LAKE) set(AVX512VNNIFLAG "${AVX512VNNIFLAG} -mtune=cascadelake") From 31497b545c4780aaa333ef1968737bd378e6e29c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 17 Sep 2023 15:25:41 -0700 Subject: [PATCH 741/798] Don't run test intrinsic code with native flag in CMake. Native flag should already determine what code will run on the architecture. This appears to have just been an extra run check with limited benefits. Any compiler that compiles code not available on the native platform is buggy and not our problem. --- cmake/detect-intrinsics.cmake | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 1076bae112..fe1848e62c 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -1,17 +1,6 @@ # detect-intrinsics.cmake -- Detect compiler intrinsics support # Licensed under the Zlib license, see LICENSE.md for details -# Macro to check if source compiles -# (and, when compiling very natively, also runs). -macro(check_c_source_compile_or_run source flag) - if(CMAKE_CROSSCOMPILING OR NOT WITH_NATIVE_INSTRUCTIONS) - check_c_source_compiles("${source}" ${flag}) - else() - check_c_source_runs("${source}" ${flag}) - endif() -endmacro() - - macro(check_acle_compiler_flag) if(MSVC) # Both ARM and ARM64-targeting msvc support intrinsics, but @@ -55,7 +44,7 @@ macro(check_armv6_compiler_flag) endif() # Check whether compiler supports ARMv6 inline asm set(CMAKE_REQUIRED_FLAGS "${ARMV6FLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "unsigned int f(unsigned int a, unsigned int b) { unsigned int c; __asm__ __volatile__ ( \"uqsub16 %0, %1, %2\" : \"=r\" (c) : \"r\" (a), \"r\" (b) ); @@ -65,7 +54,7 @@ macro(check_armv6_compiler_flag) HAVE_ARMV6_INLINE_ASM ) # Check whether compiler supports ARMv6 intrinsics - check_c_source_compile_or_run( + check_c_source_compiles( "#if defined(_MSC_VER) #include #else @@ -111,7 +100,7 @@ macro(check_avx512_intrinsics) endif() # Check whether compiler supports AVX512 intrinsics set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "#include __m512i f(__m512i y) { __m512i x = _mm512_set1_epi8(2); @@ -122,7 +111,7 @@ macro(check_avx512_intrinsics) ) # Evidently both GCC and clang were late to implementing these - check_c_source_compile_or_run( + check_c_source_compiles( "#include __mmask16 f(__mmask16 x) { return _knot_mask16(x); } int main(void) { return 0; }" @@ -157,7 +146,7 @@ macro(check_avx512vnni_intrinsics) # Check whether compiler supports AVX512vnni intrinsics set(CMAKE_REQUIRED_FLAGS "${AVX512VNNIFLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "#include __m512i f(__m512i x, __m512i y) { __m512i z = _mm512_setzero_epi32(); @@ -185,7 +174,7 @@ macro(check_avx2_intrinsics) endif() # Check whether compiler supports AVX2 intrinics set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "#include __m256i f(__m256i x) { const __m256i y = _mm256_set1_epi16(1); @@ -254,7 +243,7 @@ macro(check_pclmulqdq_intrinsics) if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) # The pclmul code currently crashes on Mac in 32bit mode. Avoid for now. set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "#include #include __m128i f(__m128i a, __m128i b) { return _mm_clmulepi64_si128(a, b, 0x10); } @@ -276,7 +265,7 @@ macro(check_vpclmulqdq_intrinsics) # Check whether compiler supports VPCLMULQDQ intrinsics if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) set(CMAKE_REQUIRED_FLAGS "${VPCLMULFLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "#include #include __m512i f(__m512i a) { @@ -454,7 +443,7 @@ macro(check_sse2_intrinsics) endif() # Check whether compiler supports SSE2 intrinsics set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "#include __m128i f(__m128i x, __m128i y) { return _mm_sad_epu8(x, y); } int main(void) { return 0; }" @@ -477,7 +466,7 @@ macro(check_ssse3_intrinsics) endif() # Check whether compiler supports SSSE3 intrinsics set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "#include __m128i f(__m128i u) { __m128i v = _mm_set1_epi32(1); @@ -502,7 +491,7 @@ macro(check_sse42_intrinsics) endif() # Check whether compiler supports SSE4.2 intrinsics set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG} ${NATIVEFLAG}") - check_c_source_compile_or_run( + check_c_source_compiles( "#include unsigned int f(unsigned int a, unsigned int b) { return _mm_crc32_u32(a, b); } int main(void) { return 0; }" From 57a2ed9e503bfeb92577c87aa49b9b0727d97120 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 17 Sep 2023 17:11:48 -0700 Subject: [PATCH 742/798] Added instructions for cpack to readme. --- README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dfd461a014..d848d7987d 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ LD_PRELOAD=/opt/zlib-ng/libz.so.1.2.13.zlib-ng /usr/bin/program To install zlib-ng system-wide using cmake: -``` +```sh or powershell cmake --build . --target install ``` @@ -139,10 +139,22 @@ cmake --build . --target install To install zlib-ng system-wide using the configure script: -``` +```sh make install ``` +### CPack + +After building with cmake, an installation package can be created using cpack. By default a tgz package is created, +but you can append `-G ` to each command to generate alternative packages types (TGZ, ZIP, RPM, DEB). To easily +create a rpm or deb package, you would use `-G RPM` or `-G DEB` respectively. + +```sh or powershell +cd build +cpack --config CPackConfig.cmake +cpack --config CPackSourceConfig.cmake +``` + ### Vcpkg Alternatively, you can build and install zlib-ng using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: From fe6aaedaf8be680d43d5726a2e2b3ed948406800 Mon Sep 17 00:00:00 2001 From: alexsifivetw Date: Thu, 31 Aug 2023 01:22:20 -0700 Subject: [PATCH 743/798] General optimized chunkset --- CMakeLists.txt | 2 +- arch/riscv/chunkset_rvv.c | 95 +++++++++++++++++++++++++++++++++++++++ cpu_features.h | 7 +++ functable.c | 3 ++ 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 arch/riscv/chunkset_rvv.c diff --git a/CMakeLists.txt b/CMakeLists.txt index bf0423b956..b7dc46be06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -739,7 +739,7 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c) # FIXME: we will not set compile flags for riscv_features.c when # the kernels update hwcap or hwprobe for riscv - set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/adler32_rvv.c ${ARCHDIR}/compare256_rvv.c ${ARCHDIR}/slide_hash_rvv.c) + set(RVV_SRCS ${ARCHDIR}/riscv_features.c ${ARCHDIR}/adler32_rvv.c ${ARCHDIR}/chunkset_rvv.c ${ARCHDIR}/compare256_rvv.c ${ARCHDIR}/slide_hash_rvv.c) list(APPEND ZLIB_ARCH_SRCS ${RVV_SRCS}) set_property(SOURCE ${RVV_SRCS} PROPERTY COMPILE_FLAGS "${RISCVFLAG} ${NOLTOFLAG}") else() diff --git a/arch/riscv/chunkset_rvv.c b/arch/riscv/chunkset_rvv.c new file mode 100644 index 0000000000..034063ba2a --- /dev/null +++ b/arch/riscv/chunkset_rvv.c @@ -0,0 +1,95 @@ +/* chunkset_rvv.c - General version of chunkset + * Copyright (C) 2023 SiFive, Inc. All rights reserved. + * Contributed by Alex Chiang + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" + +/* + * It's not a optimized implemantation using RISC-V RVV, but a general optimized one. + * + * RISC-V glibc would enable RVV optimized memcpy at runtime by IFUNC, + * so we prefer using large size chunk and copy memory as much as possible. + */ +#define CHUNK_SIZE 32 + +/* We don't have a 32-byte datatype for RISC-V arch. */ +typedef struct chunk_s { + uint8_t data[CHUNK_SIZE]; +} chunk_t; + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + memcpy(chunk->data, s, CHUNK_SIZE); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + memcpy(out, chunk->data, CHUNK_SIZE); +} + +#define CHUNKSIZE chunksize_rvv +#define CHUNKCOPY chunkcopy_rvv +#define CHUNKUNROLL chunkunroll_rvv +#define CHUNKMEMSET chunkmemset_rvv +#define CHUNKMEMSET_SAFE chunkmemset_safe_rvv + +#define HAVE_CHUNKCOPY + +/* + * Assuming that the length is non-zero, and that `from` lags `out` by at least + * sizeof chunk_t bytes, please see the comments in chunkset_tpl.h. + * + * We load/store a single chunk once in the `CHUNKCOPY`. + * However, RISC-V glibc would enable RVV optimized memcpy at runtime by IFUNC, + * such that, we prefer copy large memory size once to make good use of the the RVV advance. + * + * To be aligned to the other platforms, we did't modify `CHUNKCOPY` method a lot, + * but we still copy as much memory as possible for some conditions. + * + * case 1: out - from >= len (no overlap) + * We can use memcpy to copy `len` size once + * because the memory layout would be the same. + * + * case 2: overlap + * We copy N chunks using memcpy at once, aiming to achieve our goal: + * to copy as much memory as possible. + * + * After using a single memcpy to copy N chunks, we have to use series of + * loadchunk and storechunk to ensure the result is correct. + */ +static inline uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { + Assert(len > 0, "chunkcopy should never have a length 0"); + int32_t align = ((len - 1) % sizeof(chunk_t)) + 1; + chunk_t chunk; + memcpy(out, from, sizeof(chunk)); + out += align; + from += align; + len -= align; + ptrdiff_t dist = out - from; + if (dist >= len) { + memcpy(out, from, len); + out += len; + from += len; + return out; + } + if (dist >= sizeof(chunk_t)) { + dist = (dist / sizeof(chunk_t)) * sizeof(chunk_t); + memcpy(out, from, dist); + out += dist; + from += dist; + len -= dist; + } + while (len > 0) { + memcpy(out, from, sizeof(chunk)); + out += sizeof(chunk_t); + from += sizeof(chunk_t); + len -= sizeof(chunk_t); + } + return out; +} + +#include "chunkset_tpl.h" + +#define INFLATE_FAST inflate_fast_rvv + +#include "inffast_tpl.h" diff --git a/cpu_features.h b/cpu_features.h index faca52ad4f..aed1eaf90f 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -121,6 +121,10 @@ extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, extern uint32_t chunksize_power8(void); extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif +#ifdef RISCV_RVV +extern uint32_t chunksize_rvv(void); +extern uint8_t* chunkmemset_safe_rvv(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif #ifdef ZLIB_COMPAT typedef struct z_stream_s z_stream; @@ -145,6 +149,9 @@ extern void inflate_fast_neon(PREFIX3(stream) *strm, uint32_t start); #ifdef POWER8_VSX extern void inflate_fast_power8(PREFIX3(stream) *strm, uint32_t start); #endif +#ifdef RISCV_RVV +extern void inflate_fast_rvv(PREFIX3(stream) *strm, uint32_t start); +#endif /* CRC32 */ typedef uint32_t (*crc32_func)(uint32_t crc32, const uint8_t *buf, size_t len); diff --git a/functable.c b/functable.c index 3ef840cffc..df35bae7c0 100644 --- a/functable.c +++ b/functable.c @@ -215,7 +215,10 @@ static void init_functable(void) { #ifdef RISCV_RVV if (cf.riscv.has_rvv) { ft.adler32 = &adler32_rvv; + ft.chunkmemset_safe = &chunkmemset_safe_rvv; + ft.chunksize = &chunksize_rvv; ft.compare256 = &compare256_rvv; + ft.inflate_fast = &inflate_fast_rvv; ft.longest_match = &longest_match_rvv; ft.longest_match_slow = &longest_match_slow_rvv; ft.slide_hash = &slide_hash_rvv; From d30c7bf8fc4d7ad6c48b9f5eaccb8421a270d716 Mon Sep 17 00:00:00 2001 From: alexsifivetw Date: Sun, 24 Sep 2023 02:53:55 -0700 Subject: [PATCH 744/798] Use large data type for chunk Implement chunk memset for specific length --- arch/riscv/chunkset_rvv.c | 46 ++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/arch/riscv/chunkset_rvv.c b/arch/riscv/chunkset_rvv.c index 034063ba2a..ee43bde2f7 100644 --- a/arch/riscv/chunkset_rvv.c +++ b/arch/riscv/chunkset_rvv.c @@ -1,26 +1,53 @@ -/* chunkset_rvv.c - General version of chunkset +/* chunkset_rvv.c - RVV version of chunkset * Copyright (C) 2023 SiFive, Inc. All rights reserved. * Contributed by Alex Chiang * For conditions of distribution and use, see copyright notice in zlib.h */ - +#include #include "zbuild.h" /* - * It's not a optimized implemantation using RISC-V RVV, but a general optimized one. - * * RISC-V glibc would enable RVV optimized memcpy at runtime by IFUNC, * so we prefer using large size chunk and copy memory as much as possible. */ #define CHUNK_SIZE 32 +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 + +#define CHUNK_MEMSET_RVV_IMPL(elen) \ +do { \ + size_t vl, len = CHUNK_SIZE / sizeof(uint##elen##_t); \ + uint##elen##_t val = *(uint##elen##_t*)from; \ + uint##elen##_t* chunk_p = (uint##elen##_t*)chunk; \ + do { \ + vl = __riscv_vsetvl_e##elen##m4(len); \ + vuint##elen##m4_t v_val = __riscv_vmv_v_x_u##elen##m4(val, vl); \ + __riscv_vse##elen##_v_u##elen##m4(chunk_p, v_val, vl); \ + len -= vl; chunk_p += vl; \ + } while (len > 0); \ +} while (0) + /* We don't have a 32-byte datatype for RISC-V arch. */ typedef struct chunk_s { - uint8_t data[CHUNK_SIZE]; + uint64_t data[4]; } chunk_t; +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + CHUNK_MEMSET_RVV_IMPL(16); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + CHUNK_MEMSET_RVV_IMPL(32); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + CHUNK_MEMSET_RVV_IMPL(64); +} + static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { - memcpy(chunk->data, s, CHUNK_SIZE); + memcpy(chunk->data, (uint8_t *)s, CHUNK_SIZE); } static inline void storechunk(uint8_t *out, chunk_t *chunk) { @@ -43,7 +70,7 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { * However, RISC-V glibc would enable RVV optimized memcpy at runtime by IFUNC, * such that, we prefer copy large memory size once to make good use of the the RVV advance. * - * To be aligned to the other platforms, we did't modify `CHUNKCOPY` method a lot, + * To be aligned to the other platforms, we didn't modify `CHUNKCOPY` method a lot, * but we still copy as much memory as possible for some conditions. * * case 1: out - from >= len (no overlap) @@ -60,8 +87,7 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { static inline uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { Assert(len > 0, "chunkcopy should never have a length 0"); int32_t align = ((len - 1) % sizeof(chunk_t)) + 1; - chunk_t chunk; - memcpy(out, from, sizeof(chunk)); + memcpy(out, from, sizeof(chunk_t)); out += align; from += align; len -= align; @@ -80,7 +106,7 @@ static inline uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len len -= dist; } while (len > 0) { - memcpy(out, from, sizeof(chunk)); + memcpy(out, from, sizeof(chunk_t)); out += sizeof(chunk_t); from += sizeof(chunk_t); len -= sizeof(chunk_t); From f9228d8475100d280f416d4ce606d3d56d2a8708 Mon Sep 17 00:00:00 2001 From: Hajin Jang Date: Sun, 10 Sep 2023 18:28:28 +0900 Subject: [PATCH 745/798] Support llvm-mingw toolchain zlib-ng requires some patches to make it compilable on LLVM-mingw. 1. Add -Wno-pedantic-ms-format only if a toolchain is MinGW GCC. - llvm-mingw does not support it, causing build to break. 2. Include arm_neon.h instead of arm64_neon.h (aarch64 only). - arm64_neon.h is MSVC only. - GCC, Clang does not have arm64_neon.h but arm_neon.h on aarch64. - Also applied to configure and detect-instrinsics.cmake --- CMakeLists.txt | 6 +++++- arch/arm/neon_intrins.h | 3 ++- cmake/detect-intrinsics.cmake | 2 +- configure | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7dc46be06..6b53e8c897 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,7 +239,11 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif() endif() if(MINGW) - list(APPEND WARNFLAGS_DISABLE -Wno-pedantic-ms-format) + # Add `-Wno-pedantic-ms-format` only if the toolchain is GCC MinGW-w64 + # llvm-mingw does not support '-Wno-pedantic-ms-format' + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + list(APPEND WARNFLAGS_DISABLE -Wno-pedantic-ms-format) + endif() endif() endif() diff --git a/arch/arm/neon_intrins.h b/arch/arm/neon_intrins.h index 478697a6de..51df77dbe6 100644 --- a/arch/arm/neon_intrins.h +++ b/arch/arm/neon_intrins.h @@ -1,7 +1,8 @@ #ifndef ARM_NEON_INTRINS_H #define ARM_NEON_INTRINS_H -#if defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC)) +/* arm64_neon.h is MSVC specific */ # include #else # include diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index fe1848e62c..250ee44e5d 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -222,7 +222,7 @@ macro(check_neon_ld4_intrinsics) # Check whether compiler supports loading 4 neon vecs into a register range set(CMAKE_REQUIRED_FLAGS "${NEONFLAG}") check_c_source_compiles( - "#if defined(_M_ARM64) || defined(_M_ARM64EC) + "#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC)) # include #else # include diff --git a/configure b/configure index 29de72cecf..a660a17e87 100755 --- a/configure +++ b/configure @@ -1164,7 +1164,7 @@ EOF check_neon_ld4_intrinsics() { cat > $test.c << EOF -#if defined(_M_ARM64) || defined(_M_ARM64EC) +#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC)) # include #else # include From 9a056b81ae90fe59f0fc77b8d06e1e97452b45aa Mon Sep 17 00:00:00 2001 From: Hajin Jang Date: Sun, 24 Sep 2023 13:07:22 +0900 Subject: [PATCH 746/798] Add llvm-mingw CMake toolchain files --- cmake/toolchain-llvm-mingw-aarch64.cmake | 41 ++++++++++++++++++++++++ cmake/toolchain-llvm-mingw-armv7.cmake | 41 ++++++++++++++++++++++++ cmake/toolchain-llvm-mingw-i686.cmake | 41 ++++++++++++++++++++++++ cmake/toolchain-llvm-mingw-x86_64.cmake | 41 ++++++++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 cmake/toolchain-llvm-mingw-aarch64.cmake create mode 100644 cmake/toolchain-llvm-mingw-armv7.cmake create mode 100644 cmake/toolchain-llvm-mingw-i686.cmake create mode 100644 cmake/toolchain-llvm-mingw-x86_64.cmake diff --git a/cmake/toolchain-llvm-mingw-aarch64.cmake b/cmake/toolchain-llvm-mingw-aarch64.cmake new file mode 100644 index 0000000000..4da1e2c796 --- /dev/null +++ b/cmake/toolchain-llvm-mingw-aarch64.cmake @@ -0,0 +1,41 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_C_COMPILER_FRONTEND_VARIANT GNU) +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR wine) + +set(CMAKE_C_COMPILER_TARGET aarch64-w64-mingw32) +set(CMAKE_CXX_COMPILER_TARGET aarch64-w64-mingw32) +set(CMAKE_RC_COMPILER_TARGET aarch64-w64-mingw32) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +# Required to propagate 'LLVM_MINGW_ROOT' variables to C compiler feature test. +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES LLVM_MINGW_ROOT) + +if(NOT LLVM_MINGW_ROOT) + set(LLVM_MINGW_ROOT $ENV{LLVM_MINGW_ROOT}) +endif() +cmake_path(CONVERT "${LLVM_MINGW_ROOT}" TO_CMAKE_PATH_LIST LLVM_MINGW_ROOT) + +set(CMAKE_FIND_ROOT_PATH ${LLVM_MINGW_ROOT} ${LLVM_MINGW_ROOT}/aarch64-w64-mingw32) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ALWAYS) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-clang HINTS ${LLVM_MINGW_ROOT}/bin) +if(NOT C_COMPILER_FULL_PATH) +message(FATAL_ERROR "Compiler for ${CMAKE_C_COMPILER_TARGET} not found. Try setting llvm-mingw root path to LLVM_MINGW_ROOT variable!") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH ${CMAKE_CXX_COMPILER_TARGET}-clang++ HINTS ${LLVM_MINGW_ROOT}/bin) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() + +find_program(RC_COMPILER_FULL_PATH ${CMAKE_RC_COMPILER_TARGET}-windres HINTS ${LLVM_MINGW_ROOT}/bin) +if(RC_COMPILER_FULL_PATH) + set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) +endif() + +add_compile_options($<$:-gcodeview>) +add_link_options(-Wl,-pdb=) diff --git a/cmake/toolchain-llvm-mingw-armv7.cmake b/cmake/toolchain-llvm-mingw-armv7.cmake new file mode 100644 index 0000000000..d077309b86 --- /dev/null +++ b/cmake/toolchain-llvm-mingw-armv7.cmake @@ -0,0 +1,41 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_C_COMPILER_FRONTEND_VARIANT GNU) +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR wine) + +set(CMAKE_C_COMPILER_TARGET armv7-w64-mingw32) +set(CMAKE_CXX_COMPILER_TARGET armv7-w64-mingw32) +set(CMAKE_RC_COMPILER_TARGET armv7-w64-mingw32) +set(CMAKE_SYSTEM_PROCESSOR armv7) + +# Required to propagate 'LLVM_MINGW_ROOT' variables to C compiler feature test. +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES LLVM_MINGW_ROOT) + +if(NOT LLVM_MINGW_ROOT) + set(LLVM_MINGW_ROOT $ENV{LLVM_MINGW_ROOT}) +endif() +cmake_path(CONVERT "${LLVM_MINGW_ROOT}" TO_CMAKE_PATH_LIST LLVM_MINGW_ROOT) + +set(CMAKE_FIND_ROOT_PATH ${LLVM_MINGW_ROOT} ${LLVM_MINGW_ROOT}/armv7-w64-mingw32) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ALWAYS) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-clang HINTS ${LLVM_MINGW_ROOT}/bin) +if(NOT C_COMPILER_FULL_PATH) +message(FATAL_ERROR "Compiler for ${CMAKE_C_COMPILER_TARGET} not found. Try setting llvm-mingw root path to LLVM_MINGW_ROOT variable!") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH ${CMAKE_CXX_COMPILER_TARGET}-clang++ HINTS ${LLVM_MINGW_ROOT}/bin) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() + +find_program(RC_COMPILER_FULL_PATH ${CMAKE_RC_COMPILER_TARGET}-windres HINTS ${LLVM_MINGW_ROOT}/bin) +if(RC_COMPILER_FULL_PATH) + set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) +endif() + +add_compile_options($<$:-gcodeview>) +add_link_options(-Wl,-pdb=) diff --git a/cmake/toolchain-llvm-mingw-i686.cmake b/cmake/toolchain-llvm-mingw-i686.cmake new file mode 100644 index 0000000000..17a0aa7909 --- /dev/null +++ b/cmake/toolchain-llvm-mingw-i686.cmake @@ -0,0 +1,41 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_C_COMPILER_FRONTEND_VARIANT GNU) +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR wine) + +set(CMAKE_C_COMPILER_TARGET i686-w64-mingw32) +set(CMAKE_CXX_COMPILER_TARGET i686-w64-mingw32) +set(CMAKE_RC_COMPILER_TARGET i686-w64-mingw32) +set(CMAKE_SYSTEM_PROCESSOR i686) + +# Required to propagate 'LLVM_MINGW_ROOT' variables to C compiler feature test. +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES LLVM_MINGW_ROOT) + +if(NOT LLVM_MINGW_ROOT) + set(LLVM_MINGW_ROOT $ENV{LLVM_MINGW_ROOT}) +endif() +cmake_path(CONVERT "${LLVM_MINGW_ROOT}" TO_CMAKE_PATH_LIST LLVM_MINGW_ROOT) + +set(CMAKE_FIND_ROOT_PATH ${LLVM_MINGW_ROOT} ${LLVM_MINGW_ROOT}/i686-w64-mingw32) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ALWAYS) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-clang HINTS ${LLVM_MINGW_ROOT}/bin) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Compiler for ${CMAKE_C_COMPILER_TARGET} not found. Try setting llvm-mingw root path to LLVM_MINGW_ROOT variable!") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH ${CMAKE_CXX_COMPILER_TARGET}-clang++ HINTS ${LLVM_MINGW_ROOT}/bin) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() + +find_program(RC_COMPILER_FULL_PATH ${CMAKE_RC_COMPILER_TARGET}-windres HINTS ${LLVM_MINGW_ROOT}/bin) +if(RC_COMPILER_FULL_PATH) + set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) +endif() + +add_compile_options($<$:-gcodeview>) +add_link_options(-Wl,-pdb=) diff --git a/cmake/toolchain-llvm-mingw-x86_64.cmake b/cmake/toolchain-llvm-mingw-x86_64.cmake new file mode 100644 index 0000000000..e519562418 --- /dev/null +++ b/cmake/toolchain-llvm-mingw-x86_64.cmake @@ -0,0 +1,41 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_C_COMPILER_FRONTEND_VARIANT GNU) +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR wine) + +set(CMAKE_C_COMPILER_TARGET x86_64-w64-mingw32) +set(CMAKE_CXX_COMPILER_TARGET x86_64-w64-mingw32) +set(CMAKE_RC_COMPILER_TARGET x86_64-w64-mingw32) +set(CMAKE_SYSTEM_PROCESSOR x86_64) + +# Required to propagate 'LLVM_MINGW_ROOT' variables to C compiler feature test. +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES LLVM_MINGW_ROOT) + +if(NOT LLVM_MINGW_ROOT) + set(LLVM_MINGW_ROOT $ENV{LLVM_MINGW_ROOT}) +endif() +cmake_path(CONVERT "${LLVM_MINGW_ROOT}" TO_CMAKE_PATH_LIST LLVM_MINGW_ROOT) + +set(CMAKE_FIND_ROOT_PATH ${LLVM_MINGW_ROOT} ${LLVM_MINGW_ROOT}/x86_64-w64-mingw32) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ALWAYS) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-clang HINTS ${LLVM_MINGW_ROOT}/bin) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Compiler for ${CMAKE_C_COMPILER_TARGET} not found. Try setting llvm-mingw root path to LLVM_MINGW_ROOT variable!") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH ${CMAKE_CXX_COMPILER_TARGET}-clang++ HINTS ${LLVM_MINGW_ROOT}/bin) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() + +find_program(RC_COMPILER_FULL_PATH ${CMAKE_RC_COMPILER_TARGET}-windres HINTS ${LLVM_MINGW_ROOT}/bin) +if(RC_COMPILER_FULL_PATH) + set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) +endif() + +add_compile_options($<$:-gcodeview>) +add_link_options(-Wl,-pdb=) From a6139b349108f40f1b570e7ed49102d46e284a9d Mon Sep 17 00:00:00 2001 From: Hajin Jang Date: Tue, 26 Sep 2023 02:15:10 +0900 Subject: [PATCH 747/798] Detect -Wno-pedantic-ms-format support in mingw Use check_c_compiler_flag() feature of CMake to figure out whether this mingw toolchain has support for -Wno-pedantic-ms-format or not. This flag will be added only if the toolchain supports it. Currently, MinGW-w64 GCC has it, and llvm-mingw does not have it. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b53e8c897..974af49ca5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,9 +239,9 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif() endif() if(MINGW) - # Add `-Wno-pedantic-ms-format` only if the toolchain is GCC MinGW-w64 - # llvm-mingw does not support '-Wno-pedantic-ms-format' - if(CMAKE_C_COMPILER_ID MATCHES "GNU") + # Add `-Wno-pedantic-ms-format` only if the toolchain supports it + check_c_compiler_flag(-Wno-pedantic-ms-format HAVE_NO_PEDANTIC_MS_FORMAT) + if(HAVE_NO_PEDANTIC_MS_FORMAT) list(APPEND WARNFLAGS_DISABLE -Wno-pedantic-ms-format) endif() endif() From 2ad0cd0d259422a58444d1d051289c0dab8ce671 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 21 Sep 2023 12:45:13 +0200 Subject: [PATCH 748/798] Deprecate ZLIBNG_VER_STATUS, add new variant ZLIBNG_VER_STATUSH --- zlib-ng.h.in | 3 ++- zlib.h.in | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/zlib-ng.h.in b/zlib-ng.h.in index b3fdf87d9c..d234c1443a 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -53,7 +53,8 @@ extern "C" { #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 #define ZLIBNG_VER_REVISION 3 -#define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ +#define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ /* diff --git a/zlib.h.in b/zlib.h.in index ed25ccc646..6d5f7a5ac4 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -54,7 +54,8 @@ extern "C" { #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 #define ZLIBNG_VER_REVISION 3 -#define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ +#define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ #define ZLIB_VERSION "1.3.0.zlib-ng" From 61e181c8ae93dbf56040336179c9954078bd1399 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 25 Sep 2023 15:23:41 +0200 Subject: [PATCH 749/798] Make sure inflateCopy() allocates window with the necessary buffer for chunked operations. Based on Chromium bugfix https://chromium-review.googlesource.com/c/chromium/src/+/4876445 --- inflate.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/inflate.c b/inflate.c index 0cbed041d7..a01e10f7a5 100644 --- a/inflate.c +++ b/inflate.c @@ -1319,8 +1319,6 @@ int32_t Z_EXPORT PREFIX(inflateSyncPoint)(PREFIX3(stream) *strm) { int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *source) { struct inflate_state *state; struct inflate_state *copy; - unsigned char *window; - unsigned wsize; /* check input */ if (inflateStateCheck(source) || dest == NULL) @@ -1331,15 +1329,6 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou copy = ZALLOC_INFLATE_STATE(source); if (copy == NULL) return Z_MEM_ERROR; - window = NULL; - if (state->window != NULL) { - wsize = 1U << state->wbits; - window = (unsigned char *)ZALLOC_WINDOW(source, wsize, sizeof(unsigned char)); - if (window == NULL) { - ZFREE_STATE(source, copy); - return Z_MEM_ERROR; - } - } /* copy state */ memcpy((void *)dest, (void *)source, sizeof(PREFIX3(stream))); @@ -1350,10 +1339,17 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou copy->distcode = copy->codes + (state->distcode - state->codes); } copy->next = copy->codes + (state->next - state->codes); - if (window != NULL) { - ZCOPY_WINDOW(window, state->window, (size_t)1U << state->wbits); + + /* window */ + if (state->window != NULL) { + copy->window = NULL; + if (PREFIX(inflate_ensure_window)(copy)) { + ZFREE_STATE(source, copy); + return Z_MEM_ERROR; + } + ZCOPY_WINDOW(copy->window, state->window, (size_t)state->wsize); } - copy->window = window; + dest->state = (struct internal_state *)copy; return Z_OK; } From 6ff8b52cefe56a824fae1d53fdd687bcde2e53c9 Mon Sep 17 00:00:00 2001 From: Xeonacid Date: Sun, 8 Oct 2023 11:30:54 +0800 Subject: [PATCH 750/798] Support RVV hwcap detect at runtime Fallback to compile-time detect if kernel version lower than 6.5. Co-authored-by: Hans Kristian Rosbach Signed-off-by: Xeonacid --- arch/riscv/README.md | 6 +++--- arch/riscv/riscv_features.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/arch/riscv/README.md b/arch/riscv/README.md index b4309e1a0a..013095c373 100644 --- a/arch/riscv/README.md +++ b/arch/riscv/README.md @@ -1,10 +1,10 @@ # Building RISC-V Target with Cmake # > **Warning** -> We cannot detect rvv support at runtime, running the rvv code on a no-rvv target is a risk. Users should disable the rvv when the target does not support it. +> Runtime rvv detection (using `hwcap`) requires linux kernel 6.5 or newer. > -> We will have a better solution when the kernels update `hwcap` or `hwprobe` for risc-v. - +> When running on older kernels, we fall back to compile-time detection, potentially this can cause crashes if rvv is enabled at compile but not supported by the target cpu. +> Therefore if older kernel support is needed, rvv should be disabled if the target cpu does not support it. ## Prerequisite: Build RISC-V Clang Toolchain and QEMU ## If you don't have prebuilt clang and riscv64 qemu, you can refer to the [script](https://github.com/sifive/prepare-riscv-toolchain-qemu/blob/main/prepare_riscv_toolchain_qemu.sh) to get the source. Copy the script to the zlib-ng root directory, and run it to download the source and build them. Modify the content according to your conditions (e.g., toolchain version). diff --git a/arch/riscv/riscv_features.c b/arch/riscv/riscv_features.c index 362d714835..b066f427e0 100644 --- a/arch/riscv/riscv_features.c +++ b/arch/riscv/riscv_features.c @@ -1,15 +1,45 @@ #include #include #include +#include +#include #include "../../zbuild.h" #include "riscv_features.h" -/* TODO: detect risc-v cpu info at runtime when the kernel updates hwcap or hwprobe for risc-v */ -void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) { +#define ISA_V_HWCAP (1 << ('v' - 'a')) + +int Z_INTERNAL is_kernel_version_greater_or_equal_to_6_5() { + struct utsname buffer; + uname(&buffer); + + int major, minor; + if (sscanf(buffer.release, "%d.%d", &major, &minor) != 2) { + // Something bad with uname() + return 0; + } + + if (major > 6 || major == 6 && minor >= 5) + return 1; + return 0; +} + +void Z_INTERNAL riscv_check_features_compile_time(struct riscv_cpu_features *features) { #if defined(__riscv_v) && defined(__linux__) features->has_rvv = 1; #else features->has_rvv = 0; #endif } + +void Z_INTERNAL riscv_check_features_runtime(struct riscv_cpu_features *features) { + unsigned long hw_cap = getauxval(AT_HWCAP); + features->has_rvv = hw_cap & ISA_V_HWCAP; +} + +void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) { + if (is_kernel_version_greater_or_equal_to_6_5()) + riscv_check_features_runtime(features); + else + riscv_check_features_compile_time(features); +} From 6232532e885848ba9229743c172a606fd15c7ff3 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Mon, 16 Oct 2023 23:46:26 +0300 Subject: [PATCH 751/798] Fix cross-compiling benchmarks and libpng. --- test/benchmarks/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index 475fe07cee..616954fc0e 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -54,10 +54,8 @@ if(WIN32) target_link_libraries(benchmark_zlib shlwapi) endif() -if(ZLIB_ENABLE_TESTS) - add_test(NAME benchmark_zlib - COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) -endif() +add_test(NAME benchmark_zlib + COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) if(WITH_BENCHMARK_APPS) option(BUILD_ALT_BENCH "Link against alternative zlib implementation" OFF) @@ -72,7 +70,8 @@ if(WITH_BENCHMARK_APPS) FetchContent_GetProperties(PNG) if(NOT PNG_POPULATED) FetchContent_Populate(PNG) - add_subdirectory(${PNG_SOURCE_DIR} ${PNG_BINARY_DIR}) + set(PNG_INCLUDE_DIR ${png_SOURCE_DIR}) + add_subdirectory(${png_SOURCE_DIR} ${png_BINARY_DIR}) endif() endif() From 2bce8282374459c7a8f385d222125b1f9c2d8272 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 15 Oct 2023 22:10:46 +0300 Subject: [PATCH 752/798] Fix building benchmarks on 32-bit PowerPC. --- test/benchmarks/benchmark_crc32.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index b2b9673d9f..02a9f28eef 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -59,7 +59,7 @@ BENCHMARK_CRC32(braid, PREFIX(crc32_braid), 1); #ifdef ARM_ACLE BENCHMARK_CRC32(acle, crc32_acle, test_cpu_features.arm.has_crc32); -#elif defined(POWER8_VSX) +#elif defined(POWER8_VSX_CRC32) BENCHMARK_CRC32(power8, crc32_power8, test_cpu_features.power.has_arch_2_07); #elif defined(S390_CRC32_VX) BENCHMARK_CRC32(vx, crc32_s390_vx, test_cpu_features.s390.has_vx); From 9fb955b8ba734b6519fe1a35704a4bc0ef01a22d Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 13 Oct 2023 12:57:37 +0200 Subject: [PATCH 753/798] 2.1.4 Release --- Makefile.in | 2 +- zlib-ng.h.in | 6 +++--- zlib.h.in | 6 +++--- zutil.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.in b/Makefile.in index 316b742f1a..8e6b661cd9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.1.3 +VER=2.1.4 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h.in b/zlib-ng.h.in index d234c1443a..3af5fccd04 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -48,11 +48,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.3" -#define ZLIBNG_VERNUM 0x020103F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.4" +#define ZLIBNG_VERNUM 0x020104F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 3 +#define ZLIBNG_VER_REVISION 4 #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ #define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ diff --git a/zlib.h.in b/zlib.h.in index 6d5f7a5ac4..46d5689fe9 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -49,11 +49,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.3" -#define ZLIBNG_VERNUM 0x020103F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.4" +#define ZLIBNG_VERNUM 0x020104F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 3 +#define ZLIBNG_VER_REVISION 4 #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ #define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ diff --git a/zutil.c b/zutil.c index 7893916150..72aa9e237e 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char PREFIX3(vstring)[] = - " zlib-ng 2.1.3"; + " zlib-ng 2.1.4"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From 1822957cc2a324f38f30630ef2e539dfe5765390 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 20 Oct 2023 22:30:32 +0200 Subject: [PATCH 754/798] Update to actions/checkout@v4, and disable checkout progress logging. --- .github/workflows/analyze.yml | 8 ++++++-- .github/workflows/cmake.yml | 7 +++++-- .github/workflows/codeql.yml | 4 +++- .github/workflows/configure.yml | 4 +++- .github/workflows/libpng.yml | 7 +++++-- .github/workflows/link.yml | 11 ++++++++--- .github/workflows/nmake.yml | 4 +++- .github/workflows/pigz.yml | 7 +++++-- .github/workflows/pkgcheck.yml | 4 +++- .github/workflows/release.yml | 4 +++- 10 files changed, 44 insertions(+), 16 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index cbdea0e504..8e4cdc3032 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -6,7 +6,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Add ubuntu mirrors run: | @@ -55,7 +57,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Install packages (Ubuntu) run: sudo apt-get install -y clang-tools diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 752d628d9e..80dc4bb3a9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -520,16 +520,19 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Checkout test corpora - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Don't test against all corpora with MinGW due to Wine being unable to run parallel jobs # without connection timeout. Without parallel jobs test runs using Wine take close to an hour. if: contains(matrix.name, 'MinGW') == false with: repository: zlib-ng/corpora path: test/data/corpora + show-progress: 'false' - name: Add repositories (Wine) if: contains(matrix.packages, 'wine32') diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1cfa4d7fa9..76f838178c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -24,7 +24,9 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 02a36005f8..15d35f081e 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -200,7 +200,9 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Add ubuntu mirrors if: runner.os == 'Linux' && matrix.packages diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index c5fea574fe..616401a49e 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -6,7 +6,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository (zlib-ng) - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Generate project files (zlib-ng) run: | @@ -24,10 +26,11 @@ jobs: run: cmake --build . -j2 --config Release - name: Checkout repository (libpng) - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: glennrp/libpng path: libpng + show-progress: 'false' - name: Generate project files (libpng) run: | diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml index 5de669840f..1c0ee54462 100644 --- a/.github/workflows/link.yml +++ b/.github/workflows/link.yml @@ -6,11 +6,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Checkout zlib repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: + show-progress: 'false' repository: madler/zlib path: zlib @@ -41,7 +44,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Generate project files (compat) run: cmake -S . -B compat -DZLIB_COMPAT=ON -DZLIB_ENABLE_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DWITH_MAINTAINER_WARNINGS=ON diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index 38e6690933..3176552c77 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -48,7 +48,9 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Setup development environment uses: ilammy/msvc-dev-cmd@v1.12.1 diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index be4e1ce507..534739e111 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -51,13 +51,16 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Checkout test corpora - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: zlib-ng/corpora path: test/data/corpora + show-progress: 'false' - name: Add ubuntu mirrors if: runner.os == 'Linux' && matrix.packages diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index e8483c717c..b2300dedcc 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -85,7 +85,9 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Add ubuntu mirrors if: runner.os == 'Linux' && matrix.packages diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b64933cc7c..4494fb3454 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,7 +61,9 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 + with: + show-progress: 'false' - name: Set environment variables shell: bash From af303eab2edbbd1e750c348465810b2d0285206a Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 20 Oct 2023 22:31:43 +0200 Subject: [PATCH 755/798] Fix status badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d848d7987d..1bae03881b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ | CI | Stable | Develop | |:---|:-------|:--------| -| GitHub Actions | [![Stable Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20CMake/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions)
    [![Stable Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20Configure/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions)
    [![Stable Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20NMake/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions) | [![Develop Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20CMake/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions)
    [![Develop Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20Configure/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions)
    [![Develop Status](https://github.com/zlib-ng/zlib-ng/workflows/CI%20NMake/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions) | +| GitHub Actions | [![Stable CMake](https://github.com/zlib-ng/zlib-ng/actions/workflows/cmake.yml/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions/workflows/cmake.yml?query=branch%3Astable)
    [![Stable Configure](https://github.com/zlib-ng/zlib-ng/actions/workflows/configure.yml/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions/workflows/configure.yml?query=branch%3Astable)
    [![Stable NMake](https://github.com/zlib-ng/zlib-ng/actions/workflows/nmake.yml/badge.svg?branch=stable)](https://github.com/zlib-ng/zlib-ng/actions/workflows/nmake.yml?query=branch%3Astable) | [![Develop CMake](https://github.com/zlib-ng/zlib-ng/actions/workflows/cmake.yml/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions/workflows/cmake.yml?query=branch%3Adevelop)
    [![Develop Configure](https://github.com/zlib-ng/zlib-ng/actions/workflows/configure.yml/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions/workflows/configure.yml?query=branch%3Adevelop)
    [![Develop NMake](https://github.com/zlib-ng/zlib-ng/actions/workflows/nmake.yml/badge.svg?branch=develop)](https://github.com/zlib-ng/zlib-ng/actions/workflows/nmake.yml?query=branch%3Adevelop) | | CodeFactor | [![CodeFactor](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/badge/stable)](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/overview/stable) | [![CodeFactor](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/badge/develop)](https://www.codefactor.io/repository/github/zlib-ng/zlib-ng/overview/develop) | | OSS-Fuzz | [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/zlib-ng.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zlib-ng) | [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/zlib-ng.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:zlib-ng) | | Codecov | [![codecov](https://codecov.io/github/zlib-ng/zlib-ng/branch/stable/graph/badge.svg?token=uKsgK9LIuC)](https://codecov.io/github/zlib-ng/zlib-ng/tree/stable) | [![codecov](https://codecov.io/github/zlib-ng/zlib-ng/branch/develop/graph/badge.svg?token=uKsgK9LIuC)](https://codecov.io/github/zlib-ng/zlib-ng/tree/develop) | From 4abe8881d730f072e5f1b396cbc301a6cb7ae064 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Mon, 30 Oct 2023 21:49:18 +0200 Subject: [PATCH 756/798] [README] configure no longer supports --native --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1bae03881b..4f9fe09c69 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Build Options | WITH_GZFILEOP | --without-gzfileops | Compile with support for gzFile related functions | ON | | WITH_OPTIM | --without-optimizations | Build with optimisations | ON | | WITH_NEW_STRATEGIES | --without-new-strategies | Use new strategies | ON | -| WITH_NATIVE_INSTRUCTIONS | --native | Compiles with full instruction set supported on this host (gcc/clang -march=native) | OFF | +| WITH_NATIVE_INSTRUCTIONS | | Compiles with full instruction set supported on this host (gcc/clang -march=native) | OFF | | WITH_SANITIZER | | Build with sanitizer (memory, address, undefined) | OFF | | WITH_GTEST | | Build gtest_zlib | ON | | WITH_FUZZERS | | Build test/fuzz | OFF | From 8770d93a026aef8a020956d8d36d000cbc8f1c2f Mon Sep 17 00:00:00 2001 From: Benjamin Buch Date: Mon, 30 Oct 2023 19:18:30 +0100 Subject: [PATCH 757/798] fix cmake header path in install with custom CMAKE_INSTALL_INCLUDEDIR --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 974af49ca5..a645ad6e7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1075,7 +1075,7 @@ foreach(ZLIB_INSTALL_LIBRARY ${ZLIB_INSTALL_LIBRARIES}) endif() target_include_directories(${ZLIB_INSTALL_LIBRARY} PUBLIC "$" - "$") + "$") endforeach() if(WIN32) From 0560a3a63dfdd6642724c8fad4db9dc58629f6bf Mon Sep 17 00:00:00 2001 From: Leander Schulten Date: Fri, 3 Nov 2023 23:31:11 +0100 Subject: [PATCH 758/798] pkgconfig file: propagate WITH_GZFILEOP --- CMakeLists.txt | 3 +++ zlib.pc.cmakein | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a645ad6e7c..fbc2bdbafb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1159,6 +1159,9 @@ else() endif() set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib${SUFFIX}.pc) +if(WITH_GZFILEOP) + set(PKG_CONFIG_CFLAGS "-DWITH_GZFILEOP") +endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein ${ZLIB_PC} @ONLY) configure_file(${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein diff --git a/zlib.pc.cmakein b/zlib.pc.cmakein index 3d440ce6bd..df8bf9f051 100644 --- a/zlib.pc.cmakein +++ b/zlib.pc.cmakein @@ -11,4 +11,4 @@ Version: @ZLIB_FULL_VERSION@ Requires: Libs: -L${libdir} -L${sharedlibdir} -lz@SUFFIX@ -Cflags: -I${includedir} +Cflags: -I${includedir} @PKG_CONFIG_CFLAGS@ From 6592accb2541aa637844cabef16b7adbb4cec4e1 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Tue, 7 Nov 2023 19:06:21 +0200 Subject: [PATCH 759/798] [configure] Propagate -DWITH_GZFILEOP to pkgconfig. --- configure | 6 ++++++ zlib.pc.in | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/configure b/configure index a660a17e87..501f51badd 100755 --- a/configure +++ b/configure @@ -76,6 +76,7 @@ RCFLAGS= RCOBJS= STRIP= ARCHS= +PC_CFLAGS= prefix=${prefix-/usr/local} exec_prefix=${exec_prefix-'${prefix}'} bindir=${bindir-'${exec_prefix}/bin'} @@ -2140,6 +2141,10 @@ if test -n "$EMU_RUN"; then echo "Using cross-compile emulator: $EMU_RUN" fi +if test $gzfileops -eq 1; then + PC_CFLAGS="-DWITH_GZFILEOP" +fi + # Generate Makefile in test dir mkdir -p test sed < $SRCDIR/test/Makefile.in " @@ -2182,6 +2187,7 @@ sed < $SRCDIR/zlib.pc.in " " | sed -e " s/\@VERSION\@/$VER/g; s/\@SUFFIX\@/$SUFFIX/g; +s/\@PKG_CONFIG_CFLAGS\@/$PC_CFLAGS/g; " > ${LIBNAME2}.pc # done diff --git a/zlib.pc.in b/zlib.pc.in index a0678fbe03..45b35989b1 100644 --- a/zlib.pc.in +++ b/zlib.pc.in @@ -11,4 +11,4 @@ Version: @VERSION@ Requires: Libs: -L${libdir} -L${sharedlibdir} -lz@SUFFIX@ -Cflags: -I${includedir} +Cflags: -I${includedir} @PKG_CONFIG_CFLAGS@ From 0b3bb1d823245334861628176ccec4095f352cbf Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 21 Nov 2023 22:30:45 -0800 Subject: [PATCH 760/798] Added unit test for inflate with Z_FINISH and no window. This test decompresses a small git pack object with the text: "alone in the dark". By providing inflate with Z_FINISH, it should not use a sliding window according to zlib docs. We purposefully limit the read buffer size to trigger CHECK mode to bail early. --- test/GH-1600/packobj.gz | Bin 0 -> 46 bytes test/cmake/test-issues.cmake | 8 ++++++++ test/minideflate.c | 6 ++++++ 3 files changed, 14 insertions(+) create mode 100644 test/GH-1600/packobj.gz diff --git a/test/GH-1600/packobj.gz b/test/GH-1600/packobj.gz new file mode 100644 index 0000000000000000000000000000000000000000..d6c4405cf489be8482e7f06fe41659f8c31f6715 GIT binary patch literal 46 zcmV+}0MY+=oJ-8f&r4Ov%u^`INL5HlEXw8r06qf-H2T4r2D+Ldf$6c$ Date: Fri, 17 Nov 2023 18:26:45 -0500 Subject: [PATCH 761/798] Fix an issue with regard to finishing out the window if inflate is invoked with Z_FINISH, and it deems a window was not necessary, there's a corner case where we never checksum the bytes. Detect this by checking the window size against zero and the value of the flush parameter. This should fix issue #1600, and possibly #1565 as well. --- inflate.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/inflate.c b/inflate.c index a01e10f7a5..0c9d499f63 100644 --- a/inflate.c +++ b/inflate.c @@ -1112,11 +1112,12 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { */ inf_leave: RESTORE(); + uint32_t check_bytes = out - strm->avail_out; if (INFLATE_NEED_UPDATEWINDOW(strm) && (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH)))) { /* update sliding window with respective checksum if not in "raw" mode */ - if (updatewindow(strm, strm->next_out, out - strm->avail_out, state->wrap & 4)) { + if (updatewindow(strm, strm->next_out, check_bytes, state->wrap & 4)) { state->mode = MEM; return Z_MEM_ERROR; } @@ -1129,8 +1130,13 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) { + /* when no sliding window is used, hash the output bytes if no CHECK state */ + if (INFLATE_NEED_CHECKSUM(strm) && !state->wsize && flush == Z_FINISH) { + inf_chksum(strm, put - check_bytes, check_bytes); + } ret = Z_BUF_ERROR; + } return ret; } From 2bc66887ddc0c50776811a27be68e34430d665e1 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 26 Nov 2023 20:56:58 +0100 Subject: [PATCH 762/798] 2.1.5 Release --- Makefile.in | 2 +- zlib-ng.h.in | 6 +++--- zlib.h.in | 6 +++--- zutil.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.in b/Makefile.in index 8e6b661cd9..d2bd47f171 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.1.4 +VER=2.1.5 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 3af5fccd04..de811e05e3 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -48,11 +48,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.4" -#define ZLIBNG_VERNUM 0x020104F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.5" +#define ZLIBNG_VERNUM 0x020105F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 4 +#define ZLIBNG_VER_REVISION 5 #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ #define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ diff --git a/zlib.h.in b/zlib.h.in index 46d5689fe9..9e27d99c07 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -49,11 +49,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.4" -#define ZLIBNG_VERNUM 0x020104F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.5" +#define ZLIBNG_VERNUM 0x020105F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 4 +#define ZLIBNG_VER_REVISION 5 #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ #define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ diff --git a/zutil.c b/zutil.c index 72aa9e237e..bd937c55e8 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char PREFIX3(vstring)[] = - " zlib-ng 2.1.4"; + " zlib-ng 2.1.5"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From 1003ae6b6ae7dd6b1e2511d12c5d99754a7bb8bd Mon Sep 17 00:00:00 2001 From: Yoshiki Matsuda Date: Mon, 23 Oct 2023 18:33:16 +0900 Subject: [PATCH 763/798] Fix clang-cl warnings --- cmake/detect-intrinsics.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 250ee44e5d..fb7c735b76 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -85,7 +85,7 @@ macro(check_avx512_intrinsics) # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal # instruction scheduling unless you specify a reasonable -mtune= target set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl") - if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "[Cc][Ll][Aa][Nn][Gg][Cc][Ll]") + if(NOT MSVC) check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) if(HAVE_CASCADE_LAKE) set(AVX512FLAG "${AVX512FLAG} -mtune=cascadelake") @@ -130,7 +130,7 @@ macro(check_avx512vnni_intrinsics) elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) set(AVX512VNNIFLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx512vnni") - if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "[Cc][Ll][Aa][Nn][Gg][Cc][Ll]") + if(NOT MSVC) check_c_compiler_flag("-mtune=cascadelake" HAVE_CASCADE_LAKE) if(HAVE_CASCADE_LAKE) set(AVX512VNNIFLAG "${AVX512VNNIFLAG} -mtune=cascadelake") From f3211aba349a1d4781d0d41cb00d29fb8325af06 Mon Sep 17 00:00:00 2001 From: Simon Hosie Date: Mon, 6 Nov 2023 15:39:34 -0800 Subject: [PATCH 764/798] Add adler32_fold_copy_rvv implementation. --- arch/riscv/adler32_rvv.c | 33 ++++++++++++++++++++++++--------- cpu_features.h | 3 +++ functable.c | 1 + 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/arch/riscv/adler32_rvv.c b/arch/riscv/adler32_rvv.c index 9442f28003..da46f37e73 100644 --- a/arch/riscv/adler32_rvv.c +++ b/arch/riscv/adler32_rvv.c @@ -12,23 +12,25 @@ #include "../../zbuild.h" #include "../../adler32_p.h" -Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) { +static inline uint32_t adler32_rvv_impl(uint32_t adler, uint8_t* restrict dst, const uint8_t *src, size_t len, int COPY) { /* split Adler-32 into component sums */ uint32_t sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; /* in case user likes doing a byte at a time, keep it fast */ if (len == 1) { - return adler32_len_1(adler, buf, sum2); + if (COPY) memcpy(dst, src, 1); + return adler32_len_1(adler, src, sum2); } /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == NULL) + if (src == NULL) return 1L; /* in case short lengths are provided, keep it somewhat fast */ if (len < 16) { - return adler32_len_16(adler, buf, len, sum2); + if (COPY) memcpy(dst, src, len); + return adler32_len_16(adler, src, len, sum2); } size_t left = len; @@ -56,10 +58,12 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); size_t subprob = block_size; while (subprob > 0) { - vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(buf, vl); + vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(src, vl); + if (COPY) __riscv_vse8_v_u8m1(dst, v_buf8, vl); v_adler32_prev_accu = __riscv_vwaddu_wv_u32m4(v_adler32_prev_accu, v_buf16_accu, vl); v_buf16_accu = __riscv_vwaddu_wv_u16m2(v_buf16_accu, v_buf8, vl); - buf += vl; + src += vl; + if (COPY) dst += vl; subprob -= vl; } v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, block_size / vl, v_buf32_accu, vl); @@ -75,10 +79,12 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl); size_t res = left; while (left >= vl) { - vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(buf, vl); + vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(src, vl); + if (COPY) __riscv_vse8_v_u8m1(dst, v_buf8, vl); v_adler32_prev_accu = __riscv_vwaddu_wv_u32m4(v_adler32_prev_accu, v_buf16_accu, vl); v_buf16_accu = __riscv_vwaddu_wv_u16m2(v_buf16_accu, v_buf8, vl); - buf += vl; + src += vl; + if (COPY) dst += vl; left -= vl; } v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, res / vl, v_buf32_accu, vl); @@ -104,7 +110,8 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) adler += adler_sum; while (left--) { - adler += *buf++; + if (COPY) *dst++ = *src; + adler += *src++; sum2 += adler; } @@ -114,4 +121,12 @@ Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) return adler | (sum2 << 16); } +Z_INTERNAL uint32_t adler32_fold_copy_rvv(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + return adler32_rvv_impl(adler, dst, src, len, 1); +} + +Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) { + return adler32_rvv_impl(adler, NULL, buf, len, 0); +} + #endif // RISCV_RVV diff --git a/cpu_features.h b/cpu_features.h index aed1eaf90f..00fa6c747c 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -70,6 +70,9 @@ extern uint32_t adler32_power8(uint32_t adler, const uint8_t *buf, size_t len); #endif /* adler32 folding */ +#ifdef RISCV_RVV +extern uint32_t adler32_fold_copy_rvv(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif #ifdef X86_SSE42 extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif diff --git a/functable.c b/functable.c index df35bae7c0..f664d280d8 100644 --- a/functable.c +++ b/functable.c @@ -215,6 +215,7 @@ static void init_functable(void) { #ifdef RISCV_RVV if (cf.riscv.has_rvv) { ft.adler32 = &adler32_rvv; + ft.adler32_fold_copy = &adler32_fold_copy_rvv; ft.chunkmemset_safe = &chunkmemset_safe_rvv; ft.chunksize = &chunksize_rvv; ft.compare256 = &compare256_rvv; From 7d012acbc224cc9d43aed63bb5167ab1e28779cc Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sun, 26 Nov 2023 22:48:31 +0500 Subject: [PATCH 765/798] Run OSB tests with readonly source directory. Signed-off-by: Vladislav Shchapov --- .github/workflows/cmake.yml | 13 +++++++++++++ test/cmake/compress-and-verify.cmake | 6 +++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 80dc4bb3a9..dfda736770 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -51,6 +51,8 @@ jobs: cxx-compiler: g++ build-dir: ../build build-src-dir: ../zlib-ng + # Build with readonly project directory require CMake 3.19+ + readonly-project-dir: true codecov: ubuntu_gcc_osb cflags: -O3 @@ -60,6 +62,7 @@ jobs: cxx-compiler: g++ build-dir: ../build build-src-dir: ../zlib-ng/test/add-subdirectory-project + readonly-project-dir: true - name: Ubuntu GCC -O1 No Unaligned UBSAN os: ubuntu-latest @@ -598,6 +601,11 @@ jobs: CC: ${{ matrix.compiler }} CXX: ${{ matrix.cxx-compiler }} + - name: Make source tree read-only + shell: bash + run: chmod -R a-w . + if: matrix.readonly-project-dir + - name: Generate project files shell: bash # Shared libraries turned off for qemu ppc* and sparc & reduce code coverage sources @@ -630,6 +638,11 @@ jobs: LSAN_OPTIONS: ${{ matrix.lsan-options || 'verbosity=0' }}:abort_on_error=1:halt_on_error=1 UBSAN_OPTIONS: ${{ matrix.ubsan-options || 'verbosity=0' }}:print_stacktrace=1:abort_on_error=1:halt_on_error=1 + - name: Make source tree writable + shell: bash + run: chmod -R +w . + if: matrix.readonly-project-dir + - name: Generate coverage report if: matrix.codecov shell: bash diff --git a/test/cmake/compress-and-verify.cmake b/test/cmake/compress-and-verify.cmake index d2d9917a93..2e6c37f145 100644 --- a/test/cmake/compress-and-verify.cmake +++ b/test/cmake/compress-and-verify.cmake @@ -138,7 +138,11 @@ set(COMPRESS_COMMAND ${COMPRESS_TARGET} ${COMPRESS_ARGS}) set(INPUT_FILE ${OUTPUT_BASE}) # Make CMake copy and rename file in one operation -configure_file(${INPUT} ${INPUT_FILE} COPYONLY) +# The copied file permissions is standard 644 (-rw-r--r--) +if(NOT CMAKE_VERSION VERSION_LESS "3.19") + set(CONFIGURE_NO_SOURCE_PERMISSIONS NO_SOURCE_PERMISSIONS) +endif() +configure_file(${INPUT} ${INPUT_FILE} COPYONLY ${CONFIGURE_NO_SOURCE_PERMISSIONS}) message(STATUS "Compress ${COMPRESS_COMMAND}") message(STATUS " Source file: ${INPUT}") From 601ef90c36393affd994a6a84fc4ff586f7bec47 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Mon, 27 Nov 2023 00:13:49 +0500 Subject: [PATCH 766/798] Prevent tests writing into the source directory. Signed-off-by: Vladislav Shchapov --- test/cmake/test-issues.cmake | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/test/cmake/test-issues.cmake b/test/cmake/test-issues.cmake index 05a3500042..e731dd57dd 100644 --- a/test/cmake/test-issues.cmake +++ b/test/cmake/test-issues.cmake @@ -67,10 +67,18 @@ add_test(NAME GH-751 -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/GH-751/test.txt -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/compress-and-verify.cmake) -set(TEST_COMMAND ${MINIDEFLATE_COMMAND} - "-d;-k;-s;4;${CMAKE_CURRENT_SOURCE_DIR}/GH-1600/packobj.gz") -add_test(NAME GH-1600-no-window-check COMMAND ${TEST_COMMAND}) +set(TEST_COMMAND "${MINIDEFLATE_COMMAND};-c;-d;-k;-s;4") +add_test(NAME GH-1600-no-window-check + COMMAND ${CMAKE_COMMAND} + "-DCOMMAND=${TEST_COMMAND}" + "-DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/GH-1600/packobj.gz" + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake +) -set(TEST_COMMAND ${MINIDEFLATE_COMMAND} - "-d;-k;-s;4;-r;25;${CMAKE_CURRENT_SOURCE_DIR}/GH-1600/packobj.gz") -add_test(NAME GH-1600-no-window-no-check COMMAND ${TEST_COMMAND}) +set(TEST_COMMAND "${MINIDEFLATE_COMMAND};-c;-d;-k;-s;4;-r;25") +add_test(NAME GH-1600-no-window-no-check + COMMAND ${CMAKE_COMMAND} + "-DCOMMAND=${TEST_COMMAND}" + "-DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/GH-1600/packobj.gz" + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake +) From ecccc9a940ba38f17d036df8170705651244c430 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 7 Nov 2023 14:54:18 -0500 Subject: [PATCH 767/798] Simplify AVX2 adler32_fold_copy by removing templates --- arch/x86/adler32_avx2.c | 145 +++++++++++++++++++++++++++++++++++- arch/x86/adler32_avx2_tpl.h | 141 ----------------------------------- 2 files changed, 141 insertions(+), 145 deletions(-) delete mode 100644 arch/x86/adler32_avx2_tpl.h diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index 797d299e09..e3ac6705ce 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -1,17 +1,154 @@ /* adler32_avx2.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 2022 Adam Stylinski * Authors: * Brian Bockelman + * Adam Stylinski * For conditions of distribution and use, see copyright notice in zlib.h */ +#ifdef X86_AVX2 + +#include "../../zbuild.h" #include +#include "../../adler32_fold.h" +#include "../../adler32_p.h" +#include "adler32_avx2_p.h" +#include "x86_intrins.h" -#ifdef X86_AVX2 +#ifdef X86_SSE42 +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len); + +#define copy_sub32(a, b, c, d) adler32_fold_copy_sse42(a, b, c, d) +#define sub32(a, b, c) adler32_ssse3(a, b, c) +#else +#define copy_sub32(a, b, c, d) adler32_copy_len_16(adler0, c, b, d, adler1) +#define sub32(a, b, c) adler32_len_16(adler0, b, c, adler1) +#endif + +static inline uint32_t adler32_fold_copy_impl(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len, const int COPY) { + if (src == NULL) return 1L; + if (len == 0) return adler; + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel: + if (len < 16) { + if (COPY) { + return adler32_copy_len_16(adler0, src, dst, len, adler1); + } else { + return adler32_len_16(adler0, src, len, adler1); + } + } else if (len < 32) { + if (COPY) { + return copy_sub32(adler, dst, src, len); + } else { + return sub32(adler, src, len); + } + } + + __m256i vs1, vs2; + + const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m256i dot3v = _mm256_set1_epi16(1); + const __m256i zero = _mm256_setzero_si256(); + + while (len >= 32) { + vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0)); + vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1)); + __m256i vs1_0 = vs1; + __m256i vs3 = _mm256_setzero_si256(); + + size_t k = MIN(len, NMAX); + k -= k % 32; + len -= k; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 32 vs1 + sum( (32-i+1) c[i] ) + */ + __m256i vbuf = _mm256_loadu_si256((__m256i*)src); + src += 32; + k -= 32; + + __m256i vs1_sad = _mm256_sad_epu8(vbuf, zero); // Sum of abs diff, resulting in 2 x int32's + + if (COPY) { + _mm256_storeu_si256((__m256i*)dst, vbuf); + dst += 32; + } + + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs3 = _mm256_add_epi32(vs3, vs1_0); + __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); // sum 32 uint8s to 16 shorts + __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); // sum 16 shorts to 8 uint32s + vs2 = _mm256_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + /* Defer the multiplication with 32 to outside of the loop */ + vs3 = _mm256_slli_epi32(vs3, 5); + vs2 = _mm256_add_epi32(vs2, vs3); + + /* The compiler is generating the following sequence for this integer modulus + * when done the scalar way, in GPRs: + + adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + + (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); + + mov $0x80078071,%edi // move magic constant into 32 bit register %edi + ... + vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi + mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax + imul %rdi,%rsi // do a signed multiplication with magic constant and vector element + shr $0x2f,%rsi // shift right by 47 + imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 + sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above + ... + // repeats for each element with vpextract instructions + + This is tricky with AVX2 for a number of reasons: + 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there + 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate + back down to 32 bit precision later (there is in AVX512) + 3.) Full width integer multiplications aren't cheap + + We can, however, do a relatively cheap sequence for horizontal sums. + Then, we simply do the integer modulus on the resulting 64 bit GPR, on a scalar value. It was + previously thought that casting to 64 bit precision was needed prior to the horizontal sum, but + that is simply not the case, as NMAX is defined as the maximum number of scalar sums that can be + performed on the maximum possible inputs before overflow + */ + + + /* In AVX2-land, this trip through GPRs will probably be unavoidable, as there's no cheap and easy + * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). + * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly + * what the compiler is doing to avoid integer divisions. */ + adler0 = partial_hsum256(vs1) % BASE; + adler1 = hsum256(vs2) % BASE; + } + + adler = adler0 | (adler1 << 16); + + if (len) { + goto rem_peel; + } + + return adler; +} -#include "adler32_avx2_tpl.h" +Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) { + return adler32_fold_copy_impl(adler, NULL, src, len, 0); +} -#define COPY -#include "adler32_avx2_tpl.h" +Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + return adler32_fold_copy_impl(adler, dst, src, len, 1); +} #endif diff --git a/arch/x86/adler32_avx2_tpl.h b/arch/x86/adler32_avx2_tpl.h deleted file mode 100644 index 2104b053e5..0000000000 --- a/arch/x86/adler32_avx2_tpl.h +++ /dev/null @@ -1,141 +0,0 @@ -/* adler32_avx2_tpl.h -- adler32 avx2 vectorized function templates - * Copyright (C) 2022 Adam Stylinski - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zbuild.h" -#include -#include "../../adler32_fold.h" -#include "../../adler32_p.h" -#include "x86_intrins.h" -#include "adler32_avx2_p.h" - -#ifdef X86_SSE42 -extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); -extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len); - -#define copy_sub32(a, b, c, d) adler32_fold_copy_sse42(a, b, c, d) -#define sub32(a, b, c) adler32_ssse3(a, b, c) -#else -#define copy_sub32(a, b, c, d) adler32_copy_len_16(adler0, c, b, d, adler1) -#define sub32(a, b, c) adler32_len_16(adler0, b, c, adler1) -#endif - -#ifdef COPY -Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { -#else -Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) { -#endif - if (src == NULL) return 1L; - if (len == 0) return adler; - - uint32_t adler0, adler1; - adler1 = (adler >> 16) & 0xffff; - adler0 = adler & 0xffff; - -rem_peel: - if (len < 16) { -#ifdef COPY - return adler32_copy_len_16(adler0, src, dst, len, adler1); -#else - return adler32_len_16(adler0, src, len, adler1); -#endif - } else if (len < 32) { -#ifdef COPY - return copy_sub32(adler, dst, src, len); -#else - return sub32(adler, src, len); -#endif - } - - __m256i vs1, vs2; - - const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, - 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); - const __m256i dot3v = _mm256_set1_epi16(1); - const __m256i zero = _mm256_setzero_si256(); - - while (len >= 32) { - vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0)); - vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1)); - __m256i vs1_0 = vs1; - __m256i vs3 = _mm256_setzero_si256(); - - size_t k = MIN(len, NMAX); - k -= k % 32; - len -= k; - - while (k >= 32) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 32 vs1 + sum( (32-i+1) c[i] ) - */ - __m256i vbuf = _mm256_loadu_si256((__m256i*)src); - src += 32; - k -= 32; - - __m256i vs1_sad = _mm256_sad_epu8(vbuf, zero); // Sum of abs diff, resulting in 2 x int32's - // -#ifdef COPY - _mm256_storeu_si256((__m256i*)dst, vbuf); - dst += 32; -#endif - vs1 = _mm256_add_epi32(vs1, vs1_sad); - vs3 = _mm256_add_epi32(vs3, vs1_0); - __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); // sum 32 uint8s to 16 shorts - __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); // sum 16 shorts to 8 uint32s - vs2 = _mm256_add_epi32(vsum2, vs2); - vs1_0 = vs1; - } - - /* Defer the multiplication with 32 to outside of the loop */ - vs3 = _mm256_slli_epi32(vs3, 5); - vs2 = _mm256_add_epi32(vs2, vs3); - - /* The compiler is generating the following sequence for this integer modulus - * when done the scalar way, in GPRs: - - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + - (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); - - mov $0x80078071,%edi // move magic constant into 32 bit register %edi - ... - vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi - mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax - imul %rdi,%rsi // do a signed multiplication with magic constant and vector element - shr $0x2f,%rsi // shift right by 47 - imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 - sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above - ... - // repeats for each element with vpextract instructions - - This is tricky with AVX2 for a number of reasons: - 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there - 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate - back down to 32 bit precision later (there is in AVX512) - 3.) Full width integer multiplications aren't cheap - - We can, however, and do a relatively cheap sequence for horizontal sums. - Then, we simply do the integer modulus on the resulting 64 bit GPR, on a scalar value. It was - previously thought that casting to 64 bit precision was needed prior to the horizontal sum, but - that is simply not the case, as NMAX is defined as the maximum number of scalar sums that can be - performed on the maximum possible inputs before overflow - */ - - - /* In AVX2-land, this trip through GPRs will probably be unvoidable, as there's no cheap and easy - * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). - * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly - * what the compiler is doing to avoid integer divisions. */ - adler0 = partial_hsum256(vs1) % BASE; - adler1 = hsum256(vs2) % BASE; - } - - adler = adler0 | (adler1 << 16); - - if (len) { - goto rem_peel; - } - - return adler; -} From 5af152a6a377b45619c8860e2a25c68fa2199ed9 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 7 Nov 2023 15:22:55 -0500 Subject: [PATCH 768/798] Detemplatize adler32_fold_copy for avx512 Measurements show deltas basically in the noise floor for the benchmarks. The AVX512 VNNI implementation is a bit special in that it seems to be be hurt by the clock penalty enough versus a normal copy that a 256 bit wide variant was warranted. --- arch/x86/adler32_avx512.c | 105 ++++++++++++++++++++++++++++++++- arch/x86/adler32_avx512_tpl.h | 106 ---------------------------------- 2 files changed, 102 insertions(+), 109 deletions(-) delete mode 100644 arch/x86/adler32_avx512_tpl.h diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index e6ebb05dc8..aa6cc17018 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -8,9 +8,108 @@ #ifdef X86_AVX512 -#include "adler32_avx512_tpl.h" +#include "../../zbuild.h" +#include "../../adler32_p.h" +#include "../../adler32_fold.h" +#include "../../cpu_features.h" +#include +#include "x86_intrins.h" +#include "adler32_avx512_p.h" -#define COPY -#include "adler32_avx512_tpl.h" +static inline uint32_t adler32_fold_copy_impl(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len, const int COPY) { + if (src == NULL) return 1L; + if (len == 0) return adler; + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel: + if (len < 64) { + /* This handles the remaining copies, just call normal adler checksum after this */ + if (COPY) { + __mmask64 storemask = (0xFFFFFFFFFFFFFFFFUL >> (64 - len)); + __m512i copy_vec = _mm512_maskz_loadu_epi8(storemask, src); + _mm512_mask_storeu_epi8(dst, storemask, copy_vec); + } + +#ifdef X86_AVX2 + return adler32_avx2(adler, src, len); +#elif defined(X86_SSSE3) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); +#endif + } + + __m512i vbuf, vs1_0, vs3; + + const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + const __m512i dot3v = _mm512_set1_epi16(1); + const __m512i zero = _mm512_setzero_si512(); + size_t k; + + while (len >= 64) { + __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); + __m512i vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1)); + vs1_0 = vs1; + vs3 = _mm512_setzero_si512(); + + k = MIN(len, NMAX); + k -= k % 64; + len -= k; + + while (k >= 64) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + vbuf = _mm512_loadu_si512(src); + + if (COPY) { + _mm512_storeu_si512(dst, vbuf); + dst += 64; + } + + src += 64; + k -= 64; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf, zero); + __m512i v_short_sum2 = _mm512_maddubs_epi16(vbuf, dot2v); + vs1 = _mm512_add_epi32(vs1_sad, vs1); + vs3 = _mm512_add_epi32(vs3, vs1_0); + __m512i vsum2 = _mm512_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm512_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + vs3 = _mm512_slli_epi32(vs3, 6); + vs2 = _mm512_add_epi32(vs2, vs3); + + adler0 = partial_hsum(vs1) % BASE; + adler1 = _mm512_reduce_add_epu32(vs2) % BASE; + } + + adler = adler0 | (adler1 << 16); + + /* Process tail (len < 64). */ + if (len) { + goto rem_peel; + } + + return adler; +} + +Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + return adler32_fold_copy_impl(adler, dst, src, len, 1); +} + +Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t len) { + return adler32_fold_copy_impl(adler, NULL, src, len, 0); +} #endif + diff --git a/arch/x86/adler32_avx512_tpl.h b/arch/x86/adler32_avx512_tpl.h deleted file mode 100644 index d92ad7f665..0000000000 --- a/arch/x86/adler32_avx512_tpl.h +++ /dev/null @@ -1,106 +0,0 @@ -/* adler32_avx512_tpl.h -- adler32 avx512 vectorized function templates - * Copyright (C) 2022 Adam Stylinski - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zbuild.h" -#include "../../adler32_p.h" -#include "../../adler32_fold.h" -#include "../../cpu_features.h" -#include -#include "x86_intrins.h" -#include "adler32_avx512_p.h" - -#ifdef X86_AVX512 - -#ifdef COPY -Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { -#else -Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t len) { -#endif - - if (src == NULL) return 1L; - if (len == 0) return adler; - - uint32_t adler0, adler1; - adler1 = (adler >> 16) & 0xffff; - adler0 = adler & 0xffff; - -rem_peel: - if (len < 64) { - /* This handles the remaining copies, just call normal adler checksum after this */ -#ifdef COPY - __mmask64 storemask = (0xFFFFFFFFFFFFFFFFUL >> (64 - len)); - __m512i copy_vec = _mm512_maskz_loadu_epi8(storemask, src); - _mm512_mask_storeu_epi8(dst, storemask, copy_vec); -#endif - -#ifdef X86_AVX2 - return adler32_avx2(adler, src, len); -#elif defined(X86_SSSE3) - return adler32_ssse3(adler, src, len); -#else - return adler32_len_16(adler0, src, len, adler1); -#endif - } - - __m512i vbuf, vs1_0, vs3; - - const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64); - const __m512i dot3v = _mm512_set1_epi16(1); - const __m512i zero = _mm512_setzero_si512(); - size_t k; - - while (len >= 64) { - __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); - __m512i vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1)); - vs1_0 = vs1; - vs3 = _mm512_setzero_si512(); - - k = MIN(len, NMAX); - k -= k % 64; - len -= k; - - while (k >= 64) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) - */ - vbuf = _mm512_loadu_si512(src); -#ifdef COPY - _mm512_storeu_si512(dst, vbuf); - dst += 64; -#endif - src += 64; - k -= 64; - - __m512i vs1_sad = _mm512_sad_epu8(vbuf, zero); - __m512i v_short_sum2 = _mm512_maddubs_epi16(vbuf, dot2v); - vs1 = _mm512_add_epi32(vs1_sad, vs1); - vs3 = _mm512_add_epi32(vs3, vs1_0); - __m512i vsum2 = _mm512_madd_epi16(v_short_sum2, dot3v); - vs2 = _mm512_add_epi32(vsum2, vs2); - vs1_0 = vs1; - } - - vs3 = _mm512_slli_epi32(vs3, 6); - vs2 = _mm512_add_epi32(vs2, vs3); - - adler0 = partial_hsum(vs1) % BASE; - adler1 = _mm512_reduce_add_epu32(vs2) % BASE; - } - - adler = adler0 | (adler1 << 16); - - /* Process tail (len < 64). */ - if (len) { - goto rem_peel; - } - - return adler; -} - -#endif From ec7ffb3d9a811953164773efb77a807ccc5e2cdf Mon Sep 17 00:00:00 2001 From: Uilian Ries Date: Fri, 15 Dec 2023 14:25:30 +0100 Subject: [PATCH 769/798] Export cmake target (#1601) * Export cmake target * Mimic zlib target name --------- Signed-off-by: Uilian Ries --- CMakeLists.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index fbc2bdbafb..41f8dd0fb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,9 +152,11 @@ if(ZLIB_COMPAT) set(WITH_GZFILEOP ON) set(SUFFIX "") set(ZLIB_FULL_VERSION ${ZLIB_HEADER_VERSION}.zlib-ng) + set(EXPORT_NAME ZLIB) else() set(SUFFIX "-ng") set(ZLIB_FULL_VERSION ${ZLIBNG_HEADER_VERSION}) + set(EXPORT_NAME zlib-ng) endif() if(WITH_GZFILEOP) @@ -1199,6 +1201,22 @@ if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) endif() if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL) install(FILES ${ZLIB_PC} DESTINATION "${PKGCONFIG_INSTALL_DIR}") + # INFO: Mimics official zlib CMake target + # Generates ZLIB.cmake in case ZLIB_COMPAT=ON and always exports the CMake target ZLIB::ZLIB + # In case ZLIB_COMPAT=OFF, the CMake target and file follows zlib-ng naming convention + if (ZLIB_COMPAT) + if (TARGET zlib) + set_target_properties(zlib PROPERTIES EXPORT_NAME ZLIB) + else() + set_target_properties(zlibstatic PROPERTIES EXPORT_NAME ZLIB) + endif() + endif() + install(TARGETS ${ZLIB_INSTALL_LIBRARIES} + EXPORT ${EXPORT_NAME} + DESTINATION "${CMAKE_INSTALL_LIBDIR}") + install(EXPORT ${EXPORT_NAME} + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${EXPORT_NAME}" + NAMESPACE ${EXPORT_NAME}::) endif() #============================================================================ From 2baed9faa9437fcd1d0a106da87a540073ad851f Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 15 Dec 2023 14:23:52 +0100 Subject: [PATCH 770/798] Fix pkgcheck mismatch with configure due to cmake target files. --- test/pkgcheck.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/pkgcheck.sh b/test/pkgcheck.sh index 94a67a191e..942140179e 100644 --- a/test/pkgcheck.sh +++ b/test/pkgcheck.sh @@ -150,6 +150,9 @@ Darwin) ;; esac +# Remove cmake target files to avoid mismatch with configure +find pkgtmp2 -type f -name '*.cmake' -exec rm '{}' \; + # The ar on newer systems defaults to -D (i.e. deterministic), # but FreeBSD 12.1, Debian 8, and Ubuntu 14.04 seem to not do that. # I had trouble passing -D safely to the ar inside CMakeLists.txt, From fb753015a5d5e48853a6e5ad9d6140c5ee246c3a Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Thu, 14 Dec 2023 15:27:08 +0800 Subject: [PATCH 771/798] Remove duplicate enable tests option There are two identical ZLIB_ENABLE_TESTS option in CMakeLists.txt which means the latter one is meaningless. This issue is introduced in https://github.com/zlib-ng/zlib-ng/commit/ce1a64b5147b874a2dd32920765be333f54e7095 which adds the option to top but forgets to remove the original one. --- CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 41f8dd0fb7..4f5b6cf517 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1223,7 +1223,6 @@ endif() # Example binaries #============================================================================ -option(ZLIB_ENABLE_TESTS "Build test binaries" ON) if(ZLIB_ENABLE_TESTS) enable_testing() From 6e4b8b194b409bc776abbbfc819ce7b5980956fb Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Mon, 18 Dec 2023 21:53:21 +0800 Subject: [PATCH 772/798] Update copyright to sync with zlib 1.3 https://github.com/zlib-ng/zlib-ng/pull/1563 this patch forgets to update copyright string. --- deflate.c | 4 ++-- inftrees.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/deflate.c b/deflate.c index 978a389b97..735014516b 100644 --- a/deflate.c +++ b/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2023 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -58,7 +58,7 @@ # undef deflateInit2 #endif -const char PREFIX(deflate_copyright)[] = " deflate 1.2.13 Copyright 1995-2022 Jean-loup Gailly and Mark Adler "; +const char PREFIX(deflate_copyright)[] = " deflate 1.3.0 Copyright 1995-2023 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot diff --git a/inftrees.c b/inftrees.c index f04d65f865..423f7b461d 100644 --- a/inftrees.c +++ b/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2022 Mark Adler + * Copyright (C) 1995-2023 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -7,7 +7,7 @@ #include "zutil.h" #include "inftrees.h" -const char PREFIX(inflate_copyright)[] = " inflate 1.2.13 Copyright 1995-2022 Mark Adler "; +const char PREFIX(inflate_copyright)[] = " inflate 1.3.0 Copyright 1995-2023 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot From a6127381acc568de1b1f7a3e33290be2a82fa7f5 Mon Sep 17 00:00:00 2001 From: Letu Ren Date: Mon, 18 Dec 2023 00:58:38 +0800 Subject: [PATCH 773/798] Only read version information from zlib.h.in This is a patch for https://github.com/zlib-ng/zlib-ng/commit/cd458c79c7923e76ffdd0e2638bf2a0eed4f3996 As the commit message says: "Add code to extract version information for both ZLIB and ZLIBNG variants from the zlib.h file." The logic of ${SUFFIX} is that zlib-ng reads version information after parse ZLIB_COMPAT before the commit mentioned above. ${SUFFIX} will only be set by ZLIB_COMPAT and is meaningless before ZLIB_COMPAT. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f5b6cf517..9170ed5871 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,8 +23,8 @@ if(NOT CMAKE_C_STANDARD IN_LIST VALID_C_STANDARDS) MESSAGE(FATAL_ERROR "CMAKE_C_STANDARD:STRING=${CMAKE_C_STANDARD} not in known standards list\n ${VALID_C_STANDARDS}") endif() -# Parse the full version number from zlib.h and include in ZLIB_FULL_VERSION -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h.in _zlib_h_contents) +# Parse the full version number from zlib.h.in and include in ZLIB_FULL_VERSION +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h.in _zlib_h_contents) string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9]+.[0-9]+.[0-9]+).*\".*" "\\1" ZLIB_HEADER_VERSION ${_zlib_h_contents}) string(REGEX REPLACE ".*#define[ \t]+ZLIBNG_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" From dd8dc56e6196c01ad3c80493ef93396479871c1e Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 16 Dec 2023 14:10:11 +0500 Subject: [PATCH 774/798] Fix buffer overflow in compare256_rle benchmark Signed-off-by: Vladislav Shchapov --- test/benchmarks/benchmark_compare256_rle.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/benchmark_compare256_rle.cc b/test/benchmarks/benchmark_compare256_rle.cc index 5a8afd6943..c96d185810 100644 --- a/test/benchmarks/benchmark_compare256_rle.cc +++ b/test/benchmarks/benchmark_compare256_rle.cc @@ -33,7 +33,7 @@ class compare256_rle: public benchmark::Fixture { } void Bench(benchmark::State& state, compare256_rle_func compare256_rle) { - int32_t match_len = (int32_t)state.range(0); + int32_t match_len = (int32_t)state.range(0) - 1; uint32_t len; str2[match_len] = 0; From 0c32ad42372aabf19206068fd00e1fbd6e089bc2 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sat, 16 Dec 2023 18:00:45 +0500 Subject: [PATCH 775/798] Add force initialization functable, because deflate captures function pointers from functable Signed-off-by: Vladislav Shchapov --- deflate.c | 3 +++ functable.c | 11 +++++++++++ functable.h | 1 + 3 files changed, 15 insertions(+) diff --git a/deflate.c b/deflate.c index 735014516b..2a0a20e5d2 100644 --- a/deflate.c +++ b/deflate.c @@ -194,6 +194,9 @@ int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level deflate_state *s; int wrap = 1; + /* Force initialization functable, because deflate captures function pointers from functable. */ + functable.force_init(); + if (strm == NULL) return Z_STREAM_ERROR; diff --git a/functable.c b/functable.c index f664d280d8..99fe735e27 100644 --- a/functable.c +++ b/functable.c @@ -11,6 +11,10 @@ #include "functable.h" #include "cpu_features.h" +static void force_init_empty(void) { + // empty +} + static void init_functable(void) { struct functable_s ft; struct cpu_features cf; @@ -18,6 +22,7 @@ static void init_functable(void) { cpu_check_features(&cf); // Generic code + ft.force_init = &force_init_empty; ft.adler32 = &adler32_c; ft.adler32_fold_copy = &adler32_fold_copy_c; ft.chunkmemset_safe = &chunkmemset_safe_c; @@ -234,6 +239,7 @@ static void init_functable(void) { #endif // Assign function pointers individually for atomic operation + functable.force_init = ft.force_init; functable.adler32 = ft.adler32; functable.adler32_fold_copy = ft.adler32_fold_copy; functable.chunkmemset_safe = ft.chunkmemset_safe; @@ -254,6 +260,10 @@ static void init_functable(void) { } /* stub functions */ +static void force_init_stub(void) { + init_functable(); +} + static uint32_t adler32_stub(uint32_t adler, const uint8_t* buf, size_t len) { init_functable(); return functable.adler32(adler, buf, len); @@ -341,6 +351,7 @@ static uint32_t update_hash_stub(deflate_state* const s, uint32_t h, uint32_t va /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { + force_init_stub, adler32_stub, adler32_fold_copy_stub, chunkmemset_safe_stub, diff --git a/functable.h b/functable.h index 1cdfd4df41..b1742bade0 100644 --- a/functable.h +++ b/functable.h @@ -17,6 +17,7 @@ typedef struct zng_stream_s zng_stream; #endif struct functable_s { + void (* force_init) (void); uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, size_t len); uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); From ba4a78133ebad45c3d825865d38e0be73bf991de Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Sun, 17 Dec 2023 17:14:17 +0500 Subject: [PATCH 776/798] Initialize functable earlier, during inflateInit Signed-off-by: Vladislav Shchapov --- inflate.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/inflate.c b/inflate.c index 0c9d499f63..af5abf11a5 100644 --- a/inflate.c +++ b/inflate.c @@ -139,6 +139,9 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateInit2)(PREFIX3(stream) *strm, int32_t windo int32_t ret; struct inflate_state *state; + /* Initialize functable earlier. */ + functable.force_init(); + if (strm == NULL) return Z_STREAM_ERROR; strm->msg = NULL; /* in case we return an error */ From a0356faa44eac4dee2b33c9e4674e5d919285b8d Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Wed, 11 Jan 2023 14:52:15 +0000 Subject: [PATCH 777/798] Improve performance of crc32_acle on 32-bit ARM --- arch/arm/crc32_acle.c | 70 +++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 43 deletions(-) diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index 0c9b9b6596..978d97d720 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -17,34 +17,40 @@ Z_INTERNAL uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { Z_REGISTER uint32_t c; Z_REGISTER const uint16_t *buf2; Z_REGISTER const uint32_t *buf4; + Z_REGISTER const uint64_t *buf8; c = ~crc; - if (len && ((ptrdiff_t)buf & 1)) { - c = __crc32b(c, *buf++); - len--; - } - - if ((len >= sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) { - buf2 = (const uint16_t *) buf; - c = __crc32h(c, *buf2++); - len -= sizeof(uint16_t); - buf4 = (const uint32_t *) buf2; - } else { - buf4 = (const uint32_t *) buf; - } -#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) - if ((len >= sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { - c = __crc32w(c, *buf4++); - len -= sizeof(uint32_t); - } - - if (len == 0) { + if (UNLIKELY(len == 1)) { + c = __crc32b(c, *buf); c = ~c; return c; } - const uint64_t *buf8 = (const uint64_t *) buf4; + if ((ptrdiff_t)buf & (sizeof(uint64_t) - 1)) { + if (len && ((ptrdiff_t)buf & 1)) { + c = __crc32b(c, *buf++); + len--; + } + + if ((len >= sizeof(uint16_t)) && ((ptrdiff_t)buf & sizeof(uint16_t))) { + buf2 = (const uint16_t *) buf; + c = __crc32h(c, *buf2++); + len -= sizeof(uint16_t); + buf4 = (const uint32_t *) buf2; + } else { + buf4 = (const uint32_t *) buf; + } + + if ((len >= sizeof(uint32_t)) && ((ptrdiff_t)buf & sizeof(uint32_t))) { + c = __crc32w(c, *buf4++); + len -= sizeof(uint32_t); + } + + buf8 = (const uint64_t *) buf4; + } else { + buf8 = (const uint64_t *) buf; + } while (len >= sizeof(uint64_t)) { c = __crc32d(c, *buf8++); @@ -66,28 +72,6 @@ Z_INTERNAL uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { } buf = (const unsigned char *) buf2; -#else /* __aarch64__ */ - - if (len == 0) { - c = ~c; - return c; - } - - while (len >= sizeof(uint32_t)) { - c = __crc32w(c, *buf4++); - len -= sizeof(uint32_t); - } - - if (len >= sizeof(uint16_t)) { - buf2 = (const uint16_t *) buf4; - c = __crc32h(c, *buf2++); - len -= sizeof(uint16_t); - buf = (const unsigned char *) buf2; - } else { - buf = (const unsigned char *) buf4; - } -#endif /* __aarch64__ */ - if (len) { c = __crc32b(c, *buf); } From 0756ec4643f6d540df05dd44e4ede676f3fad259 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 21 Dec 2023 10:19:54 +0200 Subject: [PATCH 778/798] Check if compiler supports -march=native or -mcpu=native. --- CMakeLists.txt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9170ed5871..b7d15699ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -252,11 +252,18 @@ endif() # Set native march/mcpu if(WITH_NATIVE_INSTRUCTIONS) if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") - if(BASEARCH_PPC_FOUND) - set(NATIVEFLAG "-mcpu=native") - else() + check_c_compiler_flag(-march=native HAVE_MARCH_NATIVE) + if(HAVE_MARCH_NATIVE) set(NATIVEFLAG "-march=native") + else() + check_c_compiler_flag(-mcpu=native HAVE_MCPU_NATIVE) + if(HAVE_MCPU_NATIVE) + set(NATIVEFLAG "-mcpu=native") + endif() endif() + # Fall through + endif() + if(NATIVEFLAG) # Apply flag to all source files and compilation checks add_compile_options(${NATIVEFLAG}) else() From 0b080ede775485156f9db024430496fa34170ae5 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 23 Dec 2023 19:00:46 +0100 Subject: [PATCH 779/798] Always run CMake tests without LTO. --- CMakeLists.txt | 18 ++++++++++------ cmake/detect-intrinsics.cmake | 40 +++++++++++++++++------------------ 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7d15699ce..0cbc69a62d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,6 +197,15 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") set(WARNFLAGS -Wall) set(WARNFLAGS_MAINTAINER -Wextra) set(WARNFLAGS_DISABLE) + # Check whether -fno-lto is available + set(CMAKE_REQUIRED_FLAGS "-fno-lto") + check_c_source_compiles( + "int main() { return 0; }" + FNO_LTO_AVAILABLE FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) + if(FNO_LTO_AVAILABLE) + set(ZNOLTOFLAG "-fno-lto") + endif() if(NOT WITH_NATIVE_INSTRUCTIONS) if(BASEARCH_ARM_FOUND) if("${ARCH}" MATCHES "arm" AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") @@ -230,14 +239,9 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") endif() endif() endif() - # Check whether -fno-lto is available - set(CMAKE_REQUIRED_FLAGS "-fno-lto") - check_c_source_compiles( - "int main() { return 0; }" - FNO_LTO_AVAILABLE FAIL_REGEX "not supported") - set(CMAKE_REQUIRED_FLAGS) + # Disable LTO unless Native Instructions are enabled if(FNO_LTO_AVAILABLE) - set(NOLTOFLAG "-fno-lto") + set(NOLTOFLAG ${ZNOLTOFLAG}) endif() endif() if(MINGW) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index fb7c735b76..cb3d9defde 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -15,7 +15,7 @@ macro(check_acle_compiler_flag) endif() endif() # Check whether compiler supports ACLE flag - set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "int main() { return 0; }" HAVE_ACLE_FLAG FAIL_REGEX "not supported") @@ -43,7 +43,7 @@ macro(check_armv6_compiler_flag) endif() endif() # Check whether compiler supports ARMv6 inline asm - set(CMAKE_REQUIRED_FLAGS "${ARMV6FLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${ARMV6FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "unsigned int f(unsigned int a, unsigned int b) { unsigned int c; @@ -99,7 +99,7 @@ macro(check_avx512_intrinsics) set(AVX512FLAG "/arch:AVX512") endif() # Check whether compiler supports AVX512 intrinsics - set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include __m512i f(__m512i y) { @@ -145,7 +145,7 @@ macro(check_avx512vnni_intrinsics) endif() # Check whether compiler supports AVX512vnni intrinsics - set(CMAKE_REQUIRED_FLAGS "${AVX512VNNIFLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${AVX512VNNIFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include __m512i f(__m512i x, __m512i y) { @@ -173,7 +173,7 @@ macro(check_avx2_intrinsics) set(AVX2FLAG "/arch:AVX2") endif() # Check whether compiler supports AVX2 intrinics - set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include __m256i f(__m256i x) { @@ -197,7 +197,7 @@ macro(check_neon_compiler_flag) endif() endif() # Check whether compiler supports NEON flag - set(CMAKE_REQUIRED_FLAGS "${NEONFLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${NEONFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#if defined(_M_ARM64) || defined(_M_ARM64EC) # include @@ -220,7 +220,7 @@ macro(check_neon_ld4_intrinsics) endif() endif() # Check whether compiler supports loading 4 neon vecs into a register range - set(CMAKE_REQUIRED_FLAGS "${NEONFLAG}") + set(CMAKE_REQUIRED_FLAGS "${NEONFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC)) # include @@ -242,7 +242,7 @@ macro(check_pclmulqdq_intrinsics) # Check whether compiler supports PCLMULQDQ intrinsics if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) # The pclmul code currently crashes on Mac in 32bit mode. Avoid for now. - set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include #include @@ -264,7 +264,7 @@ macro(check_vpclmulqdq_intrinsics) endif() # Check whether compiler supports VPCLMULQDQ intrinsics if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) - set(CMAKE_REQUIRED_FLAGS "${VPCLMULFLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${VPCLMULFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include #include @@ -283,7 +283,7 @@ endmacro() macro(check_ppc_intrinsics) # Check if compiler supports AltiVec - set(CMAKE_REQUIRED_FLAGS "-maltivec") + set(CMAKE_REQUIRED_FLAGS "-maltivec ${ZNOLTOFLAG}") check_c_source_compiles( "#include int main(void) @@ -301,7 +301,7 @@ macro(check_ppc_intrinsics) set(PPCFLAGS "-maltivec") endif() - set(CMAKE_REQUIRED_FLAGS "-maltivec -mno-vsx") + set(CMAKE_REQUIRED_FLAGS "-maltivec -mno-vsx ${ZNOLTOFLAG}") check_c_source_compiles( "#include int main(void) @@ -320,7 +320,7 @@ macro(check_ppc_intrinsics) endif() # Check if we have what we need for AltiVec optimizations - set(CMAKE_REQUIRED_FLAGS "${PPCFLAGS} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${PPCFLAGS} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include #ifdef __FreeBSD__ @@ -347,7 +347,7 @@ macro(check_power8_intrinsics) endif() endif() # Check if we have what we need for POWER8 optimizations - set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include #ifdef __FreeBSD__ @@ -374,7 +374,7 @@ macro(check_rvv_intrinsics) endif() endif() # Check whether compiler supports RVV - set(CMAKE_REQUIRED_FLAGS "${RISCVFLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${RISCVFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include int main() { @@ -405,7 +405,7 @@ macro(check_power9_intrinsics) endif() endif() # Check if we have what we need for POWER9 optimizations - set(CMAKE_REQUIRED_FLAGS "${POWER9FLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${POWER9FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include #ifdef __FreeBSD__ @@ -442,7 +442,7 @@ macro(check_sse2_intrinsics) endif() endif() # Check whether compiler supports SSE2 intrinsics - set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include __m128i f(__m128i x, __m128i y) { return _mm_sad_epu8(x, y); } @@ -465,7 +465,7 @@ macro(check_ssse3_intrinsics) endif() endif() # Check whether compiler supports SSSE3 intrinsics - set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include __m128i f(__m128i u) { @@ -490,7 +490,7 @@ macro(check_sse42_intrinsics) endif() endif() # Check whether compiler supports SSE4.2 intrinsics - set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include unsigned int f(unsigned int a, unsigned int b) { return _mm_crc32_u32(a, b); } @@ -511,7 +511,7 @@ macro(check_vgfma_intrinsics) endif() endif() # Check whether compiler supports "VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE" intrinsic - set(CMAKE_REQUIRED_FLAGS "${VGFMAFLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${VGFMAFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#include int main(void) { @@ -529,7 +529,7 @@ macro(check_xsave_intrinsics) if(NOT NATIVEFLAG AND NOT MSVC) set(XSAVEFLAG "-mxsave") endif() - set(CMAKE_REQUIRED_FLAGS "${XSAVEFLAG} ${NATIVEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${XSAVEFLAG} ${NATIVEFLAG} ${ZNOLTOFLAG}") check_c_source_compiles( "#ifdef _MSC_VER # include From 4ece1a480cbd3601f273b3f81578478e611c62b9 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 22 Dec 2023 16:59:03 +0200 Subject: [PATCH 780/798] Add support for __attribute__((__target__(...))) to overcome limitations of -march=native. --- arch/arm/acle_intrins.h | 8 ++++++++ arch/arm/crc32_acle.c | 8 ++------ arch/arm/insert_string_acle.c | 10 ++++------ zbuild.h | 8 ++++++++ 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/arch/arm/acle_intrins.h b/arch/arm/acle_intrins.h index e9eef12dfb..531b8a7f66 100644 --- a/arch/arm/acle_intrins.h +++ b/arch/arm/acle_intrins.h @@ -8,6 +8,14 @@ # include #endif +#ifdef ARM_ACLE +#if defined(__aarch64__) +# define Z_TARGET_CRC Z_TARGET("+crc") +#else +# define Z_TARGET_CRC +#endif +#endif + #ifdef ARM_SIMD #ifdef _MSC_VER typedef uint32_t uint16x2_t; diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index 978d97d720..ac7d6ff66b 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -6,14 +6,10 @@ */ #ifdef ARM_ACLE -#ifdef _MSC_VER -# include -#else -# include -#endif +#include "acle_intrins.h" #include "../../zbuild.h" -Z_INTERNAL uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { +Z_INTERNAL Z_TARGET_CRC uint32_t crc32_acle(uint32_t crc, const uint8_t *buf, size_t len) { Z_REGISTER uint32_t c; Z_REGISTER const uint16_t *buf2; Z_REGISTER const uint32_t *buf4; diff --git a/arch/arm/insert_string_acle.c b/arch/arm/insert_string_acle.c index 9ac3ccb42f..aa8385c712 100644 --- a/arch/arm/insert_string_acle.c +++ b/arch/arm/insert_string_acle.c @@ -6,9 +6,7 @@ */ #ifdef ARM_ACLE -#ifndef _MSC_VER -# include -#endif +#include "acle_intrins.h" #include "../../zbuild.h" #include "../../deflate.h" @@ -18,9 +16,9 @@ #define HASH_CALC_VAR h #define HASH_CALC_VAR_INIT uint32_t h = 0 -#define UPDATE_HASH update_hash_acle -#define INSERT_STRING insert_string_acle -#define QUICK_INSERT_STRING quick_insert_string_acle +#define UPDATE_HASH Z_TARGET_CRC update_hash_acle +#define INSERT_STRING Z_TARGET_CRC insert_string_acle +#define QUICK_INSERT_STRING Z_TARGET_CRC quick_insert_string_acle #include "../../insert_string_tpl.h" #endif diff --git a/zbuild.h b/zbuild.h index bb964d6c0a..d78c3a15a2 100644 --- a/zbuild.h +++ b/zbuild.h @@ -61,6 +61,14 @@ # endif #endif +#ifndef Z_TARGET +# if Z_HAS_ATTRIBUTE(__target__) +# define Z_TARGET(x) __attribute__((__target__(x))) +# else +# define Z_TARGET(x) +# endif +#endif + /* This has to be first include that defines any types */ #if defined(_MSC_VER) # if defined(_WIN64) From b7fc54ef876f202ec7d4a4c61df88bcbd65e0fc6 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 22 Dec 2023 13:24:54 +0200 Subject: [PATCH 781/798] Make sure uqsub16 mnemonic doesn't get optimized away. --- cmake/detect-intrinsics.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index cb3d9defde..74ac3910b8 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -50,7 +50,7 @@ macro(check_armv6_compiler_flag) __asm__ __volatile__ ( \"uqsub16 %0, %1, %2\" : \"=r\" (c) : \"r\" (a), \"r\" (b) ); return (int)c; } - int main(void) { return 0; }" + int main(void) { return f(1,2); }" HAVE_ARMV6_INLINE_ASM ) # Check whether compiler supports ARMv6 intrinsics From 9d486b5073917eccc1bf4e59007421928cc42acf Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 21 Dec 2023 21:19:05 +0500 Subject: [PATCH 782/798] Atomic functable Signed-off-by: Vladislav Shchapov --- functable.c | 69 ++++++++++++++++++++++++++++++++++++++--------------- functable.h | 2 +- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/functable.c b/functable.c index 99fe735e27..37c4aeef7d 100644 --- a/functable.c +++ b/functable.c @@ -11,6 +11,34 @@ #include "functable.h" #include "cpu_features.h" +#if defined(_MSC_VER) +# include +#endif + +/* Platform has pointer size atomic store */ +#if defined(__GNUC__) || defined(__clang__) +# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ + __atomic_store(&(functable.FUNC_NAME), &(VAR.FUNC_NAME), __ATOMIC_SEQ_CST) +# define FUNCTABLE_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST) +#elif defined(_MSC_VER) +# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ + _InterlockedExchangePointer((void * volatile *)&(functable.FUNC_NAME), (void *)(VAR.FUNC_NAME)) +# if defined(_M_ARM) || defined(_M_ARM64) +# define FUNCTABLE_BARRIER() do { \ + _ReadWriteBarrier(); \ + __dmb(0xB); /* _ARM_BARRIER_ISH */ \ + _ReadWriteBarrier(); \ +} while (0) +# else +# define FUNCTABLE_BARRIER() _ReadWriteBarrier() +# endif +#else +# warning Unable to detect atomic intrinsic support. +# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ + *((void * volatile *)&(functable.FUNC_NAME)) = (void *)(VAR.FUNC_NAME) +# define FUNCTABLE_BARRIER() do { /* Empty */ } while (0) +#endif + static void force_init_empty(void) { // empty } @@ -239,24 +267,27 @@ static void init_functable(void) { #endif // Assign function pointers individually for atomic operation - functable.force_init = ft.force_init; - functable.adler32 = ft.adler32; - functable.adler32_fold_copy = ft.adler32_fold_copy; - functable.chunkmemset_safe = ft.chunkmemset_safe; - functable.chunksize = ft.chunksize; - functable.compare256 = ft.compare256; - functable.crc32 = ft.crc32; - functable.crc32_fold = ft.crc32_fold; - functable.crc32_fold_copy = ft.crc32_fold_copy; - functable.crc32_fold_final = ft.crc32_fold_final; - functable.crc32_fold_reset = ft.crc32_fold_reset; - functable.inflate_fast = ft.inflate_fast; - functable.insert_string = ft.insert_string; - functable.longest_match = ft.longest_match; - functable.longest_match_slow = ft.longest_match_slow; - functable.quick_insert_string = ft.quick_insert_string; - functable.slide_hash = ft.slide_hash; - functable.update_hash = ft.update_hash; + FUNCTABLE_ASSIGN(ft, force_init); + FUNCTABLE_ASSIGN(ft, adler32); + FUNCTABLE_ASSIGN(ft, adler32_fold_copy); + FUNCTABLE_ASSIGN(ft, chunkmemset_safe); + FUNCTABLE_ASSIGN(ft, chunksize); + FUNCTABLE_ASSIGN(ft, compare256); + FUNCTABLE_ASSIGN(ft, crc32); + FUNCTABLE_ASSIGN(ft, crc32_fold); + FUNCTABLE_ASSIGN(ft, crc32_fold_copy); + FUNCTABLE_ASSIGN(ft, crc32_fold_final); + FUNCTABLE_ASSIGN(ft, crc32_fold_reset); + FUNCTABLE_ASSIGN(ft, inflate_fast); + FUNCTABLE_ASSIGN(ft, insert_string); + FUNCTABLE_ASSIGN(ft, longest_match); + FUNCTABLE_ASSIGN(ft, longest_match_slow); + FUNCTABLE_ASSIGN(ft, quick_insert_string); + FUNCTABLE_ASSIGN(ft, slide_hash); + FUNCTABLE_ASSIGN(ft, update_hash); + + // Memory barrier for weak memory order CPUs + FUNCTABLE_BARRIER(); } /* stub functions */ @@ -350,7 +381,7 @@ static uint32_t update_hash_stub(deflate_state* const s, uint32_t h, uint32_t va } /* functable init */ -Z_INTERNAL Z_TLS struct functable_s functable = { +Z_INTERNAL struct functable_s functable = { force_init_stub, adler32_stub, adler32_fold_copy_stub, diff --git a/functable.h b/functable.h index b1742bade0..9f78188e10 100644 --- a/functable.h +++ b/functable.h @@ -37,6 +37,6 @@ struct functable_s { uint32_t (* update_hash) (deflate_state *const s, uint32_t h, uint32_t val); }; -Z_INTERNAL extern Z_TLS struct functable_s functable; +Z_INTERNAL extern struct functable_s functable; #endif From dfced56c57e34e0109fb8614430ed77504490ddd Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 21 Dec 2023 21:19:34 +0500 Subject: [PATCH 783/798] Remove unused Z_TLS and HAVE_THREAD_LOCAL Signed-off-by: Vladislav Shchapov --- CMakeLists.txt | 15 --------------- configure | 16 ---------------- zbuild.h | 14 -------------- 3 files changed, 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0cbc69a62d..58ed3a1a55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -427,21 +427,6 @@ if(HAVE_ATTRIBUTE_ALIGNED) add_definitions(-DHAVE_ATTRIBUTE_ALIGNED) endif() -# -# check for _Thread_local() support in the compiler -# -check_c_source_compiles( - "_Thread_local int test; - int main(void) { - (void)test; - return 0; - }" - HAVE_THREAD_LOCAL -) -if(HAVE_THREAD_LOCAL) - add_definitions(-DHAVE_THREAD_LOCAL) -endif() - # # check for __builtin_ctz() support in the compiler # diff --git a/configure b/configure index 501f51badd..e0187be092 100755 --- a/configure +++ b/configure @@ -973,22 +973,6 @@ else echo "Checking for attribute(aligned) ... No." | tee -a configure.log fi -# Check for _Thread_local support in compiler -cat > $test.c << EOF -_Thread_local int test; -int main(void) { - (void)test; - return 0; -} -EOF -if try ${CC} ${CFLAGS} $test.c $LDSHAREDLIBC; then - echo "Checking for _Thread_local ... Yes." | tee -a configure.log - CFLAGS="$CFLAGS -DHAVE_THREAD_LOCAL" - SFLAGS="$SFLAGS -DHAVE_THREAD_LOCAL" -else - echo "Checking for _Thread_local ... No." | tee -a configure.log -fi - # Check for __builtin_ctz() support in compiler cat > $test.c << EOF long f(unsigned int x) { return __builtin_ctz(x); } diff --git a/zbuild.h b/zbuild.h index d78c3a15a2..d550b4c582 100644 --- a/zbuild.h +++ b/zbuild.h @@ -31,20 +31,6 @@ # endif #endif -/* Determine compiler support for TLS */ -#ifndef Z_TLS -# ifdef HAVE_THREAD_LOCAL -# define Z_TLS _Thread_local -# elif defined(__GNUC__) || defined(__SUNPRO_C) -# define Z_TLS __thread -# elif defined(_WIN32) && (defined(_MSC_VER) || defined(__ICL)) -# define Z_TLS __declspec(thread) -# else -# warning Unable to detect Thread Local Storage support. -# define Z_TLS -# endif -#endif - #ifndef Z_HAS_ATTRIBUTE # if defined(__has_attribute) # define Z_HAS_ATTRIBUTE(a) __has_attribute(a) From 2f1747a5d187a6ad80146867446ff69e52e8d49c Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 23 Dec 2023 20:00:48 +0100 Subject: [PATCH 784/798] Update to GoogleTest 1.12.1. This requires minimum CMake 3.5 and C++11, this matches nicely with zlib-ng 2.1.x requirements. --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a7919a9628..2a673748bf 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -143,7 +143,7 @@ if(WITH_GTEST) if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3) set(GTEST_TAG release-1.10.0) else() - set(GTEST_TAG release-1.11.0) + set(GTEST_TAG release-1.12.1) endif() endif() From 8fbff4b26d4ecc43e565603b6b585cb9fa4ff6c8 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 23 Dec 2023 20:08:17 +0100 Subject: [PATCH 785/798] Add status output when running git checkout of GoogleTest --- test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2a673748bf..23014ef296 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -148,6 +148,7 @@ if(WITH_GTEST) endif() # Fetch Google test source code from official repository + message(STATUS "Git checking out GoogleTest ${GTEST_TAG}") FetchContent_Declare(googletest GIT_REPOSITORY ${GTEST_REPOSITORY} GIT_TAG ${GTEST_TAG}) From 4799b1ad727c6b550484792982842753c8260013 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sat, 23 Dec 2023 20:12:13 +0100 Subject: [PATCH 786/798] Don't incorrectly disable GoogleTest because of old CMake version. --- test/CMakeLists.txt | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 23014ef296..43b4c9a7fb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -94,16 +94,11 @@ endif() if(WITH_GTEST OR WITH_BENCHMARKS) if(CMAKE_VERSION VERSION_LESS 3.12) - message(WARNING "Minimum cmake version of 3.12 not met for GoogleTest or benchmarks!") - - set(WITH_GTEST OFF) - set(WITH_GTEST OFF PARENT_SCOPE) - + message(WARNING "Minimum cmake version of 3.12 not met for Google benchmark!") set(WITH_BENCHMARKS OFF) set(WITH_BENCHMARKS OFF PARENT_SCOPE) - else() - enable_language(CXX) endif() + enable_language(CXX) endif() if(WITH_BENCHMARKS) @@ -127,7 +122,7 @@ if(WITH_GTEST) find_package(GTest) endif() - if(NOT TARGET GTest::GTest) + if(NOT TARGET GTest::GTest AND NOT CMAKE_VERSION VERSION_LESS 3.11) include(FetchContent) # Prevent overriding the parent project's compiler/linker settings for Windows From 0993a7e96c0c0b90d8674254eb9914ae37833666 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 21 Dec 2023 01:11:40 +0100 Subject: [PATCH 787/798] Don't attempt ARMv6 detection on AARCH64. --- CMakeLists.txt | 2 +- configure | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58ed3a1a55..8bcfaf7ea2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,7 +102,7 @@ set_property(CACHE WITH_SANITIZER PROPERTY STRINGS "Memory" "Address" "Undefined if(BASEARCH_ARM_FOUND) option(WITH_ACLE "Build with ACLE" ON) option(WITH_NEON "Build with NEON intrinsics" ON) - option(WITH_ARMV6 "Build with ARMv6 SIMD" ON) + cmake_dependent_option(WITH_ARMV6 "Build with ARMv6 SIMD" ON "NOT ARCH STREQUAL \"aarch64\"" OFF) elseif(BASEARCH_PPC_FOUND) option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON) option(WITH_POWER8 "Build with optimisations for POWER8" ON) diff --git a/configure b/configure index e0187be092..20fb91aeb0 100755 --- a/configure +++ b/configure @@ -1588,12 +1588,13 @@ case "${ARCH}" in # ARM specific optimizations arm* | aarch64) - case "${ARCH}" in + case "${ARCH}" in arm*) [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=arm ;; aarch64) [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=aarch64 + buildarmv6=0 ;; esac From 758212b6795aa59e7026a119a6267342d5d64271 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 26 Dec 2023 13:33:45 -0800 Subject: [PATCH 788/798] Add linter workflow for whitespace errors. zlib-ng/zlib-ng#1190 --- .github/workflows/lint.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000000..f279d4c1b9 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,17 @@ +name: Lint +on: [pull_request] + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Whitespace errors + run: | + git config core.whitespace tab-in-indent,blank-at-eol + git diff --color --check ${{ github.event.pull_request.base.sha }} From bed309da8419a6f92c26ad62e464250aeed6f3c6 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 26 Dec 2023 13:33:45 -0800 Subject: [PATCH 789/798] Fix trailing whitespace in minideflate.c. --- test/minideflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/minideflate.c b/test/minideflate.c index 6b16a032d9..3e4b356cc5 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -168,7 +168,7 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ do { err = PREFIX(inflate)(&d_stream, flush); - /* Ignore Z_BUF_ERROR if we are finishing and read buffer size is + /* Ignore Z_BUF_ERROR if we are finishing and read buffer size is * purposefully limited */ if (flush == Z_FINISH && err == Z_BUF_ERROR && read_buf_size != BUFSIZE) err = Z_OK; From 41dd22bc515fb6919d74eb4ae4810fe7ecc4489a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 27 Dec 2023 13:41:34 -0800 Subject: [PATCH 790/798] Fixed tab character in ARM ACLE uqsub16 assembly. --- arch/arm/acle_intrins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/acle_intrins.h b/arch/arm/acle_intrins.h index 531b8a7f66..a67cf3aabd 100644 --- a/arch/arm/acle_intrins.h +++ b/arch/arm/acle_intrins.h @@ -26,7 +26,7 @@ typedef uint32_t uint16x2_t; static inline uint16x2_t __uqsub16(uint16x2_t __a, uint16x2_t __b) { uint16x2_t __c; - __asm__ __volatile__("uqsub16\t%0, %1, %2" : "=r" (__c) : "r"(__a), "r"(__b)); + __asm__ __volatile__("uqsub16 %0, %1, %2" : "=r" (__c) : "r"(__a), "r"(__b)); return __c; } #endif From a61926d3f9bf08c5429613b75f6c3d87ac37b8aa Mon Sep 17 00:00:00 2001 From: Rye Mutt Date: Wed, 27 Dec 2023 21:38:00 -0500 Subject: [PATCH 791/798] Fix memory corruption introduced in 61e181c8ae93dbf56040336179c9954078bd1399 --- inflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inflate.c b/inflate.c index af5abf11a5..fe55c498e3 100644 --- a/inflate.c +++ b/inflate.c @@ -1350,8 +1350,8 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou copy->next = copy->codes + (state->next - state->codes); /* window */ + copy->window = NULL; if (state->window != NULL) { - copy->window = NULL; if (PREFIX(inflate_ensure_window)(copy)) { ZFREE_STATE(source, copy); return Z_MEM_ERROR; From fd5b20f4ce5f0e8d4eafaad190dca5bc74a320fe Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 28 Dec 2023 16:55:44 -0800 Subject: [PATCH 792/798] Cancel previously running CI jobs for PR or branch. --- .github/workflows/analyze.yml | 3 +++ .github/workflows/cmake.yml | 3 +++ .github/workflows/codeql.yml | 5 +++-- .github/workflows/configure.yml | 3 +++ .github/workflows/fuzz.yml | 4 +++- .github/workflows/libpng.yml | 3 +++ .github/workflows/link.yml | 3 +++ .github/workflows/nmake.yml | 3 +++ .github/workflows/pigz.yml | 3 +++ .github/workflows/pkgcheck.yml | 3 +++ 10 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 8e4cdc3032..40315e7dcd 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -1,5 +1,8 @@ name: Static Analysis on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: static-analysis: name: GCC diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index dfda736770..8c3c9a7b31 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -3,6 +3,9 @@ on: [push, pull_request] env: TERM: xterm-256color GTEST_COLOR: 1 +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: cmake: name: ${{ matrix.name }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 76f838178c..2b48d3df75 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,5 +1,4 @@ name: "CodeQL" - on: push: branches: [ "develop" ] @@ -7,7 +6,9 @@ on: branches: [ "develop" ] schedule: - cron: "27 17 * * 0" - +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: analyze: name: Analyze diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 15d35f081e..4653118535 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -1,5 +1,8 @@ name: Configure on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: configure: name: ${{ matrix.name }} diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 95d64e67ae..6525f84c5e 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -9,7 +9,9 @@ on: - '2.*' tags: - '*' - +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: fuzzing: name: Fuzzing diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index 616401a49e..a15939429e 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -1,5 +1,8 @@ name: Libpng on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: libpng: name: Ubuntu Clang diff --git a/.github/workflows/link.yml b/.github/workflows/link.yml index 1c0ee54462..9c42916014 100644 --- a/.github/workflows/link.yml +++ b/.github/workflows/link.yml @@ -1,5 +1,8 @@ name: Link on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: zlib: name: Link zlib diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index 3176552c77..a22ba468a0 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -1,5 +1,8 @@ name: NMake on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: nmake: name: ${{ matrix.name }} diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 534739e111..f1147a4e6e 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -1,5 +1,8 @@ name: Pigz on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: pigz: name: ${{ matrix.name }} diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index b2300dedcc..b2f952035b 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -1,5 +1,8 @@ name: Package Check on: [push, pull_request] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true jobs: pkgcheck: name: ${{ matrix.name }} From 838a5d586d3d8efc6847c87640880ef7743ad08d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 4 Jan 2024 09:06:03 -0800 Subject: [PATCH 793/798] Remove tab-in-indent rule from lint workflow Makefiles require using tabs as indents. So we need to remove this rule. --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index f279d4c1b9..afea46a17a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -13,5 +13,5 @@ jobs: - name: Whitespace errors run: | - git config core.whitespace tab-in-indent,blank-at-eol + git config core.whitespace blank-at-eol git diff --color --check ${{ github.event.pull_request.base.sha }} From f8327aa8f7cf22725e35ed5ce89b5cdf84ae11da Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 4 Jan 2024 14:20:19 -0800 Subject: [PATCH 794/798] Added CI instance for WITH_NATIVE_INSTRUCTIONS. --- .github/workflows/cmake.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8c3c9a7b31..11fbe960ad 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -34,6 +34,13 @@ jobs: cmake-args: -DWITH_BENCHMARKS=ON codecov: ubuntu_gcc_benchmark + - name: Ubuntu GCC Native Instructions + os: ubuntu-latest + compiler: gcc + cxx-compiler: g++ + cmake-args: -DWITH_NATIVE_INSTRUCTIONS=ON + codecov: ubuntu_gcc_native_inst + - name: Ubuntu GCC Symbol Prefix os: ubuntu-latest compiler: gcc From 89c932b4fa861850dfe653fc00bb98946eb13149 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 8 Jan 2024 21:34:19 +0100 Subject: [PATCH 795/798] Add FAR macro to zlib-compat headers to improve compatibility. --- zconf.h.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zconf.h.in b/zconf.h.in index 074f025516..7a6e281e84 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -116,6 +116,9 @@ #ifndef ZEXPORTVA # define ZEXPORTVA Z_EXPORTVA #endif +#ifndef FAR +# define FAR +#endif /* Legacy zlib typedefs for backwards compatibility. Don't assume stdint.h is defined. */ typedef unsigned char Byte; From 9053e43dde37f34ac7afbf69c76b3f7f96633fc5 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 9 Jan 2024 12:02:45 +0200 Subject: [PATCH 796/798] Fix building tests with cmake 3.10 and older. --- test/CMakeLists.txt | 172 ++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 85 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 43b4c9a7fb..03935fab4d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -157,99 +157,101 @@ if(WITH_GTEST) add_library(GTest::Main ALIAS gtest_main) endif() - set(TEST_SRCS - test_compress.cc - test_compress_bound.cc - test_cve-2003-0107.cc - test_deflate_bound.cc - test_deflate_copy.cc - test_deflate_dict.cc - test_deflate_hash_head_0.cc - test_deflate_header.cc - test_deflate_params.cc - test_deflate_pending.cc - test_deflate_prime.cc - test_deflate_quick_bi_valid.cc - test_deflate_quick_block_open.cc - test_deflate_tune.cc - test_dict.cc - test_inflate_adler32.cc - test_large_buffers.cc - test_raw.cc - test_small_buffers.cc - test_small_window.cc - ) - - if(WITH_GZFILEOP) - list(APPEND TEST_SRCS test_gzio.cc) - endif() + if(TARGET GTest::GTest) + set(TEST_SRCS + test_compress.cc + test_compress_bound.cc + test_cve-2003-0107.cc + test_deflate_bound.cc + test_deflate_copy.cc + test_deflate_dict.cc + test_deflate_hash_head_0.cc + test_deflate_header.cc + test_deflate_params.cc + test_deflate_pending.cc + test_deflate_prime.cc + test_deflate_quick_bi_valid.cc + test_deflate_quick_block_open.cc + test_deflate_tune.cc + test_dict.cc + test_inflate_adler32.cc + test_large_buffers.cc + test_raw.cc + test_small_buffers.cc + test_small_window.cc + ) + + if(WITH_GZFILEOP) + list(APPEND TEST_SRCS test_gzio.cc) + endif() - if(ZLIBNG_ENABLE_TESTS) - list(APPEND TEST_SRCS - test_adler32.cc # adler32_neon(), etc - test_aligned_alloc.cc # zng_alloc_aligned() - test_compare256.cc # compare256_neon(), etc - test_crc32.cc # crc32_acle(), etc - test_inflate_sync.cc # expects a certain compressed block layout - test_main.cc # cpu_check_features() - test_version.cc # expects a fixed version string - ) - endif() + if(ZLIBNG_ENABLE_TESTS) + list(APPEND TEST_SRCS + test_adler32.cc # adler32_neon(), etc + test_aligned_alloc.cc # zng_alloc_aligned() + test_compare256.cc # compare256_neon(), etc + test_crc32.cc # crc32_acle(), etc + test_inflate_sync.cc # expects a certain compressed block layout + test_main.cc # cpu_check_features() + test_version.cc # expects a fixed version string + ) + endif() - add_executable(gtest_zlib ${TEST_SRCS}) - configure_test_executable(gtest_zlib) + add_executable(gtest_zlib ${TEST_SRCS}) + configure_test_executable(gtest_zlib) - if(WITH_SANITIZER STREQUAL "Memory") - target_link_directories(gtest_zlib PRIVATE $ENV{LLVM_BUILD_DIR}/lib) - target_link_options(gtest_zlib PRIVATE - -stdlib=libc++ - -lc++abi - -fsanitize=memory - -fsanitize-memory-track-origins) - endif() - - if(NOT ZLIB_COMPAT AND DEFINED ZLIB_LIBRARIES AND DEFINED ZLIB_INCLUDE_DIRS) - if(NOT IS_ABSOLUTE ${ZLIB_LIBRARIES}) - get_filename_component(ZLIB_ABSOLUTE_PATH - "${CMAKE_CURRENT_SOURCE_DIR}/${ZLIB_LIBRARIES}" - ABSOLUTE) - else() - set(ZLIB_ABSOLUTE_PATH ${ZLIB_LIBRARIES}) + if(WITH_SANITIZER STREQUAL "Memory") + target_link_directories(gtest_zlib PRIVATE $ENV{LLVM_BUILD_DIR}/lib) + target_link_options(gtest_zlib PRIVATE + -stdlib=libc++ + -lc++abi + -fsanitize=memory + -fsanitize-memory-track-origins) endif() - add_library(external_zlib STATIC IMPORTED) - set_property(TARGET external_zlib PROPERTY IMPORTED_LOCATION ${ZLIB_ABSOLUTE_PATH}) - message(STATUS "Added dual linking tests against zlib") - message(STATUS " Zlib include dirs: ${ZLIB_INCLUDE_DIRS}") - message(STATUS " Zlib libraries: ${ZLIB_ABSOLUTE_PATH}") + if(NOT ZLIB_COMPAT AND DEFINED ZLIB_LIBRARIES AND DEFINED ZLIB_INCLUDE_DIRS) + if(NOT IS_ABSOLUTE ${ZLIB_LIBRARIES}) + get_filename_component(ZLIB_ABSOLUTE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/${ZLIB_LIBRARIES}" + ABSOLUTE) + else() + set(ZLIB_ABSOLUTE_PATH ${ZLIB_LIBRARIES}) + endif() - target_sources(gtest_zlib PRIVATE test_compress_dual.cc) - target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIRS}) - target_link_libraries(gtest_zlib external_zlib) - endif() + add_library(external_zlib STATIC IMPORTED) + set_property(TARGET external_zlib PROPERTY IMPORTED_LOCATION ${ZLIB_ABSOLUTE_PATH}) + message(STATUS "Added dual linking tests against zlib") + message(STATUS " Zlib include dirs: ${ZLIB_INCLUDE_DIRS}") + message(STATUS " Zlib libraries: ${ZLIB_ABSOLUTE_PATH}") - if(NOT DEFINED BUILD_SHARED_LIBS) - # Link statically in order to test internal zlib-ng functions. - target_link_libraries(gtest_zlib zlibstatic) - else() - target_link_libraries(gtest_zlib zlib) - endif() + target_sources(gtest_zlib PRIVATE test_compress_dual.cc) + target_include_directories(gtest_zlib PRIVATE ${ZLIB_INCLUDE_DIRS}) + target_link_libraries(gtest_zlib external_zlib) + endif() - if(BUILD_SHARED_LIBS) - target_link_libraries(gtest_zlib GTest::Main) - endif() - target_link_libraries(gtest_zlib GTest::GTest) - - find_package(Threads) - if(Threads_FOUND AND NOT BASEARCH_WASM32_FOUND) - target_sources(gtest_zlib PRIVATE test_deflate_concurrency.cc) - if(UNIX AND NOT APPLE) - # On Linux, use a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590 - target_link_libraries(gtest_zlib -Wl,--whole-archive -lpthread -Wl,--no-whole-archive) + if(NOT DEFINED BUILD_SHARED_LIBS) + # Link statically in order to test internal zlib-ng functions. + target_link_libraries(gtest_zlib zlibstatic) + else() + target_link_libraries(gtest_zlib zlib) endif() - target_link_libraries(gtest_zlib Threads::Threads) - endif() - add_test(NAME gtest_zlib - COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) + if(BUILD_SHARED_LIBS) + target_link_libraries(gtest_zlib GTest::Main) + endif() + target_link_libraries(gtest_zlib GTest::GTest) + + find_package(Threads) + if(Threads_FOUND AND NOT BASEARCH_WASM32_FOUND) + target_sources(gtest_zlib PRIVATE test_deflate_concurrency.cc) + if(UNIX AND NOT APPLE) + # On Linux, use a workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590 + target_link_libraries(gtest_zlib -Wl,--whole-archive -lpthread -Wl,--no-whole-archive) + endif() + target_link_libraries(gtest_zlib Threads::Threads) + endif() + + add_test(NAME gtest_zlib + COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) + endif() endif() From 74253725f884e2424a0dd8ae3f69896d5377f325 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 7 Jan 2024 19:29:13 +0100 Subject: [PATCH 797/798] 2.1.6 Release --- Makefile.in | 2 +- zlib-ng.h.in | 6 +++--- zlib.h.in | 6 +++--- zutil.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.in b/Makefile.in index d2bd47f171..3859eb5325 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.1.5 +VER=2.1.6 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h.in b/zlib-ng.h.in index de811e05e3..342b240afb 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -48,11 +48,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.5" -#define ZLIBNG_VERNUM 0x020105F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.6" +#define ZLIBNG_VERNUM 0x020106F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 5 +#define ZLIBNG_VER_REVISION 6 #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ #define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ diff --git a/zlib.h.in b/zlib.h.in index 9e27d99c07..eabb94afe0 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -49,11 +49,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.1.5" -#define ZLIBNG_VERNUM 0x020105F0L /* MMNNRRSM: major minor revision status modified */ +#define ZLIBNG_VERSION "2.1.6" +#define ZLIBNG_VERNUM 0x020106F0L /* MMNNRRSM: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 1 -#define ZLIBNG_VER_REVISION 5 +#define ZLIBNG_VER_REVISION 6 #define ZLIBNG_VER_STATUS F /* 0=devel, 1-E=beta, F=Release (DEPRECATED) */ #define ZLIBNG_VER_STATUSH 0xF /* Hex values: 0=devel, 1-E=beta, F=Release */ #define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ diff --git a/zutil.c b/zutil.c index bd937c55e8..270a28c742 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char PREFIX3(vstring)[] = - " zlib-ng 2.1.5"; + " zlib-ng 2.1.6"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From bfb184bb0fbdabe82f3a36d209e56c3e2c33866a Mon Sep 17 00:00:00 2001 From: Michael Kolupaev Date: Mon, 27 May 2024 21:03:25 +0000 Subject: [PATCH 798/798] Resolve conflicts (reproduce the ((constructor)) change, update CMakeLists.txt, hope I got everything right) --- arch/arm/arm.h | 18 ---- arch/arm/armfeature.c | 71 --------------- arch/power/power.c | 19 ---- arch/power/power.h | 11 --- arch/x86/x86.c | 82 ----------------- arch/x86/x86.h | 23 ----- crc32.c | 206 ------------------------------------------ deflate.c | 4 + functable.c | 165 +-------------------------------- functable.h | 5 +- inflate.c | 5 + 11 files changed, 15 insertions(+), 594 deletions(-) delete mode 100644 arch/arm/arm.h delete mode 100644 arch/arm/armfeature.c delete mode 100644 arch/power/power.c delete mode 100644 arch/power/power.h delete mode 100644 arch/x86/x86.c delete mode 100644 arch/x86/x86.h delete mode 100644 crc32.c diff --git a/arch/arm/arm.h b/arch/arm/arm.h deleted file mode 100644 index 5fbc1d3ef1..0000000000 --- a/arch/arm/arm.h +++ /dev/null @@ -1,18 +0,0 @@ -/* arm.h -- check for ARM features. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef ARM_H_ -#define ARM_H_ - -/* - A hack that helps AppleClang linker to see arm_cpu_has_* flags. - A single call to dummy_linker_glue_y() in the compilation unit that reads - arm_cpu_has_* flags will resolve "undefined symbol" link error. -*/ -void dummy_linker_glue_y(); - -extern int arm_cpu_has_neon; -extern int arm_cpu_has_crc32; - -#endif /* ARM_H_ */ diff --git a/arch/arm/armfeature.c b/arch/arm/armfeature.c deleted file mode 100644 index f32195b2d7..0000000000 --- a/arch/arm/armfeature.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "../../zutil.h" - -#if defined(__linux__) -# include -# include -#elif defined(__FreeBSD__) && defined(__aarch64__) -# include -# ifndef ID_AA64ISAR0_CRC32_VAL -# define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32 -# endif -#elif defined(__APPLE__) -# include -#elif defined(_WIN32) -# include -#endif - -Z_INTERNAL void dummy_linker_glue_y(void) {} - -static int arm_has_crc32() { -#if defined(__linux__) && defined(HWCAP2_CRC32) - return (getauxval(AT_HWCAP2) & HWCAP2_CRC32) != 0 ? 1 : 0; -#elif defined(__FreeBSD__) && defined(__aarch64__) - return getenv("QEMU_EMULATING") == NULL - && ID_AA64ISAR0_CRC32_VAL(READ_SPECIALREG(id_aa64isar0_el1)) >= ID_AA64ISAR0_CRC32_BASE; -#elif defined(__APPLE__) - int hascrc32; - size_t size = sizeof(hascrc32); - return sysctlbyname("hw.optional.armv8_crc32", &hascrc32, &size, NULL, 0) == 0 - && hascrc32 == 1; -#elif defined(ARM_NOCHECK_ACLE) - return 1; -#else - return 0; -#endif -} - -/* AArch64 has neon. */ -#if !defined(__aarch64__) && !defined(_M_ARM64) -static inline int arm_has_neon() { -#if defined(__linux__) && defined(HWCAP_NEON) - return (getauxval(AT_HWCAP) & HWCAP_NEON) != 0 ? 1 : 0; -#elif defined(__APPLE__) - int hasneon; - size_t size = sizeof(hasneon); - return sysctlbyname("hw.optional.neon", &hasneon, &size, NULL, 0) == 0 - && hasneon == 1; -#elif defined(_M_ARM) && defined(WINAPI_FAMILY_PARTITION) -# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) - return 1; /* Always supported */ -# endif -#endif - -#if defined(ARM_NOCHECK_NEON) - return 1; -#else - return 0; -#endif -} -#endif - -Z_INTERNAL int arm_cpu_has_neon; -Z_INTERNAL int arm_cpu_has_crc32; - -static void __attribute__((constructor)) arm_check_features(void) { -#if defined(__aarch64__) || defined(_M_ARM64) - arm_cpu_has_neon = 1; /* always available */ -#else - arm_cpu_has_neon = arm_has_neon(); -#endif - arm_cpu_has_crc32 = arm_has_crc32(); -} diff --git a/arch/power/power.c b/arch/power/power.c deleted file mode 100644 index b277c26378..0000000000 --- a/arch/power/power.c +++ /dev/null @@ -1,19 +0,0 @@ -/* POWER feature check - * Copyright (C) 2020 Matheus Castanho , IBM - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include -#include "../../zutil.h" - -Z_INTERNAL int power_cpu_has_arch_2_07; - -static void __attribute__((constructor)) power_check_features(void) { - unsigned long hwcap2; - hwcap2 = getauxval(AT_HWCAP2); - -#ifdef POWER8 - if (hwcap2 & PPC_FEATURE2_ARCH_2_07) - power_cpu_has_arch_2_07 = 1; -#endif -} diff --git a/arch/power/power.h b/arch/power/power.h deleted file mode 100644 index 0bf0b1ec40..0000000000 --- a/arch/power/power.h +++ /dev/null @@ -1,11 +0,0 @@ -/* power.h -- check for POWER CPU features - * Copyright (C) 2020 Matheus Castanho , IBM - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef POWER_H_ -#define POWER_H_ - -extern int power_cpu_has_arch_2_07; - -#endif /* POWER_H_ */ diff --git a/arch/x86/x86.c b/arch/x86/x86.c deleted file mode 100644 index cbbce29fdd..0000000000 --- a/arch/x86/x86.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * x86 feature check - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * Author: - * Jim Kukunas - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zutil.h" - -#ifdef _MSC_VER -# include -#else -// Newer versions of GCC and clang come with cpuid.h -# include -#endif - -Z_INTERNAL void dummy_linker_glue_y(void) {} - -Z_INTERNAL int x86_cpu_has_avx2; -Z_INTERNAL int x86_cpu_has_sse2; -Z_INTERNAL int x86_cpu_has_ssse3; -Z_INTERNAL int x86_cpu_has_sse42; -Z_INTERNAL int x86_cpu_has_pclmulqdq; -Z_INTERNAL int x86_cpu_has_tzcnt; - -static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _MSC_VER - unsigned int registers[4]; - __cpuid((int *)registers, info); - - *eax = registers[0]; - *ebx = registers[1]; - *ecx = registers[2]; - *edx = registers[3]; -#else - __cpuid(info, *eax, *ebx, *ecx, *edx); -#endif -} - -static void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { -#ifdef _MSC_VER - unsigned int registers[4]; - __cpuidex((int *)registers, info, subinfo); - - *eax = registers[0]; - *ebx = registers[1]; - *ecx = registers[2]; - *edx = registers[3]; -#else - __cpuid_count(info, subinfo, *eax, *ebx, *ecx, *edx); -#endif -} - -static void __attribute__((constructor)) x86_check_features(void) { - unsigned eax, ebx, ecx, edx; - unsigned maxbasic; - - cpuid(0, &maxbasic, &ebx, &ecx, &edx); - - cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx); - - x86_cpu_has_sse2 = edx & 0x4000000; - x86_cpu_has_ssse3 = ecx & 0x200; - x86_cpu_has_sse42 = ecx & 0x100000; - x86_cpu_has_pclmulqdq = ecx & 0x2; - - if (maxbasic >= 7) { - cpuidex(7, 0, &eax, &ebx, &ecx, &edx); - - // check BMI1 bit - // Reference: https://software.intel.com/sites/default/files/article/405250/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family.pdf - x86_cpu_has_tzcnt = ebx & 0x8; - // check AVX2 bit - x86_cpu_has_avx2 = ebx & 0x20; - } else { - x86_cpu_has_tzcnt = 0; - x86_cpu_has_avx2 = 0; - } -} diff --git a/arch/x86/x86.h b/arch/x86/x86.h deleted file mode 100644 index 7ac9b46aa6..0000000000 --- a/arch/x86/x86.h +++ /dev/null @@ -1,23 +0,0 @@ -/* cpu.h -- check for CPU features -* Copyright (C) 2013 Intel Corporation Jim Kukunas -* For conditions of distribution and use, see copyright notice in zlib.h -*/ - -#ifndef CPU_H_ -#define CPU_H_ - -/* - A hack that helps AppleClang linker to see x86_cpu_has_* flags. - A single call to dummy_linker_glue_y() in the compilation unit that reads - x86_cpu_has_* flags will resolve "undefined symbol" link error. -*/ -void dummy_linker_glue_y(); - -extern int x86_cpu_has_avx2; -extern int x86_cpu_has_sse2; -extern int x86_cpu_has_ssse3; -extern int x86_cpu_has_sse42; -extern int x86_cpu_has_pclmulqdq; -extern int x86_cpu_has_tzcnt; - -#endif /* CPU_H_ */ diff --git a/crc32.c b/crc32.c deleted file mode 100644 index b46630e5ef..0000000000 --- a/crc32.c +++ /dev/null @@ -1,206 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -#include "zbuild.h" -#include "zendian.h" -#include -#include "deflate.h" -#include "functable.h" -#include "crc32_tbl.h" - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const uint32_t * Z_EXPORT PREFIX(get_crc_table)(void) { - return (const uint32_t *)crc_table; -} - -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(crc32_z)(unsigned long crc, const unsigned char *buf, size_t len) { - if (buf == NULL) return 0; - - return (unsigned long)functable.crc32((uint32_t)crc, buf, len); -} -#else -uint32_t Z_EXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t len) { - if (buf == NULL) return 0; - - return functable.crc32(crc, buf, len); -} -#endif -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 -#define DO4 DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_generic(uint32_t crc, const unsigned char *buf, uint64_t len) { - crc = crc ^ 0xffffffff; - -#ifdef UNROLL_MORE - while (len >= 8) { - DO8; - len -= 8; - } -#else - while (len >= 4) { - DO4; - len -= 4; - } -#endif - - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffff; -} - -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(crc32)(unsigned long crc, const unsigned char *buf, unsigned int len) { - return (unsigned long)PREFIX(crc32_z)((uint32_t)crc, buf, len); -} -#else -uint32_t Z_EXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t len) { - return PREFIX(crc32_z)(crc, buf, len); -} -#endif - -/* - This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit - integer pointer type. This violates the strict aliasing rule, where a - compiler can assume, for optimization purposes, that two pointers to - fundamentally different types won't ever point to the same memory. This can - manifest as a problem only if one of the pointers is written to. This code - only reads from those pointers. So long as this code remains isolated in - this compilation unit, there won't be a problem. For this reason, this code - should not be copied and pasted into a compilation unit in which other code - writes to the buffer that is passed to these routines. - */ - -/* ========================================================================= */ -#if BYTE_ORDER == LITTLE_ENDIAN -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_little(uint32_t crc, const unsigned char *buf, uint64_t len) { - Z_REGISTER uint32_t c; - Z_REGISTER const uint32_t *buf4; - - c = crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const uint32_t *)(const void *)buf; - -#ifdef UNROLL_MORE - while (len >= 32) { - DOLIT32; - len -= 32; - } -#endif - - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return c; -} -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -/* ========================================================================= */ -#if BYTE_ORDER == BIG_ENDIAN -#define DOBIG4 c ^= *buf4++; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_t len) { - Z_REGISTER uint32_t c; - Z_REGISTER const uint32_t *buf4; - - c = ZSWAP32(crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const uint32_t *)(const void *)buf; - -#ifdef UNROLL_MORE - while (len >= 32) { - DOBIG32; - len -= 32; - } -#endif - - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf = (const unsigned char *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return ZSWAP32(c); -} -#endif /* BYTE_ORDER == BIG_ENDIAN */ - -#ifdef X86_PCLMULQDQ_CRC -#include "arch/x86/x86.h" -#include "arch/x86/crc_folding.h" - -Z_INTERNAL void crc_finalize(deflate_state *const s) { - if (x86_cpu_has_pclmulqdq) - s->strm->adler = crc_fold_512to32(s); -} -#endif - -Z_INTERNAL void crc_reset(deflate_state *const s) { -#ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) { - crc_fold_init(s); - return; - } -#endif - s->strm->adler = PREFIX(crc32)(0L, NULL, 0); - -#if defined(__APPLE__) - dummy_linker_glue_x(); - dummy_linker_glue_y(); -#endif -} - -Z_INTERNAL void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size) { -#ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) { - crc_fold_copy(strm->state, dst, strm->next_in, size); - return; - } -#endif - memcpy(dst, strm->next_in, size); - strm->adler = PREFIX(crc32)(strm->adler, dst, size); -} diff --git a/deflate.c b/deflate.c index 735014516b..a773a0459c 100644 --- a/deflate.c +++ b/deflate.c @@ -313,6 +313,10 @@ int32_t ZNG_CONDEXPORT PREFIX(deflateInit2)(PREFIX3(stream) *strm, int32_t level s->block_open = 0; s->reproducible = 0; +#if defined(__APPLE__) + dummy_linker_glue(); +#endif + return PREFIX(deflateReset)(strm); } diff --git a/functable.c b/functable.c index 37c4aeef7d..c063d373c2 100644 --- a/functable.c +++ b/functable.c @@ -15,42 +15,13 @@ # include #endif -/* Platform has pointer size atomic store */ -#if defined(__GNUC__) || defined(__clang__) -# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ - __atomic_store(&(functable.FUNC_NAME), &(VAR.FUNC_NAME), __ATOMIC_SEQ_CST) -# define FUNCTABLE_BARRIER() __atomic_thread_fence(__ATOMIC_SEQ_CST) -#elif defined(_MSC_VER) -# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ - _InterlockedExchangePointer((void * volatile *)&(functable.FUNC_NAME), (void *)(VAR.FUNC_NAME)) -# if defined(_M_ARM) || defined(_M_ARM64) -# define FUNCTABLE_BARRIER() do { \ - _ReadWriteBarrier(); \ - __dmb(0xB); /* _ARM_BARRIER_ISH */ \ - _ReadWriteBarrier(); \ -} while (0) -# else -# define FUNCTABLE_BARRIER() _ReadWriteBarrier() -# endif -#else -# warning Unable to detect atomic intrinsic support. -# define FUNCTABLE_ASSIGN(VAR, FUNC_NAME) \ - *((void * volatile *)&(functable.FUNC_NAME)) = (void *)(VAR.FUNC_NAME) -# define FUNCTABLE_BARRIER() do { /* Empty */ } while (0) -#endif - -static void force_init_empty(void) { - // empty -} - -static void init_functable(void) { +static void __attribute__((constructor)) init_functable(void) { struct functable_s ft; struct cpu_features cf; cpu_check_features(&cf); // Generic code - ft.force_init = &force_init_empty; ft.adler32 = &adler32_c; ft.adler32_fold_copy = &adler32_fold_copy_c; ft.chunkmemset_safe = &chunkmemset_safe_c; @@ -266,138 +237,10 @@ static void init_functable(void) { ft.crc32 = crc32_s390_vx; #endif - // Assign function pointers individually for atomic operation - FUNCTABLE_ASSIGN(ft, force_init); - FUNCTABLE_ASSIGN(ft, adler32); - FUNCTABLE_ASSIGN(ft, adler32_fold_copy); - FUNCTABLE_ASSIGN(ft, chunkmemset_safe); - FUNCTABLE_ASSIGN(ft, chunksize); - FUNCTABLE_ASSIGN(ft, compare256); - FUNCTABLE_ASSIGN(ft, crc32); - FUNCTABLE_ASSIGN(ft, crc32_fold); - FUNCTABLE_ASSIGN(ft, crc32_fold_copy); - FUNCTABLE_ASSIGN(ft, crc32_fold_final); - FUNCTABLE_ASSIGN(ft, crc32_fold_reset); - FUNCTABLE_ASSIGN(ft, inflate_fast); - FUNCTABLE_ASSIGN(ft, insert_string); - FUNCTABLE_ASSIGN(ft, longest_match); - FUNCTABLE_ASSIGN(ft, longest_match_slow); - FUNCTABLE_ASSIGN(ft, quick_insert_string); - FUNCTABLE_ASSIGN(ft, slide_hash); - FUNCTABLE_ASSIGN(ft, update_hash); - - // Memory barrier for weak memory order CPUs - FUNCTABLE_BARRIER(); -} - -/* stub functions */ -static void force_init_stub(void) { - init_functable(); -} - -static uint32_t adler32_stub(uint32_t adler, const uint8_t* buf, size_t len) { - init_functable(); - return functable.adler32(adler, buf, len); -} - -static uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t* dst, const uint8_t* src, size_t len) { - init_functable(); - return functable.adler32_fold_copy(adler, dst, src, len); -} - -static uint8_t* chunkmemset_safe_stub(uint8_t* out, unsigned dist, unsigned len, unsigned left) { - init_functable(); - return functable.chunkmemset_safe(out, dist, len, left); -} - -static uint32_t chunksize_stub(void) { - init_functable(); - return functable.chunksize(); -} - -static uint32_t compare256_stub(const uint8_t* src0, const uint8_t* src1) { - init_functable(); - return functable.compare256(src0, src1); -} - -static uint32_t crc32_stub(uint32_t crc, const uint8_t* buf, size_t len) { - init_functable(); - return functable.crc32(crc, buf, len); + functable = ft; } -static void crc32_fold_stub(crc32_fold* crc, const uint8_t* src, size_t len, uint32_t init_crc) { - init_functable(); - functable.crc32_fold(crc, src, len, init_crc); -} - -static void crc32_fold_copy_stub(crc32_fold* crc, uint8_t* dst, const uint8_t* src, size_t len) { - init_functable(); - functable.crc32_fold_copy(crc, dst, src, len); -} - -static uint32_t crc32_fold_final_stub(crc32_fold* crc) { - init_functable(); - return functable.crc32_fold_final(crc); -} - -static uint32_t crc32_fold_reset_stub(crc32_fold* crc) { - init_functable(); - return functable.crc32_fold_reset(crc); -} - -static void inflate_fast_stub(PREFIX3(stream) *strm, uint32_t start) { - init_functable(); - functable.inflate_fast(strm, start); -} - -static void insert_string_stub(deflate_state* const s, uint32_t str, uint32_t count) { - init_functable(); - functable.insert_string(s, str, count); -} - -static uint32_t longest_match_stub(deflate_state* const s, Pos cur_match) { - init_functable(); - return functable.longest_match(s, cur_match); -} - -static uint32_t longest_match_slow_stub(deflate_state* const s, Pos cur_match) { - init_functable(); - return functable.longest_match_slow(s, cur_match); -} - -static Pos quick_insert_string_stub(deflate_state* const s, const uint32_t str) { - init_functable(); - return functable.quick_insert_string(s, str); -} - -static void slide_hash_stub(deflate_state* s) { - init_functable(); - functable.slide_hash(s); -} - -static uint32_t update_hash_stub(deflate_state* const s, uint32_t h, uint32_t val) { - init_functable(); - return functable.update_hash(s, h, val); -} +Z_INTERNAL void dummy_linker_glue(void) {} /* functable init */ -Z_INTERNAL struct functable_s functable = { - force_init_stub, - adler32_stub, - adler32_fold_copy_stub, - chunkmemset_safe_stub, - chunksize_stub, - compare256_stub, - crc32_stub, - crc32_fold_stub, - crc32_fold_copy_stub, - crc32_fold_final_stub, - crc32_fold_reset_stub, - inflate_fast_stub, - insert_string_stub, - longest_match_stub, - longest_match_slow_stub, - quick_insert_string_stub, - slide_hash_stub, - update_hash_stub -}; +Z_INTERNAL struct functable_s functable; diff --git a/functable.h b/functable.h index 8d436ca070..994ba9bff7 100644 --- a/functable.h +++ b/functable.h @@ -18,13 +18,12 @@ typedef struct zng_stream_s zng_stream; /* A hack that helps AppleClang linker to see functable. - A single call to dummy_linker_glue_x() in the compilation unit that reads + A single call to dummy_linker_glue() in the compilation unit that reads functable will resolve "undefined symbol" link error. */ -void dummy_linker_glue_x(); +void dummy_linker_glue(); struct functable_s { - void (* force_init) (void); uint32_t (* adler32) (uint32_t adler, const uint8_t *buf, size_t len); uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); diff --git a/inflate.c b/inflate.c index 1ba9f99a5c..daa06cfcef 100644 --- a/inflate.c +++ b/inflate.c @@ -162,6 +162,11 @@ int32_t ZNG_CONDEXPORT PREFIX(inflateInit2)(PREFIX3(stream) *strm, int32_t windo ZFREE_STATE(strm, state); strm->state = NULL; } + +#if defined(__APPLE__) + dummy_linker_glue(); +#endif + return ret; }
  • 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℞AMkzQ=&V-bWaym-?9j zyCi192}tL)N%e?~*W@z0)P+wO&;J`_8KN3chq4AkW^o^9hzf$RU7@5(=g=}p7F%az z67j5Mr@nX0RXt2n-ULl;q)sM=WXYHd(UvL;MTkiP-q$~I6Lf`Btf$=SOTt%P2_EcVgVKgOwE;s;d za%pqM{npVqfi8?hZ1`LYoVKHT4d8lQCqNRd(LZ=Eo5s5y;mktXYaKOz7U_`PoLmvBiV z9*_h}wKlUwTp6!e&Lyl9X(?#h!3X6mT^JUPWO+ghr(DM*dQCZjJn57n;gFMC=iBTD z_>8`^a?Z4JbLZ9fxlA9Zq)eT{W$=YcprksXT&1Dz&bLe9h=cnJy&fNMpPCHB_UKjcA>?wb#i#-T@q&S%L{foIx8e@5E9e zr^m?ZGRVsz$7w2&Kjp+@xgHh`casdBab5T#9Ld_l-#3MmN+JA(^2}i+C&VVu&4Ik=s3dpXlv}KYK^e#;DdS3e+>mnq9=mj?_^h&xWZ=3) z1mq_2!`PXa@-v{9{=qy-yP-}d$yJmmiKR%SQ6yc179V=u3UZ%KVn`m{=#y)zK=!s_ z>JRXoUfa8;Uf2=W2EWEN?Siw1`n=J~kcQR})yM8OgCF*`3ntln)%%O^Y|z(Ns+@Z% zr0&TK;X*pqt)5~C8_E8uRY?hIdN9reqQ$nP3jJbO^ov%38dU-dIb5^D8~?SzSjHuw zTA}2ZDx><)7;06Kv-njk4_mP$0$*+nt7YAZGmDI+1ZQIzi4`1sY9+IbV17u3o*#$| zZKUTKYx1G%E#AT)WbRZWj%keRX+RHmQ{D>!=EC2mODF#pAI60-$!jVFlB`&>5hs&? z0c|@=8o<$wYSz+{kb=jea`1T1K%9Ndor8hDKb?<~Hij*>$!^AgN6)bwJds_iI#3hf zR zu3|aqg~xoC+g#=XCQ$+R2xq=h+wy5G*4WBg~YsOU0cV9$mnC8Z6Lb+>h=A|^QtOgXcLo4J2TZ3d6Q#SF|MOPc4q zVAr+^l$gC6E-lD*{sP37A&`W)rUqTv!CPA1xmtf&K>Lu~_>=F}VDTurWEDlev=a*d zWkOai)tW@o8$`78Hk}gs)!oj+pX0~D7@<5vIE=~@Ba#}aeONFj`C+BTd6*V6iLMUs zN|LoVFN|!vX03kV`)O|e@~B|kCPKoZ^1-(?3tU_QD#oxJZH8TpNCD9ZlHY96)=DGS z5GA@hY9zCiZ^8Kh_LsU#y{D1l{LFDpH~Z+o?PZW!a{Lb#D%RiPpEEHM#Ib-aMT#d{ zat=#|RDJCI9Mr*mnKZ9-Y^3< zII>cQq_CbrVn+tC_s9W|hg{8Yeje8>r)P|Cjog#|+|&(G2{{*cdl%1?^AqHcrR^14 z99em645EN{`WqdDf{=zkS$Z#>S+w5rTUjBE-fA=mtKU}=E0W(V^7>wl_#SxTnWHFW zm%l=*&VUYXR5|QzviU>+#Rz1Qo}D@SrY)dZRp=1I2E|OHAnSsYL##bQXch zM_o3zBHG8HUyR!>eyy9%<1A6k<5tub7Xb{tmVIB|18K8XH!qRFsgh1v-MW1h=o{1% zn$c<;Il;xn=!&S~BxN|mW8`Er4U+}opMv$wnJWT^b9}2rDn8Qf*dv0x_i(+yq}dAy zc)gdI1}L?hjgVxc*-eY1V0LSb&AHASix`^ci5g(?bX{ykvHELDj|h*ezgM(7f%zpe z@6}WTGKzJYzK@jTvD~;vJjNEL5*R`cOP(g#^bfExbxI6SB5`SChRTI0E}l*tedIQL zIbF*SbsszF-l0&Q=#+*)`U-1*QYL!!ZZ23lVppiD1dV*M zVyL#I#UYZe(0Z*H2hTivwfRj)YN$qtH!G7iF5_nwTWSf>SycsB4(o?Z$+kpXADU;c z#m2_HN1XEHx`YlAS-Yh87GyGO1<&9SPOOOQT{a(UZpsrWJQW8LnlY?2?jP*EB5gCy zF0q|xr7x=CZc<%WjBCJC`C&Aay7W;P5KYQ-p?`W5hUi5nSS-aY52I?q3WweG+bxMB z;1Ti6=9w^LXtz&4#nyzEP?|EizTgIiWDj%?EaZN-cw0N1-umvk@V%CQpAiLs z;xx9{cl>dH0}h(yp0zZB4k~paw6NPFOjtHZPRLHq@uKe0v^dG%VsgF z+!!S0-Ap>!em%HCh)2iaN!X~_UXa6a!e6clT)~rVm1sBAdCMskJcK6-1#Qh-?Z-kF zI%AsXXXCiaq<@p9R!`(PLp!$lHAzz{DBIzn4zusC_WNpUhx?7-)aX~c)6v{&4|+Fp zP*f0|k*k_aU=$B*bhOn6oJX8Dnq)BG3SoLCjTv$-;CQQg;bw$`!oarziIKn{^0B#b z7#X2GifMJ z@`VQ^0u!Yk4&i@L!#WTuW3h(a>S8Z9%0C3 z01MeURh`Y2f76m9fnr&AIaNYxLPCyR)sKzRX?tY3=00BAd=?Ne*zq@riBXg1adfM9 z26bK013T$O>;0(AyzN3{StoQMsKNG7JsWJDs;(k8s<5)Gk=SUr(}QAK=sLfgu4n0; z3_on;dK&f|iSf~9n)&!mj&A$kVYz8xGV7eIeU*XP?NE_#2T@0`9geCj!y;b}p0%dQ|Q+x(rP5H@wI+{%ZAggfqG{ByPu*sCTyfuuQD zjJqx_v0rQsKSupygOwV~*Xj|23>>(w0bBax)~pV>3Yu>F&5k6&Wb|#NE=+1r;bVF- z_^!6H45!+Kh#FJ1d!CFc+K4DkExT=6o4abznmcAs3;a*FO0#QGaY+mR3bw-T+y zv z2DDL9s?HrSlIPGt6pVldnq}t~0dvXL3BmFxB$X+KYmFOcy;RaavS_4Eo2*f$WNXN% z4asJm6EdOBuL-M|j&PCD?nt;Xkl1kH_b8-bvg0Pb?HH8w?wobUK^VH2} zF&CI`swqeQ<;JM4i8&u&Y^?fxFEEmxY;`5DHR@o$W$a~drQht+9A1Z|m3>6khF*|$ znnK)9qX4dwP!lgyL$f9~yZM+(ecNFYV-t*?TO_?ziDw0vUt%%KI=V-Gj)+Rg{?HBJ z=ipw4#cl>$o7_rYm@Ml1dqDDZY_%s=R4bm5^E7?v#rk%ksM93P_H$ddHIGbp&1&7h zA6>}fp&(DlkSq&EVD4F;jVfi~!Ybl7#Z2g?0d%Z*jJHnL$W9F{LPtJ+*EVtDq^A`7 zkh=AYedpN+svh#)WW_Yen zMCVr3Cm6R+?{ztnQ+DzlcBjW50t9bU5(LL6+00|0--L>6O`@e#{1`sHV0F$i2GtE? z31x`{v8e3egEA32nf@%+tS?0*=wKJw(FD`!k1RvCN!@n95kj9kf?KKJix-&O_;9Tq zJ0Tu0R6+3!zdpH#0uga2iWV;a{LNUQoyZDQWTbaGd=U5^XZ3(cPbp2mPr5qg>#Z8s z%K~44c~ov)!&>MBU!$mwd_-#X`%(Nl%jo9M%5G*Ee!22fxwh(AT@*M~aEWis zeAtYVBPN$wo86r))qo|k<|tDQQNRcJg@}uLM8XL&%9o^i%=Hl!e zI|@li(B2tazSe2v&@9D2?AyS9YR~)q?CJdKbISAA_&{!#(#pp-eeX{^y-srFc$tDuQY2ne(W%1%P5Ntl!tUN_ZsG+9NqDv-wd9^AAe)huqFYX# zERi0Ae*DDHIz|QDiGF01Xl@A^2{QlCI|FIfYKB;)=`QJ6AJSQrugSzc&J+Hl`N|V&x@$H z>9HNk943u0lImhI&c6K?oC8xiM;fj&YhA7d<$WV&88yjHM55|^K!*~9fo&E~091J7 z%#Jd4Yt$M@?m^tY{@9q&2ndS z#ZHVF>1{unFePENjGZyOdp?8pQzd)uk!7u;g1j!Ou!Q|3NhxgZ4)&H%>a{gcRSl0i99k|)pi8$G~ z^U8mr6MsSX&qg+nQOM{HqG^ zpRU8dMAQH3I(&aDYHr}DV&Y6h_1$z3`))S;ONsqgbK$>KSljPzg5$UM`k!>cH;VqZ zzAJ9={k6>8|B_q(sk^c;G5_QD|8L!ujrkwN0uC0Y@4Cc)&i<*pax!zW{@Zr_e+d@2 zf~%rgE;DS-$Mgds5VJdnqs$ZICn7L0iB2Mk1{I@3vPqKaCCL768)62byY zd|gN0p@3He^BS}U)&>D`0mIvs2lEcMzi|j!6-_v%@goG@;NSxyrlyAO1?&KMn1$m` zLcl?q2P7zlvvwB3uR!O=)dvX23w%ir(1VJR=oN#5_jGrI^-o`dKz%QL=ko?)#6p3Y z4QdzN;3IDJ|78yx*FPN(=m!h;2Lh#<{D{*gGzhx~=@JGq4?&%T0CAImbnmwzwgqyw z@$b!~5LyQZ`P!>~84WYX zr2=#kvk&UO)7pnOAb$zv%(sFH=LDitgzw9V06{fz2GVct?N{K`<`C3DvdqyaR%4ngxw+Yt~4yWggCoQAXM=br~V2(BL% z3Iy%HDm*Lr!}n5O0Sf5k5E%OU4G`)l^Fu@gNGBa0MIXK)Y#`z@3BM+E&fEg*X zib%;H>=o(yitcOs3-`^g1_A3)!!G~JST$&!7)aTVDF5ox4lCEsA@HrvWe51Z>wCy1 za}){a$IbtBTZXkdB!I_cL7V$BS<)MnjVq ze%ilJLskd>@CM`T&`N#xW2lU1Xw~SRN%Lu8PMr}2h z_S_>tdc~vAo-=Bp`#RGf^%yvjT(6AVhxDaqqJ2cT`36qP>T{~)InOk7>lZnXHpx`_ zGku~MO(ODi^>w&QLU}=n7 z!byWYx;Etv0{-gSg~}0ql2z%~S=Z;l;7X!ZE#tl^U#s;$X_^fjt#;f-)oYZHEJWRR zeWHs^gKuT@T7)8dvR)nU5y6^}@t-|9(H=sn>-2M6j>^q+-fHk9-;Prr@e8Rk8%POE zkBk--O(-bQlUQNO%Q@a7Zhx9z zhPDd^JvwgCHMO@x86mP1mM$KEA63yr6=@aqGDf2$7AxTmN8ravoVyS>pU;th3=d;# zLmzaaxY^3?st*+CPcCDrK_Rx|BX(wlK*uYc`1$QJb<&+MC(9H>eJoi z+*ZW*RJ3VW?%=9=`*-8%L#pw?UPLBLs@&)c647|tUBvBf;BIO0{=%_X+1p34F6E+O zLo~`J8MX2T0`q;)tb8vYZ6Bae1gMCl^rNizZr67iJlO=X|VikqXG| zFWLbTbwHkPPVh%VAeSEFra>qF;#5vLS9mgg2i>N;`FyKYur%k*!MIFgA3I~oB@m3o zS7wXo?Q#_esLWWWE4Fw1%*V^V(nD{;)5tp<%Rtu8WfK-uAtA;5ad;;&Hw5|vM3?89`_2e_j4)wSmUQc~0(Hv@?WZPahdEP2*%(&uRJ4dr37 z%!jxw1th3S#+js)-B!;|-MTBHHZ*NNV6_%rVC#&ed9}O9i=?tWj$GP!6yDU=ux=ym z9t9yc&T{qi3Urmc6gy}<+IuYLQ#`DuS+?baLKZQdK7GuW?R$=n0zVJ|<>FzcKQDni zTWogQJfSanDIK#5*d8utEetCt11p@pr;4*)sR0 z%#8~GK4w35O}-VH@sW8&nBT>$!{l4#3UGq;3_-c)7sOt%&)YTI7i-5k2WKj!(QHQ? z8{XcaCj&j*pTb9bUg#mIkp+Bk^A}UkHTHR_;fiJ`wy-Vy@Ttr=^p5NAZgGmSVtkBi z2OPYX26fMDL z{P*_gA{oMW9@(k$YH+zSAe#h+Fn!HxWKs?)_X~%`6Ox3^#V!i?@!1$HWJ>nvGT!5D z;sc^4AK0XQzmQXDeZ!JTcBt@_H#gl;BrgeJ-|e zcm#^|iV2m)A*>kAQ9&k^*w_4i<>k+`;qO3*P|~reK?XO$#R7&c$mOh6Uo*A#4DcLY zM9c~BH(aAj1&x_0`pgOxgH1UHu~e3PMl1fBj7?2(y(_nV%Nx?M=mrtcejS8#t(ygX z00>%Y3lY*-RphQNtJ?|y?NdLtsrzVt5or+qXDNL2$ViWS;I`l*pJ2GUQ40GOqRFkT zz%&>2viotWZ8j}l_}hkh$(W518CNYogtM`jVe#Q@#FBxF@((6{D`lk~@h$*3Ua}OE zst4mQy_z(Y>eGNgd)FZDw7-t%>8hM4hly#98N-BmM+IY=a2uv%sc}$y?m|kxA{^j# z)K^5!t!Np#5SfNMnX{Lz>$_d!Y-?@qmptWF-p+&NyZ!Il$tEy)&wY<4NF&I4#TCX$ zFv~U2^a9}?%b0!*lH+7Hu~Ay6K>Y2w70{0I3>%j-u?#xk&$;FD5k-KfPu_n}U{Tw- zF3+fsQ0eZ zYTo9)z;A7xLfJ73PIP=U4&xe}AWt;l0W%Uc`I0n!vBr3Q&xpNY5cb^H>NC?h#yZ>qIaW(Bop_vNslYDfD1 ze$X=h<5?FKOLU+|8M16~wnj=r81J(=37I!oA16i7;IHjx_~ho|rt_3LTdV<*fgX%W;#--%Vo?=#7;$`h))FZi~(}^!Wvg75K@5FD)b9D#>LrSNTg9sB} zts!|oa%7w5ncG|q;nQL(4@Vdnd|urvg-b-fvHT+m7}pVAzH4@)yYV&%ZEzseB57u? z!Ex?1MGS7=V3?MTp_Da26MIoW5keiQdx!|t(v|PU&KzH+j6nsJwQTQGa9|XNNO72{ zCyvBLt8;q!mm(yv8_XpBr~At9x7Z@jq|l~aA*eXYu2rv8Xh%nAQx}e73lJ&?zeAb% zb9q0*tF{N?UZa^p-0F*pB7~-Z`21{LFbl1z?Jmfi%U>(hJTxD+P(BOMdk1V851o7k z=v)c~N>9lnmF8H9@MEOB7^+w(uU_PtoUKgiuaXC1aqVhm?HO%2mUw=>vLs}!znlv? z#3Px)6VNt$v%^{qH7g$*eXqGAM;}teW&qJ-F7qrafpRy!%=$lVy=79;6bm z5)>hFy01!C`wHAvmm_D!_&6p#El9auX~J*wE@8j>=YU$wlzc6UUQ=FJRo?=Bjh>!5%|44*%uWo4eQjEQJ;4olSdd2x79g zc=hs8YU|*bQL9QlbM{wiP<4@27J)P@CqI%G@b;_HM{RpnIicC;?z{!^}=e5h~ zdjk_IdBa4Z|7KB3P#edS4lF^(8)3AZ0{a14XRF-8f&oQdYY#xOx)tw!4Qq4BeWQQ2 z5R7PMBgOB}h?hkZ{n@4k(FYe9m7~sakZdl2r9i!R-o2-Mazf@Vs zpZ;VwyBQHhlO2eKLZzgtn(qmuO^%^uz~2*J?;HQEBt|kF39Xmj8F)<%sDfQV;lc-p zj+42u$h7lr{pC5l>VCbOWfs!fu3QY8-fA%pN~%gUHHkvF1;;GSB{9pc{EY{Q*O>L# zM5DAQx&RuAC9ZLY=jY2Cf(10q+}<_YL6{e;&YdK1TX$$D2-G+r1d8Eu4@cD8iST!J zkExtw;Vhc)b~`6YbdS|VP7L6^Q^$m^-@i%zum%t|Eij{Z9aXxj_6lmVgZ8M3EHXse zjp#cEx^IR+)b>Xy*n8xPQ1+Z)ok!A6JmCC}pMW_XAB#mC4UB3fZN&Lg{vB}n9jGx_ zyZM0-sTuWRqqpKS4;b4@I!+!sr?W~!ckrp~x~I1iNMH66yK^B3PB?6-#ascLav5iI z|0HfaS)Da$@?h_rjU1KJOV<{BIx)?!XbCv%wWgUVwPU#noVnOqUzEc@xH+Ye{8W3_ zJA`m+AZ-oKR57?+_2=y6Xv5LL2-%;`MUZ7&Fc~DJvjJUxp4?Ng2=RAxYkG$}MoN{c z%yOPupjh)z*oVpE;f(Bl{4%(j!_IcWUJ7>Rw&3sq+VNv;KnE%0ARD|WAUa-^)bZn# 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%0Dmda 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 literal 0 HcmV?d00001 diff --git a/test/pigz/CMakeLists.txt b/test/pigz/CMakeLists.txt index a9298201eb..5be719bbba 100644 --- a/test/pigz/CMakeLists.txt +++ b/test/pigz/CMakeLists.txt @@ -172,6 +172,10 @@ if(PIGZ_ENABLE_TESTS) test_pigz(${TEST_NAME} ${TEST_FILE_PATH} ${TEST_CONFIG}) endforeach() endforeach() + + set(GH979_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ + -d -k -f ${CMAKE_CURRENT_SOURCE_DIR}/../GH-979/pigz-2.6.tar.gz) + add_test(NAME GH-979 COMMAND ${GH979_COMMAND}) endif() add_feature_info(WITH_CODE_COVERAGE WITH_CODE_COVERAGE "Enable code coverage reporting") From c58d99581242e83390d049b361fdb5ed69724cad Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 4 Jun 2021 08:01:30 -0700 Subject: [PATCH 042/798] Added pigz tests for no threads and no optimizations. --- .github/workflows/pigz.yml | 16 ++++++++++ test/pigz/CMakeLists.txt | 60 +++++++++++++++++++++++--------------- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 5b1a335d5b..92f9ee6df7 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -20,6 +20,22 @@ jobs: gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_pigz + - name: Ubuntu Clang No Optim + os: ubuntu-latest + compiler: clang + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov + codecov: ubuntu_clang_pigz_no_optim + cmake-args: -DWITH_OPTIM=OFF + + - name: Ubuntu Clang No Threads + os: ubuntu-latest + compiler: clang + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov + codecov: ubuntu_clang_pigz_no_threads + cmake-args: -DWITH_THREADS=OFF + steps: - name: Checkout repository uses: actions/checkout@v2 diff --git a/test/pigz/CMakeLists.txt b/test/pigz/CMakeLists.txt index 5be719bbba..6038e6cb53 100644 --- a/test/pigz/CMakeLists.txt +++ b/test/pigz/CMakeLists.txt @@ -7,6 +7,8 @@ # pthread libraries if installed. # Optional Variables +# WITH_CODE_COVERAGE - Enable code coverage reporting +# WITH_THREADS - Enable threading support # PIGZ_ENABLE_TESTS - Enable adding unit tests # ZLIB_ROOT - Path to the zlib source directory # PTHREADS4W_ROOT - Path to pthreads4w source directory on Windows. @@ -21,6 +23,7 @@ include(FetchContent) include(../../cmake/detect-coverage.cmake) option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF) +option(WITH_THREADS "Enable threading support" ON) option(PIGZ_ENABLE_TESTS "Build unit tests" ON) project(pigz LANGUAGES C) @@ -40,8 +43,11 @@ elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.8.0) add_definitions(-fno-diagnostics-show-caret) endif() -elseif(MSVC) - add_definitions(-D_CRT_SECURE_NO_DEPRECATE) +elseif(WIN32) + add_definitions(-D_TIMESPEC_DEFINED) + if(MSVC) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + endif() endif() # Fetch pigz source code from official repository @@ -56,37 +62,44 @@ endif() set(PIGZ_SRCS ${pigz_SOURCE_DIR}/pigz.c - ${pigz_SOURCE_DIR}/try.c - ${pigz_SOURCE_DIR}/yarn.c) + ${pigz_SOURCE_DIR}/try.c) set(PIGZ_HDRS - ${pigz_SOURCE_DIR}/try.h - ${pigz_SOURCE_DIR}/yarn.h) + ${pigz_SOURCE_DIR}/try.h) add_executable(${PROJECT_NAME} ${PIGZ_SRCS} ${PIGZ_HDRS}) add_definitions(-DNOZOPFLI) # Find and link against pthreads or pthreads4w -if(WIN32) - add_definitions(-D_TIMESPEC_DEFINED) - - if(DEFINED PTHREADS4W_ROOT) - set(CLEANUP_STYLE VC) - set(PTHREADS4W_VERSION 3) - - add_subdirectory(${PTHREADS4W_ROOT} ${PTHREADS4W_ROOT} EXCLUDE_FROM_ALL) - target_link_libraries(${PROJECT_NAME} pthreadVC3) - target_include_directories(${PROJECT_NAME} PRIVATE win ${PTHREADS4W_ROOT}) +if(WITH_THREADS) + if(WIN32) + if(DEFINED PTHREADS4W_ROOT) + set(CLEANUP_STYLE VC) + set(PTHREADS4W_VERSION 3) + + add_subdirectory(${PTHREADS4W_ROOT} ${PTHREADS4W_ROOT} EXCLUDE_FROM_ALL) + target_link_libraries(${PROJECT_NAME} pthreadVC3) + target_include_directories(${PROJECT_NAME} PRIVATE win ${PTHREADS4W_ROOT}) + else() + message(WARNING "Missing pthreads4w root directory") + set(WITH_THREADS OFF) + endif() else() - message(WARNING "Missing pthreads4w root directory, disabling threading") - add_definitions(-DNOTHREAD) + find_package(Threads REQUIRED) + target_link_libraries(${PROJECT_NAME} Threads::Threads) + if(NOT APPLE) + target_link_libraries(${PROJECT_NAME} m) + endif() endif() +endif() + +# Disable threading support +if(NOT WITH_THREADS) + add_definitions(-DNOTHREAD) else() - find_package(Threads REQUIRED) - target_link_libraries(${PROJECT_NAME} Threads::Threads) - if(NOT APPLE) - target_link_libraries(${PROJECT_NAME} m) - endif() + set_property(TARGET ${PROJECT_NAME} APPEND PROPERTY SOURCES + ${pigz_SOURCE_DIR}/yarn.c + ${pigz_SOURCE_DIR}/yarn.h) endif() # Find and link against zlib @@ -179,6 +192,7 @@ if(PIGZ_ENABLE_TESTS) endif() add_feature_info(WITH_CODE_COVERAGE WITH_CODE_COVERAGE "Enable code coverage reporting") +add_feature_info(WITH_THREADS WITH_THREADS "Enable threading support") add_feature_info(PIGZ_ENABLE_TESTS PIGZ_ENABLE_TESTS "Build unit tests") FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) From 4a0907e3f7684055426b1d52a6431ec4d3f5c256 Mon Sep 17 00:00:00 2001 From: Ilya Kurdyukov <59548320+ilyakurdyukov@users.noreply.github.com> Date: Wed, 9 Jun 2021 19:19:50 +0700 Subject: [PATCH 043/798] fix: SSE42CMPSTR compiled even if WITH_SSE4=OFF --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a9b51438a6..d7f8924441 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -789,7 +789,7 @@ if(WITH_OPTIM) add_definitions(-DX86_SSE42_CRC_INTRIN) endif() endif() - if(HAVE_SSE42CMPSTR_INTRIN) + if(WITH_SSE4 AND HAVE_SSE42CMPSTR_INTRIN) add_definitions(-DX86_SSE42_CMP_STR) set(SSE42_SRCS ${ARCHDIR}/compare258_sse.c) add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE4FLAG}\"") From 5cfb7f15e32bc16ec4cca82b9c094bb886456e4c Mon Sep 17 00:00:00 2001 From: Ilya Kurdyukov <59548320+ilyakurdyukov@users.noreply.github.com> Date: Wed, 9 Jun 2021 19:27:24 +0700 Subject: [PATCH 044/798] fix: unterminated #elif in detect-arch.c ``` $ gcc detect-arch.c detect-arch.c:8:6: error: #error archfound x86_64 #error archfound x86_64 ^~~~~ detect-arch.c:7:0: error: unterminated #elif #if defined(__x86_64__) || defined(_M_X64) ``` --- cmake/detect-arch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/detect-arch.c b/cmake/detect-arch.c index c8bad4beda..8cae4eb668 100644 --- a/cmake/detect-arch.c +++ b/cmake/detect-arch.c @@ -99,6 +99,7 @@ #error archfound riscv64 #elif __riscv_xlen == 32 #error archfound riscv32 + #endif // return 'unrecognized' if we do not know what architecture this is #else From ce4409c1241a60c7ba5807530adf4a795ff87afe Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 9 Jun 2021 19:15:12 +0300 Subject: [PATCH 045/798] [CHUNKCOPY_SAFE] Fix off-by-one error * When chunk size was more than 8 bytes, the comparison logic failed if safe length was one less than chunk size. --- chunkset_tpl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 9e8ede5591..68b7dedeee 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -37,7 +37,8 @@ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { /* Behave like chunkcopy, but avoid writing beyond of legal output. */ Z_INTERNAL uint8_t* CHUNKCOPY_SAFE(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe) { - if ((safe - out) < (ptrdiff_t)sizeof(chunk_t)) { + len = MIN(len, safe - out + 1); + if (len < sizeof(chunk_t)) { int32_t use_chunk16 = sizeof(chunk_t) > 16 && (len & 16); if (use_chunk16) { memcpy(out, from, 16); From 91599b37e533359a1027d1b6b2be8ed2745145f1 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 9 Jun 2021 19:15:52 +0300 Subject: [PATCH 046/798] [inflate_fast] Always use safe versions of chunkcopy and chunkmemset to avoid errors with optimizations enabled. --- inffast.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/inffast.c b/inffast.c index 18ce570e9c..c8d3da3410 100644 --- a/inffast.c +++ b/inffast.c @@ -260,15 +260,11 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { out = functable.chunkcopy_safe(out, from, len, safe); } } else { - /* Whole reference is in range of current output. No range checks are - necessary because we start with room for at least 258 bytes of output, - so unroll and roundoff operations can write beyond `out+len` so long - as they stay within 258 bytes of `out`. - */ + /* Whole reference is in range of current output. */ if (dist >= len || dist >= state->chunksize) - out = functable.chunkcopy(out, out - dist, len); + out = functable.chunkcopy_safe(out, out - dist, len, safe); else - out = functable.chunkmemset(out, dist, len); + out = functable.chunkmemset_safe(out, dist, len, safe - out + 1); } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode + here->val + BITS(op); From 4af20eae037a91cf4c47dd07619891d3261f6227 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 10 Jun 2021 18:23:34 +0300 Subject: [PATCH 047/798] [CHUNKMEMSET_SAFE] Precalculate "from". * limit len to minimum of len and left --- chunkset_tpl.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 68b7dedeee..96f08d118e 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -161,10 +161,11 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { } Z_INTERNAL uint8_t* CHUNKMEMSET_SAFE(uint8_t *out, unsigned dist, unsigned len, unsigned left) { + len = MIN(len, left); if (left < (unsigned)(3 * sizeof(chunk_t))) { + uint8_t *from = out - dist; while (len > 0) { - *out = *(out - dist); - out++; + *out++ = *from++; --len; } return out; From 558192b4a6f9c8142a0e17ff3c4574a20a2dc96f Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 11 Jun 2021 12:44:06 +0200 Subject: [PATCH 048/798] Version 2.0.4 - Fix inflate corruption #982 - Minor code cleanup #983 #984 - Fix mpicc compilation #959 - Fix build on NetBSD #964 - Fix build on OpenBSD #970 - Fix build on Cygwin #972 #974 - Fix linter warnings in configure #975 - Spelling fixes #961 - Improve unistd.h handling #960 - Remove stdarg.h detection #976 - CI/Test improvements #977 #981 #985 - Cmake improvements #980 #989 --- Makefile.in | 2 +- zlib-ng.h | 6 +++--- zlib.h | 6 +++--- zutil.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile.in b/Makefile.in index 68e921774c..0dd656d644 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.0.3 +VER=2.0.4 VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/zlib-ng.h b/zlib-ng.h index b506faddc6..2a078385fc 100644 --- a/zlib-ng.h +++ b/zlib-ng.h @@ -44,11 +44,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.0.3" -#define ZLIBNG_VERNUM 0x2030 +#define ZLIBNG_VERSION "2.0.4" +#define ZLIBNG_VERNUM 0x2040 #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 0 -#define ZLIBNG_VER_REVISION 3 +#define ZLIBNG_VER_REVISION 4 #define ZLIBNG_VER_SUBREVISION 0 /* diff --git a/zlib.h b/zlib.h index ee5edde6fd..0b44342337 100644 --- a/zlib.h +++ b/zlib.h @@ -46,11 +46,11 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.0.3" -#define ZLIBNG_VERNUM 0x2030 +#define ZLIBNG_VERSION "2.0.4" +#define ZLIBNG_VERNUM 0x2040 #define ZLIBNG_VER_MAJOR 2 #define ZLIBNG_VER_MINOR 0 -#define ZLIBNG_VER_REVISION 3 +#define ZLIBNG_VER_REVISION 4 #define ZLIBNG_VER_SUBREVISION 0 #define ZLIB_VERSION "1.2.11.zlib-ng" diff --git a/zutil.c b/zutil.c index a01150ad0a..b38dc45a91 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char zlibng_string[] = - " zlib-ng 2.0.3 forked from zlib"; + " zlib-ng 2.0.4 forked from zlib"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From 74436cfb05b0d6bd1acff4e8e57204cb176d738e Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 20 May 2021 20:51:51 +0200 Subject: [PATCH 049/798] Open up develop branch for non-stable commits. Replace ZLIBNG_VERNUM with a larger one with space for more accurate information. Replace ZLIBNG_VER_SUBREVISION with ZLIBNG_VER_MODIFIED and ZLIBNG_VER_STATUS. --- Makefile.in | 2 +- test/example.c | 4 ++-- zlib-ng.h | 11 ++++++----- zlib.h | 11 ++++++----- zutil.c | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Makefile.in b/Makefile.in index 0dd656d644..28d637470e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -29,7 +29,7 @@ TEST_LIBS=$(LIBNAME1).a LDSHARED=$(CC) LDSHAREDFLAGS=-shared -VER=2.0.4 +VER=2.1.0.devel VER1=2 STATICLIB=$(LIBNAME1).a diff --git a/test/example.c b/test/example.c index 97ca0029b9..8a8905dd5b 100644 --- a/test/example.c +++ b/test/example.c @@ -1016,8 +1016,8 @@ int main(int argc, char *argv[]) { fprintf(stderr, "warning: different zlib version\n"); } - printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", - PREFIX2(VERSION), PREFIX2(VERNUM), PREFIX(zlibCompileFlags)()); + printf("zlib-ng version %s = 0x%08lx, compile flags = 0x%lx\n", + ZLIBNG_VERSION, ZLIBNG_VERNUM, PREFIX(zlibCompileFlags)()); compr = (unsigned char*)calloc((unsigned int)comprLen, 1); uncompr = (unsigned char*)calloc((unsigned int)uncomprLen, 1); diff --git a/zlib-ng.h b/zlib-ng.h index 2a078385fc..36750cf1d7 100644 --- a/zlib-ng.h +++ b/zlib-ng.h @@ -44,12 +44,13 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.0.4" -#define ZLIBNG_VERNUM 0x2040 +#define ZLIBNG_VERSION "2.1.0.devel" +#define ZLIBNG_VERNUM 0x02010000L /* MMNNRRMS: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 -#define ZLIBNG_VER_MINOR 0 -#define ZLIBNG_VER_REVISION 4 -#define ZLIBNG_VER_SUBREVISION 0 +#define ZLIBNG_VER_MINOR 1 +#define ZLIBNG_VER_REVISION 0 +#define ZLIBNG_VER_STATUS 0 /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ /* The 'zlib' compression library provides in-memory compression and diff --git a/zlib.h b/zlib.h index 0b44342337..6852dc67bc 100644 --- a/zlib.h +++ b/zlib.h @@ -46,12 +46,13 @@ extern "C" { #endif -#define ZLIBNG_VERSION "2.0.4" -#define ZLIBNG_VERNUM 0x2040 +#define ZLIBNG_VERSION "2.1.0.devel" +#define ZLIBNG_VERNUM 0x02010000L /* MMNNRRMS: major minor revision status modified */ #define ZLIBNG_VER_MAJOR 2 -#define ZLIBNG_VER_MINOR 0 -#define ZLIBNG_VER_REVISION 4 -#define ZLIBNG_VER_SUBREVISION 0 +#define ZLIBNG_VER_MINOR 1 +#define ZLIBNG_VER_REVISION 0 +#define ZLIBNG_VER_STATUS 0 /* 0=devel, 1-E=beta, F=Release */ +#define ZLIBNG_VER_MODIFIED 0 /* non-zero if modified externally from zlib-ng */ #define ZLIB_VERSION "1.2.11.zlib-ng" #define ZLIB_VERNUM 0x12bf diff --git a/zutil.c b/zutil.c index b38dc45a91..74d7524353 100644 --- a/zutil.c +++ b/zutil.c @@ -21,7 +21,7 @@ z_const char * const PREFIX(z_errmsg)[10] = { }; const char zlibng_string[] = - " zlib-ng 2.0.4 forked from zlib"; + " zlib-ng 2.1.0.devel forked from zlib"; #ifdef ZLIB_COMPAT const char * Z_EXPORT zlibVersion(void) { From 2e37971ec0bb4775c041336ce16cbd7a718e8005 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 17 Feb 2021 19:29:46 -0800 Subject: [PATCH 050/798] Sync changes between different slide_hash variants. --- arch/arm/slide_neon.c | 8 +++--- arch/power/slide_hash_power8.c | 38 +++++++++++-------------- arch/x86/slide_avx.c | 38 ++++++++++--------------- arch/x86/slide_sse.c | 38 ++++++++++--------------- deflate.c | 52 +++++++++++----------------------- 5 files changed, 68 insertions(+), 106 deletions(-) diff --git a/arch/arm/slide_neon.c b/arch/arm/slide_neon.c index f64fa5b5b4..81461391c0 100644 --- a/arch/arm/slide_neon.c +++ b/arch/arm/slide_neon.c @@ -18,7 +18,7 @@ #include "../../deflate.h" /* SIMD version of hash_chain rebase */ -static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t window_size) { +static inline void slide_hash_neon_chain(Pos *table, uint32_t entries, uint16_t wsize) { Z_REGISTER uint16x8_t v, *p; Z_REGISTER size_t n; @@ -26,7 +26,7 @@ static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t w Assert((size % sizeof(uint16x8_t) * 8 == 0), "hash table size err"); Assert(sizeof(Pos) == 2, "Wrong Pos size"); - v = vdupq_n_u16(window_size); + v = vdupq_n_u16(wsize); p = (uint16x8_t *)table; n = size / (sizeof(uint16x8_t) * 8); @@ -46,7 +46,7 @@ static inline void slide_hash_chain(Pos *table, unsigned int entries, uint16_t w Z_INTERNAL void slide_hash_neon(deflate_state *s) { unsigned int wsize = s->w_size; - slide_hash_chain(s->head, HASH_SIZE, wsize); - slide_hash_chain(s->prev, wsize, wsize); + slide_hash_neon_chain(s->head, HASH_SIZE, wsize); + slide_hash_neon_chain(s->prev, wsize, wsize); } #endif diff --git a/arch/power/slide_hash_power8.c b/arch/power/slide_hash_power8.c index b1e30cea09..112561939e 100644 --- a/arch/power/slide_hash_power8.c +++ b/arch/power/slide_hash_power8.c @@ -10,51 +10,47 @@ #include "zbuild.h" #include "deflate.h" -static inline void slide_hash_power8_loop(deflate_state *s, unsigned n_elems, Pos *table_end) { +static inline void slide_hash_power8_chain(Pos *table, uint32_t entries, uint16_t wsize) { vector unsigned short vw, vm, *vp; unsigned chunks; + table += entries; + /* Each vector register (chunk) corresponds to 128 bits == 8 Posf, - * so instead of processing each of the n_elems in the hash table + * so instead of processing each of the entries in the hash table * individually, we can do it in chunks of 8 with vector instructions. * * This function is only called from slide_hash_power8(), and both calls - * pass n_elems as a power of 2 higher than 2^7, as defined by - * deflateInit2_(), so n_elems will always be a multiple of 8. */ - chunks = n_elems >> 3; - Assert(n_elems % 8 == 0, "Weird hash table size!"); + * pass entries as a power of 2 higher than 2^7, as defined by + * deflateInit2_(), so entries will always be a multiple of 8. */ + chunks = entries >> 3; + Assert(entries % 8 == 0, "Weird hash table size!"); - /* This type casting is safe since s->w_size is always <= 64KB + /* This type casting is safe since wsize is always <= 64KB * as defined by deflateInit2_() and Posf == unsigned short */ - vw[0] = (Pos) s->w_size; + vw[0] = wsize; vw = vec_splat(vw,0); - vp = (vector unsigned short *) table_end; + vp = (vector unsigned short *)table; do { /* Processing 8 elements at a time */ vp--; vm = *vp; - /* This is equivalent to: m >= w_size ? m - w_size : 0 + /* This is equivalent to: m >= wsize ? m - wsize : 0 * Since we are using a saturated unsigned subtraction, any - * values that are > w_size will be set to 0, while the others - * will be subtracted by w_size. */ + * values that are > wsize will be set to 0, while the others + * will be subtracted by wsize. */ *vp = vec_subs(vm,vw); } while (--chunks); } void Z_INTERNAL slide_hash_power8(deflate_state *s) { - unsigned int n; - Pos *p; - - n = HASH_SIZE; - p = &s->head[n]; - slide_hash_power8_loop(s,n,p); + uint16_t wsize = s->w_size; - n = s->w_size; - p = &s->prev[n]; - slide_hash_power8_loop(s,n,p); + slide_hash_power8_chain(s->head, HASH_SIZE, wsize); + slide_hash_power8_chain(s->prev, wsize, wsize); } #endif /* POWER8_VSX_SLIDEHASH */ diff --git a/arch/x86/slide_avx.c b/arch/x86/slide_avx.c index be9a9b7ea2..01c788df1c 100644 --- a/arch/x86/slide_avx.c +++ b/arch/x86/slide_avx.c @@ -14,34 +14,26 @@ #include -Z_INTERNAL void slide_hash_avx2(deflate_state *s) { - Pos *p; - unsigned n; - uint16_t wsize = (uint16_t)s->w_size; - const __m256i ymm_wsize = _mm256_set1_epi16((short)wsize); +static inline void slide_hash_avx2_chain(Pos *table, uint32_t entries, const __m256i wsize) { + table += entries; + table -= 16; - n = HASH_SIZE; - p = &s->head[n] - 16; do { __m256i value, result; - value = _mm256_loadu_si256((__m256i *)p); - result= _mm256_subs_epu16(value, ymm_wsize); - _mm256_storeu_si256((__m256i *)p, result); - p -= 16; - n -= 16; - } while (n > 0); + value = _mm256_loadu_si256((__m256i *)table); + result = _mm256_subs_epu16(value, wsize); + _mm256_storeu_si256((__m256i *)table, result); - n = wsize; - p = &s->prev[n] - 16; - do { - __m256i value, result; + table -= 16; + entries -= 16; + } while (entries > 0); +} - value = _mm256_loadu_si256((__m256i *)p); - result= _mm256_subs_epu16(value, ymm_wsize); - _mm256_storeu_si256((__m256i *)p, result); +Z_INTERNAL void slide_hash_avx2(deflate_state *s) { + uint16_t wsize = (uint16_t)s->w_size; + const __m256i ymm_wsize = _mm256_set1_epi16((short)wsize); - p -= 16; - n -= 16; - } while (n > 0); + slide_hash_avx2_chain(s->head, HASH_SIZE, ymm_wsize); + slide_hash_avx2_chain(s->prev, wsize, ymm_wsize); } diff --git a/arch/x86/slide_sse.c b/arch/x86/slide_sse.c index abf4474752..65d58a71eb 100644 --- a/arch/x86/slide_sse.c +++ b/arch/x86/slide_sse.c @@ -13,34 +13,26 @@ #include -Z_INTERNAL void slide_hash_sse2(deflate_state *s) { - Pos *p; - unsigned n; - uint16_t wsize = (uint16_t)s->w_size; - const __m128i xmm_wsize = _mm_set1_epi16((short)wsize); +static inline void slide_hash_sse2_chain(Pos *table, uint32_t entries, const __m128i wsize) { + table += entries; + table -= 8; - n = HASH_SIZE; - p = &s->head[n] - 8; do { __m128i value, result; - value = _mm_loadu_si128((__m128i *)p); - result= _mm_subs_epu16(value, xmm_wsize); - _mm_storeu_si128((__m128i *)p, result); - p -= 8; - n -= 8; - } while (n > 0); + value = _mm_loadu_si128((__m128i *)table); + result= _mm_subs_epu16(value, wsize); + _mm_storeu_si128((__m128i *)table, result); - n = wsize; - p = &s->prev[n] - 8; - do { - __m128i value, result; + table -= 8; + entries -= 8; + } while (entries > 0); +} - value = _mm_loadu_si128((__m128i *)p); - result= _mm_subs_epu16(value, xmm_wsize); - _mm_storeu_si128((__m128i *)p, result); +Z_INTERNAL void slide_hash_sse2(deflate_state *s) { + uint16_t wsize = (uint16_t)s->w_size; + const __m128i xmm_wsize = _mm_set1_epi16((short)wsize); - p -= 8; - n -= 8; - } while (n > 0); + slide_hash_sse2_chain(s->head, HASH_SIZE, xmm_wsize); + slide_hash_sse2_chain(s->prev, wsize, xmm_wsize); } diff --git a/deflate.c b/deflate.c index ca9dafa8db..2aae899be1 100644 --- a/deflate.c +++ b/deflate.c @@ -188,20 +188,19 @@ static const config configuration_table[10] = { * 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. */ -Z_INTERNAL void slide_hash_c(deflate_state *s) { - Pos *p; - unsigned n; - unsigned int wsize = s->w_size; - - n = HASH_SIZE; - p = &s->head[n]; +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 = *--p; - *p = (Pos)(m >= wsize ? m-wsize : 0); - } while (--n); + 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 @@ -210,40 +209,23 @@ Z_INTERNAL void slide_hash_c(deflate_state *s) { * choose type "Pos" (instead of 'unsigned int') for the * variable to avoid unnecessary zero-extension. */ - { unsigned int i; - Pos *q = p - n; - for (i = 0; i < n; 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 */ +} - n = wsize; - p = &s->prev[n]; -#ifdef NOT_TWEAK_COMPILER - do { - unsigned m; - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : 0); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#else - { - unsigned int i; - Pos *q = p - n; - for (i = 0; i < n; i++) { - Pos m = *q; - Pos t = (Pos)wsize; - *q++ = (Pos)(m >= t ? m-t: 0); +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); } - } -#endif /* NOT_TWEAK_COMPILER */ -} /* ========================================================================= */ int32_t Z_EXPORT PREFIX(deflateInit_)(PREFIX3(stream) *strm, int32_t level, const char *version, int32_t stream_size) { From b739f0f170109cb00228186790a90df9066c5cac Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 17 Feb 2021 19:39:00 -0800 Subject: [PATCH 051/798] Fixed formatting for CLEAR_HASH macro. --- deflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deflate.c b/deflate.c index 2aae899be1..5656e3aba2 100644 --- a/deflate.c +++ b/deflate.c @@ -179,7 +179,7 @@ static const config configuration_table[10] = { /* =========================================================================== * Initialize the hash table. prev[] will be initialized on the fly. */ -#define CLEAR_HASH(s) do { \ +#define CLEAR_HASH(s) do { \ memset((unsigned char *)s->head, 0, HASH_SIZE * sizeof(*s->head)); \ } while (0) From 06ee8421456ead3d7c1a2488e6f594749eca09a4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 24 Feb 2021 16:50:46 -0800 Subject: [PATCH 052/798] Rename slide_hash chain functions. --- arch/arm/slide_neon.c | 6 +++--- arch/power/slide_hash_power8.c | 6 +++--- arch/x86/slide_avx.c | 6 +++--- arch/x86/slide_sse.c | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/arm/slide_neon.c b/arch/arm/slide_neon.c index 81461391c0..87b5397647 100644 --- a/arch/arm/slide_neon.c +++ b/arch/arm/slide_neon.c @@ -18,7 +18,7 @@ #include "../../deflate.h" /* SIMD version of hash_chain rebase */ -static inline void slide_hash_neon_chain(Pos *table, uint32_t entries, uint16_t wsize) { +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { Z_REGISTER uint16x8_t v, *p; Z_REGISTER size_t n; @@ -46,7 +46,7 @@ static inline void slide_hash_neon_chain(Pos *table, uint32_t entries, uint16_t Z_INTERNAL void slide_hash_neon(deflate_state *s) { unsigned int wsize = s->w_size; - slide_hash_neon_chain(s->head, HASH_SIZE, wsize); - slide_hash_neon_chain(s->prev, wsize, wsize); + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); } #endif diff --git a/arch/power/slide_hash_power8.c b/arch/power/slide_hash_power8.c index 112561939e..c0083aad67 100644 --- a/arch/power/slide_hash_power8.c +++ b/arch/power/slide_hash_power8.c @@ -10,7 +10,7 @@ #include "zbuild.h" #include "deflate.h" -static inline void slide_hash_power8_chain(Pos *table, uint32_t entries, uint16_t wsize) { +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { vector unsigned short vw, vm, *vp; unsigned chunks; @@ -49,8 +49,8 @@ static inline void slide_hash_power8_chain(Pos *table, uint32_t entries, uint16_ void Z_INTERNAL slide_hash_power8(deflate_state *s) { uint16_t wsize = s->w_size; - slide_hash_power8_chain(s->head, HASH_SIZE, wsize); - slide_hash_power8_chain(s->prev, wsize, wsize); + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); } #endif /* POWER8_VSX_SLIDEHASH */ diff --git a/arch/x86/slide_avx.c b/arch/x86/slide_avx.c index 01c788df1c..94fe10c7bf 100644 --- a/arch/x86/slide_avx.c +++ b/arch/x86/slide_avx.c @@ -14,7 +14,7 @@ #include -static inline void slide_hash_avx2_chain(Pos *table, uint32_t entries, const __m256i wsize) { +static inline void slide_hash_chain(Pos *table, uint32_t entries, const __m256i wsize) { table += entries; table -= 16; @@ -34,6 +34,6 @@ Z_INTERNAL void slide_hash_avx2(deflate_state *s) { uint16_t wsize = (uint16_t)s->w_size; const __m256i ymm_wsize = _mm256_set1_epi16((short)wsize); - slide_hash_avx2_chain(s->head, HASH_SIZE, ymm_wsize); - slide_hash_avx2_chain(s->prev, wsize, ymm_wsize); + slide_hash_chain(s->head, HASH_SIZE, ymm_wsize); + slide_hash_chain(s->prev, wsize, ymm_wsize); } diff --git a/arch/x86/slide_sse.c b/arch/x86/slide_sse.c index 65d58a71eb..7507c68b12 100644 --- a/arch/x86/slide_sse.c +++ b/arch/x86/slide_sse.c @@ -13,7 +13,7 @@ #include -static inline void slide_hash_sse2_chain(Pos *table, uint32_t entries, const __m128i wsize) { +static inline void slide_hash_chain(Pos *table, uint32_t entries, const __m128i wsize) { table += entries; table -= 8; @@ -33,6 +33,6 @@ Z_INTERNAL void slide_hash_sse2(deflate_state *s) { uint16_t wsize = (uint16_t)s->w_size; const __m128i xmm_wsize = _mm_set1_epi16((short)wsize); - slide_hash_sse2_chain(s->head, HASH_SIZE, xmm_wsize); - slide_hash_sse2_chain(s->prev, wsize, xmm_wsize); + slide_hash_chain(s->head, HASH_SIZE, xmm_wsize); + slide_hash_chain(s->prev, wsize, xmm_wsize); } From 3e053d061879e2b56c9395aeea277412033ff1a8 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 24 Feb 2021 16:52:07 -0800 Subject: [PATCH 053/798] Rename slide_hash_power8.c to slide_power8.c to be consistent with other slide hash variants. --- CMakeLists.txt | 2 +- arch/power/Makefile.in | 12 ++++++------ arch/power/{slide_hash_power8.c => slide_power8.c} | 0 configure | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) rename arch/power/{slide_hash_power8.c => slide_power8.c} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7f8924441..e45bdc84e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -742,7 +742,7 @@ if(WITH_OPTIM) add_definitions(-DPOWER8_VSX_SLIDEHASH) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) - set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/slide_hash_power8.c) + set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/slide_power8.c) list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") endif() diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index cf5839b934..e7a2473a39 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -19,8 +19,8 @@ all: power.o \ power.lo \ adler32_power8.o \ adler32_power8.lo \ - slide_hash_power8.o \ - slide_hash_power8.lo + slide_power8.o \ + slide_power8.lo power.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power.c @@ -34,11 +34,11 @@ adler32_power8.o: adler32_power8.lo: $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c -slide_hash_power8.o: - $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c +slide_power8.o: + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_power8.c -slide_hash_power8.lo: - $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c +slide_power8.lo: + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_power8.c mostlyclean: clean clean: diff --git a/arch/power/slide_hash_power8.c b/arch/power/slide_power8.c similarity index 100% rename from arch/power/slide_hash_power8.c rename to arch/power/slide_power8.c diff --git a/configure b/configure index 353cad4d80..339e8fd8c9 100755 --- a/configure +++ b/configure @@ -1531,8 +1531,8 @@ EOF CFLAGS="${CFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_SLIDEHASH" SFLAGS="${SFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o adler32_power8.o slide_hash_power8.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo adler32_power8.lo slide_hash_power8.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o adler32_power8.o slide_power8.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo adler32_power8.lo slide_power8.lo" fi fi ;; From 1da723dcf9dc049c36255306ff22999ada703376 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 24 Feb 2021 16:55:37 -0800 Subject: [PATCH 054/798] Remove obsolete comment about wsize casting. --- arch/power/slide_power8.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/power/slide_power8.c b/arch/power/slide_power8.c index c0083aad67..3c78d303ba 100644 --- a/arch/power/slide_power8.c +++ b/arch/power/slide_power8.c @@ -26,8 +26,6 @@ static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize chunks = entries >> 3; Assert(entries % 8 == 0, "Weird hash table size!"); - /* This type casting is safe since wsize is always <= 64KB - * as defined by deflateInit2_() and Posf == unsigned short */ vw[0] = wsize; vw = vec_splat(vw,0); From 525ddbed32186ce20457a432dc19ceef25228852 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 24 Feb 2021 16:59:48 -0800 Subject: [PATCH 055/798] Fixed operator in comment in slide_hash_chain for power8. --- arch/power/slide_power8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/power/slide_power8.c b/arch/power/slide_power8.c index 3c78d303ba..f153057274 100644 --- a/arch/power/slide_power8.c +++ b/arch/power/slide_power8.c @@ -38,7 +38,7 @@ static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize /* This is equivalent to: m >= wsize ? m - wsize : 0 * Since we are using a saturated unsigned subtraction, any - * values that are > wsize will be set to 0, while the others + * values that are <= wsize will be set to 0, while the others * will be subtracted by wsize. */ *vp = vec_subs(vm,vw); } while (--chunks); From b1ad50412f4e3006139bbff8f83481d4a851b82e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 25 Feb 2021 16:46:11 -0800 Subject: [PATCH 056/798] Fixed malformed double quotes in shell script. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 339e8fd8c9..3d527683bf 100755 --- a/configure +++ b/configure @@ -557,7 +557,7 @@ try() ( $* ) >> configure.log 2>&1 ret=$? if test $ret -ne 0; then - echo "(exit code "$ret")" >> configure.log + echo "(exit code $ret)" >> configure.log fi return $ret } From 6eabea7c8804552d27092fa292766e29d4200431 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 25 Feb 2021 17:27:03 -0800 Subject: [PATCH 057/798] Fixed iterating over ls output is fragile in configure script. --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 3d527683bf..cf557844fc 100755 --- a/configure +++ b/configure @@ -1687,7 +1687,7 @@ sed < $SRCDIR/Makefile.in " " > Makefile # Append header files dependences. -for file in $(ls -1 $SRCDIR/*.c $SRCDIR/test/*.c $SRCDIR/test/fuzz/*.c $SRCDIR/$ARCHDIR/*.c $SRCDIR/tools/*.c); do +for file in $SRCDIR/*.c $SRCDIR/test/*.c $SRCDIR/test/fuzz/*.c $SRCDIR/$ARCHDIR/*.c $SRCDIR/tools/*.c; do short_name=$(echo $file | sed -e "s#$SRCDIR/##g") incs=$(grep -h include $file | sed -n 's/# *\include *"\(.*\.h\)".*/\1/p' | sort | uniq) includes=$(for i in $incs; do @@ -1755,7 +1755,7 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " " > $ARCHDIR/Makefile # Append header files dependences. -for file in $(ls -1 $SRCDIR/$ARCHDIR/*.c); do +for file in $SRCDIR/$ARCHDIR/*.c; do incs=$(grep -h include $file | sed -n 's/# *\include *"\(.*\.h\)".*/\1/p' | sort | uniq) includes=$(for i in $incs; do # Check that the include file exists in the current dir, From c475ec95525ac4bbf4838a6943ebd2c88c1fb5a1 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 25 Feb 2021 18:36:36 -0800 Subject: [PATCH 058/798] Remove legacy backticks notation for $(...) in configure script. --- configure | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/configure b/configure index cf557844fc..8cd48786ee 100755 --- a/configure +++ b/configure @@ -29,7 +29,7 @@ if [ -n "${CHOST}" ]; then CROSS_PREFIX="${CHOST}-" ARCH="$(echo "${NORM_CHOST}" | sed -e 's/-.*//')" else - ARCH="`uname -m`" + ARCH="$(uname -m)" fi case "${ARCH}" in @@ -159,12 +159,12 @@ case "$1" in echo ' [--with-fuzzers] Build test/fuzz (disabled by default)' | tee -a configure.log echo ' [--native] Compiles with full instruction set supported on this host' | tee -a configure.log exit 0 ;; - -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;; - -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;; - -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;; - --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;; - -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;; - -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;; + -p*=* | --prefix=*) prefix=$(echo $1 | sed 's/.*=//'); shift ;; + -e*=* | --eprefix=*) exec_prefix=$(echo $1 | sed 's/.*=//'); shift ;; + -l*=* | --libdir=*) libdir=$(echo $1 | sed 's/.*=//'); shift ;; + --sharedlibdir=*) sharedlibdir=$(echo $1 | sed 's/.*=//'); shift ;; + -i*=* | --includedir=*) includedir=$(echo $1 | sed 's/.*=//');shift ;; + -u*=* | --uname=*) uname=$(echo $1 | sed 's/.*=//');shift ;; -p* | --prefix) prefix="$2"; shift; shift ;; -e* | --eprefix) exec_prefix="$2"; shift; shift ;; -l* | --libdir) libdir="$2"; shift; shift ;; @@ -182,14 +182,14 @@ case "$1" in --with-dfltcc-inflate) builddfltccinflate=1; shift ;; --force-sse2) forcesse2=1; shift ;; -n | --native) native=1; shift ;; - -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;; + -a*=* | --archs=*) ARCHS=$(echo $1 | sed 's/.*=//'); shift ;; --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;; -noopt | --without-optimizations) without_optimizations=1; shift;; -oldstrat | --without-new-strategies) without_new_strategies=1; shift;; -w* | --warn) warn=1; shift ;; -d* | --debug) debug=1; shift ;; - --with-sanitizer=*) with_sanitizer=`echo $1 | sed 's/.*=//'`; shift ;; + --with-sanitizer=*) with_sanitizer=$(echo $1 | sed 's/.*=//'); shift ;; --with-fuzzers) with_fuzzers=1; shift ;; *) @@ -226,7 +226,7 @@ case "$cc" in *gcc*) gcc=1 ;; *clang*) gcc=1 ;; esac -case `$cc -v 2>&1` in +case $($cc -v 2>&1) in *gcc*) gcc=1 ;; *clang*) gcc=1 ;; esac @@ -268,15 +268,15 @@ MAPNAME=${LIBNAME2}.map # extract zlib version numbers from zlib.h if test $compat -eq 0; then - VER=`sed -n -e '/ZLIBNG_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib-ng.h` - VER3=`sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib-ng.h` - VER2=`sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib-ng.h` - VER1=`sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib-ng.h` + VER=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib-ng.h) + VER3=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib-ng.h) + VER2=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\.[0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib-ng.h) + VER1=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib-ng.h) else - VER=`sed -n -e '/ZLIB_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib.h` - VER3=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib.h` - VER2=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib.h` - VER1=`sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}/zlib.h` + VER=$(sed -n -e '/ZLIB_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib.h) + VER3=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib.h) + VER2=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\.[0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib.h) + VER1=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib.h) fi show $cc -c $test.c @@ -287,9 +287,9 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then # Re-check ARCH if the compiler is a cross-compiler. if $CC -print-multiarch 1> /dev/null 2>&1 && test -n "$($CC -print-multiarch)" 1> /dev/null 2>&1; then - CC_ARCH=`$CC $CFLAGS -print-multiarch | sed 's/-.*//g'` + CC_ARCH=$($CC $CFLAGS -print-multiarch | sed 's/-.*//g') else - CC_ARCH=`$CC $CFLAGS -dumpmachine | sed 's/-.*//g'` + CC_ARCH=$($CC $CFLAGS -dumpmachine | sed 's/-.*//g') fi case $CC_ARCH in i386 | i486 | i586 | i686) @@ -370,7 +370,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then SFLAGS="${SFLAGS} -DZLIB_DEBUG" fi if test -z "$uname"; then - uname=`(uname -s || echo unknown) 2>/dev/null` + uname=$((uname -s || echo unknown) 2>/dev/null) fi case "$uname" in Linux* | linux* | GNU | GNU/* | solaris*) @@ -458,7 +458,7 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then HP-UX*) LDSHARED=${LDSHARED-"$cc"} LDSHAREDFLAGS="-shared" - case `(uname -m || echo unknown) 2>/dev/null` in + case $((uname -m || echo unknown) 2>/dev/null) in ia64) shared_ext='.so' SHAREDLIB='${LIBNAME}.so' ;; @@ -494,14 +494,14 @@ else gcc=0 echo "$CC" | tee -a configure.log if test -z "$uname"; then - uname=`(uname -sr || echo unknown) 2>/dev/null` + uname=$((uname -sr || echo unknown) 2>/dev/null) fi case "$uname" in HP-UX*) SFLAGS=${CFLAGS-"-O +z"} CFLAGS=${CFLAGS-"-O"} LDSHARED=${LDSHARED-"ld"} LDSHAREDFLAGS="-b" - case `(uname -m || echo unknown) 2>/dev/null` in + case $((uname -m || echo unknown) 2>/dev/null) in ia64) shared_ext='.so' SHAREDLIB='${LIBNAME}.so' ;; @@ -547,7 +547,7 @@ if ($CC -c $CFLAGS $test.c) 2>/dev/null; then try() { show $* - test "`( $* ) 2>&1 | tee -a configure.log`" = "" + test "$(\( $* \) 2>&1 | tee -a configure.log)" = "" } echo - using any output from compiler to indicate an error >> configure.log else @@ -566,7 +566,7 @@ fi tryboth() { show $* - got=`( $* ) 2>&1` + got=$(( $* ) 2>&1) ret=$? printf %s "$got" >> configure.log if test $ret -ne 0; then From 366aa5ac9998f84bf011b8a2f8a4dbde5f7ab55f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 22 Feb 2021 21:43:24 -0800 Subject: [PATCH 059/798] Sync use of adler32_len_16 among adler32 variants. --- arch/power/adler32_power8.c | 2 +- arch/x86/adler32_avx.c | 12 ++---------- arch/x86/adler32_ssse3.c | 12 ++---------- 3 files changed, 5 insertions(+), 21 deletions(-) diff --git a/arch/power/adler32_power8.c b/arch/power/adler32_power8.c index cda51aa807..029aa3a84c 100644 --- a/arch/power/adler32_power8.c +++ b/arch/power/adler32_power8.c @@ -147,7 +147,7 @@ uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len) { s1 = vs1[0] % BASE; s2 = vs2[0] % BASE; - /* Process tail (len < 16).and return */ + /* Process tail (len < 16). */ return adler32_len_16(s1, buf, len, s2); } diff --git a/arch/x86/adler32_avx.c b/arch/x86/adler32_avx.c index 1063246549..3d30d4d783 100644 --- a/arch/x86/adler32_avx.c +++ b/arch/x86/adler32_avx.c @@ -102,16 +102,8 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ s2[7] = sum2; } - while (len) { - len--; - adler += *buf++; - sum2 += adler; - } - adler %= BASE; - sum2 %= BASE; - - /* return recombined sums */ - return adler | (sum2 << 16); + /* Process tail (len < 16). */ + return adler32_len_16(adler, buf, len, sum2); } #endif diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 101df4fe4d..f7587f3da1 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -103,16 +103,8 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size s2[3] = sum2; } - while (len) { - len--; - adler += *buf++; - sum2 += adler; - } - adler %= BASE; - sum2 %= BASE; - - /* return recombined sums */ - return adler | (sum2 << 16); + /* Process tail (len < 16). */ + return adler32_len_16(adler, buf, len, sum2); } #endif From d5419d68ea37cdf7740268188535d811d05bf270 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 28 Feb 2021 18:17:04 -0800 Subject: [PATCH 060/798] Mod adler and sum2 when calculating adler32 for short lengths. --- adler32_p.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/adler32_p.h b/adler32_p.h index 7f75c71e2e..adcc79f01e 100644 --- a/adler32_p.h +++ b/adler32_p.h @@ -20,11 +20,9 @@ static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, uint32_t sum2) { adler += buf[0]; - if (adler >= BASE) - adler -= BASE; + adler %= BASE; sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; + sum2 %= BASE; return adler | (sum2 << 16); } @@ -34,8 +32,7 @@ static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, adler += *buf++; sum2 += adler; } - if (adler >= BASE) - adler -= BASE; + adler %= BASE; sum2 %= BASE; /* only added so many BASE's */ return adler | (sum2 << 16); } From d4f33e1538fbe161241e4fa8c509cd11412b60f4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 20 Mar 2021 09:31:59 -0700 Subject: [PATCH 061/798] Remove extra check that always is false in compare256_c_static. --- compare258.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compare258.c b/compare258.c index bc41638ae8..6b452b89cc 100644 --- a/compare258.c +++ b/compare258.c @@ -14,28 +14,28 @@ static inline uint32_t compare256_c_static(const unsigned char *src0, const unsi do { if (*src0 != *src1) - return len + (*src0 == *src1); + return len; src0 += 1, src1 += 1, len += 1; if (*src0 != *src1) - return len + (*src0 == *src1); + return len; src0 += 1, src1 += 1, len += 1; if (*src0 != *src1) - return len + (*src0 == *src1); + return len; src0 += 1, src1 += 1, len += 1; if (*src0 != *src1) - return len + (*src0 == *src1); + return len; src0 += 1, src1 += 1, len += 1; if (*src0 != *src1) - return len + (*src0 == *src1); + return len; src0 += 1, src1 += 1, len += 1; if (*src0 != *src1) - return len + (*src0 == *src1); + return len; src0 += 1, src1 += 1, len += 1; if (*src0 != *src1) - return len + (*src0 == *src1); + return len; src0 += 1, src1 += 1, len += 1; if (*src0 != *src1) - return len + (*src0 == *src1); + return len; src0 += 1, src1 += 1, len += 1; } while (len < 256); From 156be5cf0f4dd41a75bf3563abf4fb1feee5e789 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 27 May 2021 20:43:41 -0700 Subject: [PATCH 062/798] Separate huff, rle, and stored deflate strategies into their own source files. --- CMakeLists.txt | 3 + Makefile.in | 6 + deflate.c | 339 +-------------------------------------------- deflate_huff.c | 45 ++++++ deflate_p.h | 38 ++++- deflate_rle.c | 81 +++++++++++ deflate_stored.c | 192 +++++++++++++++++++++++++ win32/Makefile.a64 | 10 +- win32/Makefile.arm | 10 +- win32/Makefile.msc | 8 +- 10 files changed, 392 insertions(+), 340 deletions(-) create mode 100644 deflate_huff.c create mode 100644 deflate_rle.c create mode 100644 deflate_stored.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e45bdc84e2..ae656ae05a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -920,9 +920,12 @@ set(ZLIB_SRCS crc32_comb.c deflate.c deflate_fast.c + deflate_huff.c deflate_medium.c deflate_quick.c + deflate_rle.c deflate_slow.c + deflate_stored.c functable.c infback.c inffast.c diff --git a/Makefile.in b/Makefile.in index 28d637470e..2c70ee1d52 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,9 +80,12 @@ OBJZ = \ crc32_comb.o \ deflate.o \ deflate_fast.o \ + deflate_huff.o \ deflate_medium.o \ deflate_quick.o \ + deflate_rle.o \ deflate_slow.o \ + deflate_stored.o \ functable.o \ infback.o \ inffast.o \ @@ -110,9 +113,12 @@ PIC_OBJZ = \ crc32_comb.lo \ deflate.lo \ deflate_fast.lo \ + deflate_huff.lo \ deflate_medium.lo \ deflate_quick.lo \ + deflate_rle.lo \ deflate_slow.lo \ + deflate_stored.lo \ functable.lo \ infback.lo \ inffast.lo \ diff --git a/deflate.c b/deflate.c index 5656e3aba2..3acd6d4f73 100644 --- a/deflate.c +++ b/deflate.c @@ -104,15 +104,15 @@ typedef block_state (*compress_func) (deflate_state *s, int flush); /* Compression function. Returns the block state after the call. */ static int deflateStateCheck (PREFIX3(stream) *strm); -static block_state deflate_stored (deflate_state *s, int flush); -Z_INTERNAL block_state deflate_fast (deflate_state *s, int flush); -Z_INTERNAL block_state deflate_quick (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush); +Z_INTERNAL block_state deflate_fast (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_quick (deflate_state *s, int flush); #ifndef NO_MEDIUM_STRATEGY -Z_INTERNAL block_state deflate_medium (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush); #endif -Z_INTERNAL block_state deflate_slow (deflate_state *s, int flush); -static block_state deflate_rle (deflate_state *s, int flush); -static block_state deflate_huff (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_slow (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_rle (deflate_state *s, int flush); +Z_INTERNAL block_state deflate_huff (deflate_state *s, int flush); static void lm_init (deflate_state *s); Z_INTERNAL unsigned read_buf (PREFIX3(stream) *strm, unsigned char *buf, unsigned size); @@ -1170,44 +1170,6 @@ static void lm_init(deflate_state *s) { s->match_start = 0; } -#ifdef ZLIB_DEBUG -#define EQUAL 0 -/* result of memcmp for equal strings */ - -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -void check_match(deflate_state *s, Pos start, Pos match, int length) { - /* check that the match length is valid*/ - if (length < MIN_MATCH || length > MAX_MATCH) { - fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); - z_error("invalid match length"); - } - /* check that the match isn't at the same position as the start string */ - if (match == start) { - fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); - z_error("invalid match position"); - } - /* check that the match is indeed a match */ - if (memcmp(s->window + match, s->window + start, length) != EQUAL) { - int32_t i = 0; - fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); - do { - fprintf(stderr, " %03d: match [%02x] start [%02x]\n", i++, s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr, "\\[%u,%d]", start-match, length); - do { - putc(s->window[start++], stderr); - } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* ZLIB_DEBUG */ - /* =========================================================================== * Fill the window when the lookahead becomes insufficient. * Updates strstart and lookahead. @@ -1335,294 +1297,7 @@ void Z_INTERNAL fill_window(deflate_state *s) { "not enough room for search"); } -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * - * In case deflateParams() is used to later switch to a non-zero compression - * level, s->matches (otherwise unused when storing) keeps track of the number - * of hash table slides to perform. If s->matches is 1, then one hash table - * slide will be done when switching. If s->matches is 2, the maximum value - * allowed here, then the hash table will be cleared, since two or more slides - * is the same as a clear. - * - * deflate_stored() is written to minimize the number of times an input byte is - * copied. It is most efficient with large input and output buffers, which - * maximizes the opportunites to have a single copy from next_in to next_out. - */ -static block_state deflate_stored(deflate_state *s, int flush) { - /* Smallest worthy block size when not flushing or finishing. By default - * this is 32K. This can be as small as 507 bytes for memLevel == 1. For - * large input and output buffers, the stored block size will be larger. - */ - unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); - - /* Copy as many min_block or larger stored blocks directly to next_out as - * possible. If flushing, copy the remaining available input to next_out as - * stored blocks, if there is enough space. - */ - unsigned len, left, have, last = 0; - unsigned used = s->strm->avail_in; - do { - /* Set len to the maximum size block that we can copy directly with the - * available input data and output space. Set left to how much of that - * would be copied from what's left in the window. - */ - len = MAX_STORED; /* maximum deflate stored block length */ - have = (s->bi_valid + 42) >> 3; /* number of header bytes */ - if (s->strm->avail_out < have) /* need room for header */ - break; - /* maximum stored block length that will fit in avail_out: */ - have = s->strm->avail_out - have; - left = (int)s->strstart - s->block_start; /* bytes left in window */ - if (len > (unsigned long)left + s->strm->avail_in) - len = left + s->strm->avail_in; /* limit len to the input */ - if (len > have) - len = have; /* limit len to the output */ - - /* If the stored block would be less than min_block in length, or if - * unable to copy all of the available input when flushing, then try - * copying to the window and the pending buffer instead. Also don't - * write an empty block when flushing -- deflate() does that. - */ - if (len < min_block && ((len == 0 && flush != Z_FINISH) || flush == Z_NO_FLUSH || len != left + s->strm->avail_in)) - break; - - /* Make a dummy stored block in pending to get the header bytes, - * including any pending bits. This also updates the debugging counts. - */ - last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; - zng_tr_stored_block(s, (char *)0, 0L, last); - - /* Replace the lengths in the dummy stored block with len. */ - s->pending -= 4; - put_short(s, (uint16_t)len); - put_short(s, (uint16_t)~len); - - /* Write the stored block header bytes. */ - flush_pending(s->strm); - - /* Update debugging counts for the data about to be copied. */ - cmpr_bits_add(s, len << 3); - sent_bits_add(s, len << 3); - - /* Copy uncompressed bytes from the window to next_out. */ - if (left) { - if (left > len) - left = len; - memcpy(s->strm->next_out, s->window + s->block_start, left); - s->strm->next_out += left; - s->strm->avail_out -= left; - s->strm->total_out += left; - s->block_start += (int)left; - len -= left; - } - - /* Copy uncompressed bytes directly from next_in to next_out, updating - * the check value. - */ - if (len) { - read_buf(s->strm, s->strm->next_out, len); - s->strm->next_out += len; - s->strm->avail_out -= len; - s->strm->total_out += len; - } - } while (last == 0); - - /* Update the sliding window with the last s->w_size bytes of the copied - * data, or append all of the copied data to the existing window if less - * than s->w_size bytes were copied. Also update the number of bytes to - * insert in the hash tables, in the event that deflateParams() switches to - * a non-zero compression level. - */ - used -= s->strm->avail_in; /* number of input bytes directly copied */ - if (used) { - /* If any input was used, then no unused input remains in the window, - * therefore s->block_start == s->strstart. - */ - if (used >= s->w_size) { /* supplant the previous history */ - s->matches = 2; /* clear hash */ - memcpy(s->window, s->strm->next_in - s->w_size, s->w_size); - s->strstart = s->w_size; - s->insert = s->strstart; - } else { - if (s->window_size - s->strstart <= used) { - /* Slide the window down. */ - s->strstart -= s->w_size; - memcpy(s->window, s->window + s->w_size, s->strstart); - if (s->matches < 2) - s->matches++; /* add a pending slide_hash() */ - if (s->insert > s->strstart) - s->insert = s->strstart; - } - memcpy(s->window + s->strstart, s->strm->next_in - used, used); - s->strstart += used; - s->insert += MIN(used, s->w_size - s->insert); - } - s->block_start = (int)s->strstart; - } - if (s->high_water < s->strstart) - s->high_water = s->strstart; - - /* If the last block was written to next_out, then done. */ - if (last) - return finish_done; - - /* If flushing and all input has been consumed, then done. */ - if (flush != Z_NO_FLUSH && flush != Z_FINISH && s->strm->avail_in == 0 && (int)s->strstart == s->block_start) - return block_done; - - /* Fill the window with any remaining input. */ - have = s->window_size - s->strstart; - if (s->strm->avail_in > have && s->block_start >= (int)s->w_size) { - /* Slide the window down. */ - s->block_start -= (int)s->w_size; - s->strstart -= s->w_size; - memcpy(s->window, s->window + s->w_size, s->strstart); - if (s->matches < 2) - s->matches++; /* add a pending slide_hash() */ - have += s->w_size; /* more space now */ - if (s->insert > s->strstart) - s->insert = s->strstart; - } - if (have > s->strm->avail_in) - have = s->strm->avail_in; - if (have) { - read_buf(s->strm, s->window + s->strstart, have); - s->strstart += have; - s->insert += MIN(have, s->w_size - s->insert); - } - if (s->high_water < s->strstart) - s->high_water = s->strstart; - - /* There was not enough avail_out to write a complete worthy or flushed - * stored block to next_out. Write a stored block to pending instead, if we - * have enough input for a worthy block, or if flushing and there is enough - * room for the remaining input as a stored block in the pending buffer. - */ - have = (s->bi_valid + 42) >> 3; /* number of header bytes */ - /* maximum stored block length that will fit in pending: */ - have = MIN(s->pending_buf_size - have, MAX_STORED); - min_block = MIN(have, s->w_size); - left = (int)s->strstart - s->block_start; - if (left >= min_block || ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && s->strm->avail_in == 0 && left <= have)) { - len = MIN(left, have); - last = flush == Z_FINISH && s->strm->avail_in == 0 && len == left ? 1 : 0; - zng_tr_stored_block(s, (char *)s->window + s->block_start, len, last); - s->block_start += (int)len; - flush_pending(s->strm); - } - - /* We've done all we can with the available input and output. */ - return last ? finish_started : need_more; -} - - -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -static block_state deflate_rle(deflate_state *s, int flush) { - int bflush = 0; /* set if current block must be flushed */ - unsigned int prev; /* byte at distance one to match */ - unsigned char *scan, *strend; /* scan goes up to strend for length of run */ - uint32_t match_len = 0; - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest run, plus one for the unrolled loop. - */ - if (s->lookahead <= MAX_MATCH) { - fill_window(s); - if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) - return need_more; - if (s->lookahead == 0) - break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - if (s->lookahead >= MIN_MATCH && s->strstart > 0) { - scan = s->window + s->strstart - 1; - prev = *scan; - if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + MAX_MATCH; - do { - } while (prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - prev == *++scan && prev == *++scan && - scan < strend); - match_len = MAX_MATCH - (unsigned int)(strend - scan); - if (match_len > s->lookahead) - match_len = s->lookahead; - } - Assert(scan <= s->window + s->window_size - 1, "wild scan"); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (match_len >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, match_len); - bflush = zng_tr_tally_dist(s, 1, match_len - MIN_MATCH); - - s->lookahead -= match_len; - s->strstart += match_len; - match_len = 0; - } else { - /* No match, output a literal byte */ - bflush = zng_tr_tally_lit(s, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - } - if (bflush) - FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->sym_next) - FLUSH_BLOCK(s, 0); - return block_done; -} - -/* =========================================================================== - * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. - * (It will be regenerated if this run of deflate switches away from Huffman.) - */ -static block_state deflate_huff(deflate_state *s, int flush) { - int bflush = 0; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we have a literal to write. */ - if (s->lookahead == 0) { - fill_window(s); - if (s->lookahead == 0) { - if (flush == Z_NO_FLUSH) - return need_more; - break; /* flush the current block */ - } - } - - /* Output a literal byte */ - bflush = zng_tr_tally_lit(s, s->window[s->strstart]); - s->lookahead--; - s->strstart++; - if (bflush) - FLUSH_BLOCK(s, 0); - } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); - return finish_done; - } - if (s->sym_next) - FLUSH_BLOCK(s, 0); - return block_done; -} #ifndef ZLIB_COMPAT /* ========================================================================= diff --git a/deflate_huff.c b/deflate_huff.c new file mode 100644 index 0000000000..296201f6f1 --- /dev/null +++ b/deflate_huff.c @@ -0,0 +1,45 @@ +/* deflate_huff.c -- compress data using huffman encoding only strategy + * + * 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" +#include "deflate_p.h" +#include "functable.h" + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +Z_INTERNAL block_state deflate_huff(deflate_state *s, int flush) { + int bflush = 0; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + bflush = zng_tr_tally_lit(s, s->window[s->strstart]); + s->lookahead--; + s->strstart++; + if (bflush) + FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/deflate_p.h b/deflate_p.h index 7cad8ab0ba..becaf71e3e 100644 --- a/deflate_p.h +++ b/deflate_p.h @@ -12,11 +12,43 @@ /* Forward declare common non-inlined functions declared in deflate.c */ #ifdef ZLIB_DEBUG -void check_match(deflate_state *s, Pos start, Pos match, int length); +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +static inline void check_match(deflate_state *s, Pos start, Pos match, int length) { + /* check that the match length is valid*/ + if (length < MIN_MATCH || length > MAX_MATCH) { + fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); + z_error("invalid match length"); + } + /* check that the match isn't at the same position as the start string */ + if (match == start) { + fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); + z_error("invalid match position"); + } + /* check that the match is indeed a match */ + if (memcmp(s->window + match, s->window + start, length) != 0) { + int32_t i = 0; + fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); + do { + fprintf(stderr, " %03d: match [%02x] start [%02x]\n", i++, + s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr, "\\[%u,%d]", start-match, length); + do { + putc(s->window[start++], stderr); + } while (--length != 0); + } +} #else #define check_match(s, start, match, length) #endif -void flush_pending(PREFIX3(stream) *strm); + +Z_INTERNAL void flush_pending(PREFIX3(stream) *strm); +Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size); /* =========================================================================== * Save the match info and tally the frequency counts. Return true if @@ -45,7 +77,7 @@ static inline int zng_tr_tally_dist(deflate_state *s, uint32_t dist, uint32_t le s->sym_buf[s->sym_next++] = (uint8_t)len; s->matches++; dist--; - Assert(dist < MAX_DIST(s) && (uint16_t)d_code(dist) < (uint16_t)D_CODES, + Assert(dist < MAX_DIST(s) && (uint16_t)d_code(dist) < (uint16_t)D_CODES, "zng_tr_tally: bad match"); s->dyn_ltree[zng_length_code[len]+LITERALS+1].Freq++; diff --git a/deflate_rle.c b/deflate_rle.c new file mode 100644 index 0000000000..c09bcc44ec --- /dev/null +++ b/deflate_rle.c @@ -0,0 +1,81 @@ +/* deflate_rle.c -- compress data using RLE strategy of deflation algorithm + * + * 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" +#include "deflate_p.h" +#include "functable.h" + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { + int bflush = 0; /* set if current block must be flushed */ + unsigned int prev; /* byte at distance one to match */ + unsigned char *scan, *strend; /* scan goes up to strend for length of run */ + uint32_t match_len = 0; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s->lookahead <= MAX_MATCH) { + fill_window(s); + if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) + return need_more; + if (s->lookahead == 0) + break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + match_len = MAX_MATCH - (unsigned int)(strend - scan); + if (match_len > s->lookahead) + match_len = s->lookahead; + } + Assert(scan <= s->window + s->window_size - 1, "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (match_len >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, match_len); + + bflush = zng_tr_tally_dist(s, 1, match_len - MIN_MATCH); + + s->lookahead -= match_len; + s->strstart += match_len; + match_len = 0; + } else { + /* No match, output a literal byte */ + bflush = zng_tr_tally_lit(s, s->window[s->strstart]); + s->lookahead--; + s->strstart++; + } + if (bflush) + FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->sym_next) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/deflate_stored.c b/deflate_stored.c new file mode 100644 index 0000000000..134ed619ba --- /dev/null +++ b/deflate_stored.c @@ -0,0 +1,192 @@ +/* deflate_stored.c -- store data without compression using deflation algorithm + * + * 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" +#include "deflate_p.h" +#include "functable.h" + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. + */ +Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. + */ + unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); + + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + unsigned len, left, have, last = 0; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. + */ + len = MAX_STORED; /* maximum deflate stored block length */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = (int)s->strstart - s->block_start; /* bytes left in window */ + if (len > (unsigned long)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + if (len > have) + len = have; /* limit len to the output */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || flush == Z_NO_FLUSH || len != left + s->strm->avail_in)) + break; + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; + zng_tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending -= 4; + put_short(s, (uint16_t)len); + put_short(s, (uint16_t)~len); + + /* Write the stored block header bytes. */ + flush_pending(s->strm); + + /* Update debugging counts for the data about to be copied. */ + cmpr_bits_add(s, len << 3); + sent_bits_add(s, len << 3); + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) + left = len; + memcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += (int)left; + len -= left; + } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; + } + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + memcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + s->insert = s->strstart; + } else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + memcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + if (s->insert > s->strstart) + s->insert = s->strstart; + } + memcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + s->insert += MIN(used, s->w_size - s->insert); + } + s->block_start = (int)s->strstart; + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* If the last block was written to next_out, then done. */ + if (last) + return finish_done; + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && s->strm->avail_in == 0 && (int)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = s->window_size - s->strstart; + if (s->strm->avail_in > have && s->block_start >= (int)s->w_size) { + /* Slide the window down. */ + s->block_start -= (int)s->w_size; + s->strstart -= s->w_size; + memcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ + if (s->insert > s->strstart) + s->insert = s->strstart; + } + if (have > s->strm->avail_in) + have = s->strm->avail_in; + if (have) { + read_buf(s->strm, s->window + s->strstart, have); + s->strstart += have; + s->insert += MIN(have, s->w_size - s->insert); + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = (int)s->strstart - s->block_start; + if (left >= min_block || ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && len == left ? 1 : 0; + zng_tr_stored_block(s, (char *)s->window + s->block_start, len, last); + s->block_start += (int)len; + flush_pending(s->strm); + } + + /* We've done all we can with the available input and output. */ + return last ? finish_started : need_more; +} diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index a2f2e6a608..136e32d4d7 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -51,9 +51,12 @@ OBJS = \ crc32_comb.obj \ deflate.obj \ deflate_fast.obj \ - deflate_slow.obj \ + deflate_huff.obj \ deflate_quick.obj \ deflate_medium.obj \ + deflate_rle.obj \ + deflate_slow.obj \ + deflate_stored.obj \ functable.obj \ infback.obj \ inflate.obj \ @@ -164,10 +167,13 @@ uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h -deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/trees_emit.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h +deflate_huff.obj: $(SRCDIR)/deflate_huff.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h +deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/trees_emit.h deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h +deflate_rle.obj: $(SRCDIR)/deflate_rle.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h +deflate_stored.obj: $(SRCDIR)/deflate_stored.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 5ed53f5f3e..92eed88ad6 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -54,9 +54,12 @@ OBJS = \ crc32_comb.obj \ deflate.obj \ deflate_fast.obj \ - deflate_slow.obj \ - deflate_quick.obj \ + deflate_huff.obj \ deflate_medium.obj \ + deflate_quick.obj \ + deflate_rle.obj \ + deflate_slow.obj \ + deflate_stored.obj \ functable.obj \ infback.obj \ inflate.obj \ @@ -177,9 +180,12 @@ crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/de crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h +deflate_huff.obj: $(SRCDIR)/deflate_huff.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/trees_emit.h +deflate_rle.obj: $(SRCDIR)/deflate_rle.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h +deflate_stored.obj: $(SRCDIR)/deflate_stored.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 85d27b9d76..ee6f857d76 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -61,9 +61,12 @@ OBJS = \ crc_folding.obj \ deflate.obj \ deflate_fast.obj \ + deflate_huff.obj \ + deflate_medium.obj \ deflate_quick.obj \ + deflate_rle.obj \ deflate_slow.obj \ - deflate_medium.obj \ + deflate_stored.obj \ functable.obj \ infback.obj \ inflate.obj \ @@ -171,9 +174,12 @@ crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/de crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h +deflate_huff.obj: $(SRCDIR)/deflate_huff.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_medium.obj: $(SRCDIR)/deflate_medium.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_quick.obj: $(SRCDIR)/deflate_quick.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h $(SRCDIR)/trees_emit.h +deflate_rle.obj: $(SRCDIR)/deflate_rle.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_slow.obj: $(SRCDIR)/deflate_slow.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h +deflate_stored.obj: $(SRCDIR)/deflate_stored.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h From d4dd539d1c08ce0affb360120a9e4ac2396e734b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 28 May 2021 18:15:50 -0700 Subject: [PATCH 063/798] Clean up deflate_stored and deflate_rle by using MIN() where applicable. --- deflate_rle.c | 3 +-- deflate_stored.c | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/deflate_rle.c b/deflate_rle.c index c09bcc44ec..c3899b7751 100644 --- a/deflate_rle.c +++ b/deflate_rle.c @@ -46,8 +46,7 @@ Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { prev == *++scan && prev == *++scan && scan < strend); match_len = MAX_MATCH - (unsigned int)(strend - scan); - if (match_len > s->lookahead) - match_len = s->lookahead; + match_len = MIN(match_len, s->lookahead); } Assert(scan <= s->window + s->window_size - 1, "wild scan"); } diff --git a/deflate_stored.c b/deflate_stored.c index 134ed619ba..860d894ddd 100644 --- a/deflate_stored.c +++ b/deflate_stored.c @@ -51,8 +51,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { left = (int)s->strstart - s->block_start; /* bytes left in window */ if (len > (unsigned long)left + s->strm->avail_in) len = left + s->strm->avail_in; /* limit len to the input */ - if (len > have) - len = have; /* limit len to the output */ + len = MIN(len, have); /* limit len to the output */ /* If the stored block would be less than min_block in length, or if * unable to copy all of the available input when flushing, then try @@ -82,8 +81,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { /* Copy uncompressed bytes from the window to next_out. */ if (left) { - if (left > len) - left = len; + left = MIN(left, len); memcpy(s->strm->next_out, s->window + s->block_start, left); s->strm->next_out += left; s->strm->avail_out -= left; @@ -126,8 +124,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { memcpy(s->window, s->window + s->w_size, s->strstart); if (s->matches < 2) s->matches++; /* add a pending slide_hash() */ - if (s->insert > s->strstart) - s->insert = s->strstart; + s->insert = MIN(s->insert, s->strstart); } memcpy(s->window + s->strstart, s->strm->next_in - used, used); s->strstart += used; @@ -135,8 +132,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { } s->block_start = (int)s->strstart; } - if (s->high_water < s->strstart) - s->high_water = s->strstart; + s->high_water = MIN(s->high_water, s->strstart); /* If the last block was written to next_out, then done. */ if (last) @@ -156,18 +152,16 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { if (s->matches < 2) s->matches++; /* add a pending slide_hash() */ have += s->w_size; /* more space now */ - if (s->insert > s->strstart) - s->insert = s->strstart; + s->insert = MIN(s->insert, s->strstart); } - if (have > s->strm->avail_in) - have = s->strm->avail_in; + + have = MIN(have, s->strm->avail_in); if (have) { read_buf(s->strm, s->window + s->strstart, have); s->strstart += have; s->insert += MIN(have, s->w_size - s->insert); } - if (s->high_water < s->strstart) - s->high_water = s->strstart; + s->high_water = MIN(s->high_water, s->strstart); /* There was not enough avail_out to write a complete worthy or flushed * stored block to next_out. Write a stored block to pending instead, if we From baff847dc1f6aa957054f33ba182fee2542939a7 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 9 Mar 2021 10:18:24 -0800 Subject: [PATCH 064/798] Increase size of gzip output buffer to be a multiple of the size of deflate's pending buffer for improved performance and fewer calls to deflate. --- CMakeLists.txt | 1 - gzguts.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae656ae05a..9462652893 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -749,7 +749,6 @@ if(WITH_OPTIM) elseif(BASEARCH_S360_FOUND) if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/dfltcc_common.c) - add_definitions(-DGZBUFSIZE=262144) endif() if(WITH_DFLTCC_DEFLATE) add_definitions(-DS390_DFLTCC_DEFLATE) diff --git a/gzguts.h b/gzguts.h index 16029607f7..c42587470e 100644 --- a/gzguts.h +++ b/gzguts.h @@ -88,7 +88,7 @@ /* default i/o buffer size -- double this for output when reading (this and twice this must be able to fit in an unsigned type) */ #ifndef GZBUFSIZE -# define GZBUFSIZE 8192 +# define GZBUFSIZE 131072 #endif /* gzip modes, also provide a little integrity check on the passed structure */ From ce6789c7e093e8e6bb6fc591bbdf0f805999bdb9 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 26 Mar 2021 16:21:23 +0100 Subject: [PATCH 065/798] Rebalance levels 1-4. - Deflate_quick (level 1), no longer limit window, improves compression. - Deflate_medium, don't check next position for levels below 5. - Use deflate_medium instead of deflate_fast for level 3. - Tweak level 4 to give a more predictable speed/compression tradeoff curve. --- deflate.c | 13 ++++--------- deflate_medium.c | 7 +++++-- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/deflate.c b/deflate.c index 3acd6d4f73..076b05f199 100644 --- a/deflate.c +++ b/deflate.c @@ -144,21 +144,21 @@ static const config configuration_table[10] = { /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ #ifndef NO_QUICK_STRATEGY -/* 1 */ {4, 4, 8, 4, deflate_quick}, +/* 1 */ {0, 0, 0, 0, deflate_quick}, /* 2 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ #else /* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, #endif -/* 3 */ {4, 6, 32, 32, deflate_fast}, - #ifdef NO_MEDIUM_STRATEGY +/* 3 */ {4, 6, 32, 32, deflate_fast}, /* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_slow}, /* 6 */ {8, 16, 128, 128, deflate_slow}, #else -/* 4 */ {4, 4, 16, 16, deflate_medium}, /* lazy matches */ +/* 3 */ {4, 6, 16, 6, deflate_medium}, +/* 4 */ {4, 12, 32, 24, deflate_medium}, /* lazy matches */ /* 5 */ {8, 16, 32, 32, deflate_medium}, /* 6 */ {8, 16, 128, 128, deflate_medium}, #endif @@ -281,11 +281,6 @@ int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ -#if !defined(NO_QUICK_STRATEGY) && !defined(S390_DFLTCC_DEFLATE) - if (level == 1) - windowBits = 13; -#endif - s = (deflate_state *) ZALLOC_STATE(strm, 1, sizeof(deflate_state)); if (s == NULL) return Z_MEM_ERROR; diff --git a/deflate_medium.c b/deflate_medium.c index 59ccfa89ef..303890a651 100644 --- a/deflate_medium.c +++ b/deflate_medium.c @@ -165,6 +165,9 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { ALIGNED_(16) struct match current_match; struct match next_match; + /* For levels below 5, don't check the next position for a better match */ + int early_exit = s->level < 5; + memset(¤t_match, 0, sizeof(struct match)); memset(&next_match, 0, sizeof(struct match)); @@ -193,7 +196,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { */ /* If we already have a future match from a previous round, just use that */ - if (next_match.match_length > 0) { + if (!early_exit && next_match.match_length > 0) { current_match = next_match; next_match.match_length = 0; } else { @@ -233,7 +236,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { insert_match(s, current_match); /* now, look ahead one */ - if (LIKELY(s->lookahead > MIN_LOOKAHEAD && (uint32_t)(current_match.strstart + current_match.match_length) < (s->window_size - MIN_LOOKAHEAD))) { + if (LIKELY(!early_exit && s->lookahead > MIN_LOOKAHEAD && (uint32_t)(current_match.strstart + current_match.match_length) < (s->window_size - MIN_LOOKAHEAD))) { s->strstart = current_match.strstart + current_match.match_length; hash_head = functable.quick_insert_string(s, s->strstart); From eb41bf416dee72972c12fbb264d3d50d3976d2e7 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 26 Mar 2021 17:06:28 +0100 Subject: [PATCH 066/798] Reorder config table to avoid double negation, and to use the same logical ordering as the other ifdef. --- deflate.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deflate.c b/deflate.c index 076b05f199..dd1f120c4d 100644 --- a/deflate.c +++ b/deflate.c @@ -143,12 +143,12 @@ static const config configuration_table[10] = { /* good lazy nice chain */ /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -#ifndef NO_QUICK_STRATEGY -/* 1 */ {0, 0, 0, 0, deflate_quick}, -/* 2 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -#else +#ifdef NO_QUICK_STRATEGY /* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ /* 2 */ {4, 5, 16, 8, deflate_fast}, +#else +/* 1 */ {0, 0, 0, 0, deflate_quick}, +/* 2 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ #endif #ifdef NO_MEDIUM_STRATEGY From 887dce61b856987a95a7fd7e5143798521be3f42 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 10 Jun 2021 17:19:25 -0700 Subject: [PATCH 067/798] Must use safe chunk copies due to inflateBack using the same allocation for output and window. In this instance if too many bytes are written it will not correctly write matches with distances close to the window size. --- inffast.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/inffast.c b/inffast.c index c8d3da3410..c431e50fc1 100644 --- a/inffast.c +++ b/inffast.c @@ -128,6 +128,7 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ unsigned char *from; /* where to copy match from */ + unsigned extra_safe; /* copy chunks safely in all cases */ /* copy state to local variables */ state = (struct inflate_state *)strm->state; @@ -151,6 +152,11 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; + /* Detect if out and window point to the same memory allocation. In this instance it is + necessary to use safe chunk copy functions to prevent overwriting the window. If the + window is overwritten then future matches with far distances will fail to copy correctly. */ + extra_safe = (out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); + /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { @@ -259,12 +265,22 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { } else { out = functable.chunkcopy_safe(out, from, len, safe); } - } else { + } else if (extra_safe) { /* Whole reference is in range of current output. */ if (dist >= len || dist >= state->chunksize) out = functable.chunkcopy_safe(out, out - dist, len, safe); else out = functable.chunkmemset_safe(out, dist, len, safe - out + 1); + } else { + /* Whole reference is in range of current output. No range checks are + necessary because we start with room for at least 258 bytes of output, + so unroll and roundoff operations can write beyond `out+len` so long + as they stay within 258 bytes of `out`. + */ + if (dist >= len || dist >= state->chunksize) + out = functable.chunkcopy(out, out - dist, len); + else + out = functable.chunkmemset(out, dist, len); } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode + here->val + BITS(op); From 1118fa8ecc0b5522738b8d7781c813d47f607394 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 5 May 2021 15:32:40 -0700 Subject: [PATCH 068/798] Change bi_reverse to use a bit-twiddling hack for 240x speed improvement. --- deflate.h | 2 +- tools/maketrees.c | 2 +- trees.c | 18 +++++++----------- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/deflate.h b/deflate.h index 03ea3126ff..7243d1d9d8 100644 --- a/deflate.h +++ b/deflate.h @@ -387,7 +387,7 @@ void Z_INTERNAL zng_tr_flush_block(deflate_state *s, char *buf, uint32_t stored_ void Z_INTERNAL zng_tr_flush_bits(deflate_state *s); void Z_INTERNAL zng_tr_align(deflate_state *s); void Z_INTERNAL zng_tr_stored_block(deflate_state *s, char *buf, uint32_t stored_len, int last); -unsigned Z_INTERNAL bi_reverse(unsigned code, int len); +uint16_t Z_INTERNAL bi_reverse(unsigned code, int len); void Z_INTERNAL flush_pending(PREFIX3(streamp) strm); #define d_code(dist) ((dist) < 256 ? zng_dist_code[dist] : zng_dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and diff --git a/tools/maketrees.c b/tools/maketrees.c index 337f2fc070..c648a650c8 100644 --- a/tools/maketrees.c +++ b/tools/maketrees.c @@ -90,7 +90,7 @@ static void tr_static_init(void) { /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; - static_dtree[n].Code = (uint16_t)bi_reverse((unsigned)n, 5); + static_dtree[n].Code = bi_reverse((unsigned)n, 5); } } diff --git a/trees.c b/trees.c index efd4d49fb9..2a5e2de946 100644 --- a/trees.c +++ b/trees.c @@ -305,7 +305,7 @@ Z_INTERNAL void gen_codes(ct_data *tree, int max_code, uint16_t *bl_count) { if (len == 0) continue; /* Now reverse the bits */ - tree[n].Code = (uint16_t)bi_reverse(next_code[len]++, len); + tree[n].Code = bi_reverse(next_code[len]++, len); Tracecv(tree != static_ltree, (stderr, "\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); @@ -806,17 +806,13 @@ static void bi_flush(deflate_state *s) { } /* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 + * Reverse the first len bits of a code using bit manipulation */ -Z_INTERNAL unsigned bi_reverse(unsigned code, int len) { +Z_INTERNAL uint16_t bi_reverse(unsigned code, int len) { /* code: the value to invert */ /* len: its bit length */ - Z_REGISTER unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; + Assert(len >= 1 && len <= 15, "code length must be 1-15"); +#define bitrev8(b) \ + (uint8_t)((((uint8_t)(b) * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32) + return (bitrev8(code >> 8) | (uint16_t)bitrev8(code) << 8) >> (16 - len); } From ce6c2b4b00ba463d61dc4cd83384ea40790db1a6 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 20 Mar 2021 14:10:14 -0700 Subject: [PATCH 069/798] Only run checks for intrinsics if optimizations are enabled. --- CMakeLists.txt | 209 ++++------------------ cmake/detect-intrinsics.cmake | 221 ++++++++++++++++++++++++ configure | 314 ++++++++++++++++------------------ 3 files changed, 409 insertions(+), 335 deletions(-) create mode 100644 cmake/detect-intrinsics.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 9462652893..9fcef69042 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ include(FeatureSummary) include(cmake/detect-arch.cmake) include(cmake/detect-install-dirs.cmake) include(cmake/detect-coverage.cmake) +include(cmake/detect-intrinsics.cmake) include(cmake/detect-sanitizer.cmake) if(CMAKE_TOOLCHAIN_FILE) @@ -139,23 +140,11 @@ if(CMAKE_C_COMPILER_ID MATCHES "Intel") set(WARNFLAGS "-w3") set(WARNFLAGS_MAINTAINER "-w3 -Wcheck -Wremarks") set(WARNFLAGS_DISABLE "") - if(BASEARCH_X86_FOUND) - set(AVX2FLAG "-mavx2") - set(SSE2FLAG "-msse2") - set(SSSE3FLAG "-mssse3") - set(SSE4FLAG "-msse4.2") - endif() else() set(WARNFLAGS "/W3") set(WARNFLAGS_MAINTAINER "/W5") set(WARNFLAGS_DISABLE "") - if(BASEARCH_X86_FOUND) - set(AVX2FLAG "/arch:AVX2") - set(SSE2FLAG "/arch:SSE2") - set(SSSE3FLAG "/arch:SSSE3") - set(SSE4FLAG "/arch:SSE4.2") endif() - endif() if(WITH_NATIVE_INSTRUCTIONS) message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") endif() @@ -177,38 +166,22 @@ elseif(MSVC) if(NOT "${ARCH}" MATCHES "aarch64") set(NEONFLAG "/arch:VFPv4") endif() - elseif(BASEARCH_X86_FOUND) - if(NOT "${ARCH}" MATCHES "x86_64") - set(SSE2FLAG "/arch:SSE2") endif() - endif() if(WITH_NATIVE_INSTRUCTIONS) message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") endif() -else() - # catch all GNU C compilers as well as Clang and AppleClang - if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") - set(__GNUC__ ON) - endif() +elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") # Enable warnings in GCC and Clang - if(__GNUC__) set(WARNFLAGS "-Wall") set(WARNFLAGS_MAINTAINER "-Wextra -Wpedantic") set(WARNFLAGS_DISABLE "-Wno-implicit-fallthrough") - endif() if(WITH_NATIVE_INSTRUCTIONS) - if(__GNUC__) if(BASEARCH_PPC_FOUND) set(NATIVEFLAG "-mcpu=native") else() set(NATIVEFLAG "-march=native") endif() else() - message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration") - endif() - endif() - if(NOT NATIVEFLAG) - if(__GNUC__) if(BASEARCH_ARM_FOUND) if("${ARCH}" MATCHES "arm" AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") # Auto-detect support for ARM floating point ABI @@ -228,31 +201,7 @@ else() message(STATUS "ARM floating point arch not auto-detected") endif() endif() - # NEON - if("${ARCH}" MATCHES "aarch64") - set(NEONFLAG "-march=armv8-a+simd") - else() - # Check whether -mfpu=neon is available - set(CMAKE_REQUIRED_FLAGS "-mfpu=neon") - check_c_source_compiles( - "int main() { return 0; }" - MFPU_NEON_AVAILABLE FAIL_REGEX "not supported") - set(CMAKE_REQUIRED_FLAGS) - if(MFPU_NEON_AVAILABLE) - set(NEONFLAG "-mfpu=neon") endif() - endif() - # ACLE - set(ACLEFLAG "-march=armv8-a+crc") - elseif(BASEARCH_PPC_FOUND) - set(POWER8FLAG "-mcpu=power8") - elseif(BASEARCH_X86_FOUND) - set(AVX2FLAG "-mavx2") - set(SSE2FLAG "-msse2") - set(SSSE3FLAG "-mssse3") - set(SSE4FLAG "-msse4") - set(PCLMULFLAG "-mpclmul") - endif() # Check whether -fno-lto is available set(CMAKE_REQUIRED_FLAGS "-fno-lto") check_c_source_compiles( @@ -263,6 +212,9 @@ else() set(NOLTOFLAG "-fno-lto") endif() endif() +else() + if(WITH_NATIVE_INSTRUCTIONS) + message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration") endif() endif() @@ -483,119 +435,7 @@ if(MSVC) add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) endif() -if(BASEARCH_PPC_FOUND) - # Check if we have what we need for POWER8 optimizations - set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG}") - check_c_source_compiles( - "#include - int main() { - return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); - }" - HAVE_POWER8 - ) - set(CMAKE_REQUIRED_FLAGS) -elseif(BASEARCH_X86_FOUND) - # Check whether compiler supports SSE2 instrinics - set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG}") - check_c_source_compile_or_run( - "#include - int main(void) { - __m128i zero = _mm_setzero_si128(); - (void)zero; - return 0; - }" - HAVE_SSE2_INTRIN - ) - # Check whether compiler supports SSSE3 intrinsics - set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG}") - check_c_source_compile_or_run( - "#include - int main(void) { - __m128i u, v, w; - u = _mm_set1_epi32(1); - v = _mm_set1_epi32(2); - w = _mm_hadd_epi32(u, v); - (void)w; - return 0; - }" - HAVE_SSSE3_INTRIN - ) - # Check whether compiler supports SSE4 CRC inline asm - set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG}") - check_c_source_compile_or_run( - "int main(void) { - unsigned val = 0, h = 0; - #if defined(_MSC_VER) - { __asm mov edx, h __asm mov eax, val __asm crc32 eax, edx __asm mov val, eax } - #else - __asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) ); - #endif - return (int)h; - }" - HAVE_SSE42CRC_INLINE_ASM - ) - # Check whether compiler supports SSE4 CRC intrinsics - check_c_source_compile_or_run( - "#include - int main(void) { - unsigned crc = 0; - char c = 'c'; - #if defined(_MSC_VER) - crc = _mm_crc32_u32(crc, c); - #else - crc = __builtin_ia32_crc32qi(crc, c); - #endif - (void)crc; - return 0; - }" - HAVE_SSE42CRC_INTRIN - ) - # Check whether compiler supports SSE4.2 compare string instrinics - check_c_source_compile_or_run( - "#include - int main(void) { - unsigned char a[64] = { 0 }; - unsigned char b[64] = { 0 }; - __m128i xmm_src0, xmm_src1; - xmm_src0 = _mm_loadu_si128((__m128i *)(char *)a); - xmm_src1 = _mm_loadu_si128((__m128i *)(char *)b); - return _mm_cmpestri(xmm_src0, 16, xmm_src1, 16, 0); - }" - HAVE_SSE42CMPSTR_INTRIN - ) - # Check whether compiler supports PCLMULQDQ intrinsics - set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG}") - if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) - # The pclmul code currently crashes on Mac in 32bit mode. Avoid for now. - check_c_source_compile_or_run( - "#include - int main(void) { - __m128i a = _mm_setzero_si128(); - __m128i b = _mm_setzero_si128(); - __m128i c = _mm_clmulepi64_si128(a, b, 0x10); - (void)c; - return 0; - }" - HAVE_PCLMULQDQ_INTRIN - ) - else() - set(HAVE_PCLMULQDQ_INTRIN NO) - endif() - # Check whether compiler supports AVX2 intrinics - set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG}") - check_c_source_compile_or_run( - "#include - int main(void) { - __m256i x = _mm256_set1_epi16(2); - const __m256i y = _mm256_set1_epi16(1); - x = _mm256_subs_epu16(x, y); - (void)x; - return 0; - }" - HAVE_AVX2_INTRIN - ) - set(CMAKE_REQUIRED_FLAGS) - +if(BASEARCH_X86_FOUND) # FORCE_SSE2 option will only be shown if HAVE_SSE2_INTRIN is true if("${ARCH}" MATCHES "i[3-6]86") cmake_dependent_option(FORCE_SSE2 "Always assume CPU is SSE2 capable" OFF "HAVE_SSE2_INTRIN" OFF) @@ -717,13 +557,18 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/armfeature.c) if(WITH_ACLE AND NOT MSVC) + check_acle_intrinsics() + if(HAVE_ACLE_INTRIN) add_definitions(-DARM_ACLE_CRC_HASH) set(ACLE_SRCS ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c) set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG} ${NOLTOFLAG}") list(APPEND ZLIB_ARCH_SRCS ${ACLE_SRCS}) add_feature_info(ACLE_CRC 1 "Support ACLE optimized CRC hash generation, using \"${ACLEFLAG}\"") endif() + endif() if(WITH_NEON) + check_neon_intrinsics() + if(MFPU_NEON_AVAILABLE) add_definitions(-DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_neon.c) list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) @@ -734,8 +579,11 @@ if(WITH_OPTIM) add_feature_info(NEON_ADLER32 1 "Support NEON instructions in adler32, using \"${NEONFLAG}\"") add_feature_info(NEON_SLIDEHASH 1 "Support NEON instructions in slide_hash, using \"${NEONFLAG}\"") endif() + endif() elseif(BASEARCH_PPC_FOUND) - if(WITH_POWER8 AND HAVE_POWER8) + if(WITH_POWER8) + check_power8_intrinsics() + if(HAVE_POWER8_INTRIN) add_definitions(-DPOWER8) add_definitions(-DPOWER_FEATURES) add_definitions(-DPOWER8_VSX_ADLER32) @@ -746,6 +594,7 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") endif() + endif() elseif(BASEARCH_S360_FOUND) if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/dfltcc_common.c) @@ -765,7 +614,9 @@ if(WITH_OPTIM) if(MSVC) list(APPEND ZLIB_ARCH_HDRS fallback_builtins.h) endif() - if(WITH_AVX2 AND HAVE_AVX2_INTRIN) + if(WITH_AVX2) + check_avx2_intrinsics() + if(HAVE_AVX2_INTRIN) add_definitions(-DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET) set(AVX2_SRCS ${ARCHDIR}/slide_avx.c) add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") @@ -778,7 +629,10 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG} ${NOLTOFLAG}") endif() - if(WITH_SSE4 AND (HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN)) + endif() + if(WITH_SSE4) + check_sse4_intrinsics() + if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) add_definitions(-DX86_SSE42_CRC_HASH) set(SSE42_SRCS ${ARCHDIR}/insert_string_sse.c) add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE4FLAG}\"") @@ -795,7 +649,10 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") endif() - if(WITH_SSE2 AND HAVE_SSE2_INTRIN) + endif() + if(WITH_SSE2) + check_sse2_intrinsics() + if(HAVE_SSE2_INTRIN) add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) set(SSE2_SRCS ${ARCHDIR}/chunkset_sse.c ${ARCHDIR}/slide_sse.c) list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) @@ -807,14 +664,20 @@ if(WITH_OPTIM) endif() endif() endif() - if(WITH_SSSE3 AND HAVE_SSSE3_INTRIN) + endif() + if(WITH_SSSE3) + check_ssse3_intrinsics() + if(HAVE_SSSE3_INTRIN) add_definitions(-DX86_SSSE3 -DX86_SSSE3_ADLER32) set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c) add_feature_info(SSSE3_ADLER32 1 "Support SSSE3-accelerated adler32, using \"${SSSE3FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${NOLTOFLAG}") endif() - if(WITH_PCLMULQDQ AND HAVE_PCLMULQDQ_INTRIN AND WITH_SSSE3 AND WITH_SSE4) + endif() + if(WITH_PCLMULQDQ AND WITH_SSSE3 AND WITH_SSE4) + check_pclmulqdq_intrinsics() + if(HAVE_PCLMULQDQ_INTRIN AND HAVE_SSSE3_INTRIN) add_definitions(-DX86_PCLMULQDQ_CRC) set(PCLMULQDQ_SRCS ${ARCHDIR}/crc_folding.c) add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}\"") @@ -823,6 +686,8 @@ if(WITH_OPTIM) endif() endif() endif() +endif() + message(STATUS "Architecture-specific source files: ${ZLIB_ARCH_SRCS}") #============================================================================ diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake new file mode 100644 index 0000000000..a360b7e664 --- /dev/null +++ b/cmake/detect-intrinsics.cmake @@ -0,0 +1,221 @@ +# detect-intrinsics.cmake -- Detect compiler intrinsics support +# Licensed under the Zlib license, see LICENSE.md for details + +macro(check_acle_intrinsics) + if(NOT NATIVEFLAG) + set(ACLEFLAG "-march=armv8-a+crc") + endif() + # Check whether compiler supports ACLE flag + set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG}") + check_c_source_compiles( + "int main() { return 0; }" + HAVE_ACLE_INTRIN FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_avx2_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(AVX2FLAG "-mavx2") + else() + set(AVX2FLAG "/arch:AVX2") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(AVX2FLAG "-mavx2") + endif() + endif() + # Check whether compiler supports AVX2 intrinics + set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG}") + check_c_source_compile_or_run( + "#include + int main(void) { + __m256i x = _mm256_set1_epi16(2); + const __m256i y = _mm256_set1_epi16(1); + x = _mm256_subs_epu16(x, y); + (void)x; + return 0; + }" + HAVE_AVX2_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_neon_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + if("${ARCH}" MATCHES "aarch64") + set(NEONFLAG "-march=armv8-a+simd") + else() + set(NEONFLAG "-mfpu=neon") + endif() + endif() + endif() + # Check whether compiler supports NEON flag + set(CMAKE_REQUIRED_FLAGS "${NEONFLAG}") + check_c_source_compiles( + "int main() { return 0; }" + MFPU_NEON_AVAILABLE FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_pclmulqdq_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(PCLMULFLAG "-mpclmul") + endif() + endif() + # Check whether compiler supports PCLMULQDQ intrinsics + if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) + # The pclmul code currently crashes on Mac in 32bit mode. Avoid for now. + set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG}") + check_c_source_compile_or_run( + "#include + int main(void) { + __m128i a = _mm_setzero_si128(); + __m128i b = _mm_setzero_si128(); + __m128i c = _mm_clmulepi64_si128(a, b, 0x10); + (void)c; + return 0; + }" + HAVE_PCLMULQDQ_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) + else() + set(HAVE_PCLMULQDQ_INTRIN OFF) + endif() +endmacro() + +macro(check_power8_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(POWER8FLAG "-mcpu=power8") + endif() + endif() + # Check if we have what we need for POWER8 optimizations + set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG}") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); + }" + HAVE_POWER8_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_sse2_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(SSE2FLAG "-msse2") + else() + set(SSE2FLAG "/arch:SSE2") + endif() + elseif(MSVC) + if(NOT "${ARCH}" MATCHES "x86_64") + set(SSE2FLAG "/arch:SSE2") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(SSE2FLAG "-msse2") + endif() + endif() + # Check whether compiler supports SSE2 instrinics + set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG}") + check_c_source_compile_or_run( + "#include + int main(void) { + __m128i zero = _mm_setzero_si128(); + (void)zero; + return 0; + }" + HAVE_SSE2_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_ssse3_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(SSSE3FLAG "-mssse3") + else() + set(SSSE3FLAG "/arch:SSSE3") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(SSSE3FLAG "-mssse3") + endif() + endif() + # Check whether compiler supports SSSE3 intrinsics + set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG}") + check_c_source_compile_or_run( + "#include + int main(void) { + __m128i u, v, w; + u = _mm_set1_epi32(1); + v = _mm_set1_epi32(2); + w = _mm_hadd_epi32(u, v); + (void)w; + return 0; + }" + HAVE_SSSE3_INTRIN + ) +endmacro() + +macro(check_sse4_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(SSE4FLAG "-msse4.2") + else() + set(SSE4FLAG "/arch:SSE4.2") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(SSE4FLAG "-msse4") + endif() + endif() + # Check whether compiler supports SSE4 CRC inline asm + set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG}") + check_c_source_compile_or_run( + "int main(void) { + unsigned val = 0, h = 0; + #if defined(_MSC_VER) + { __asm mov edx, h __asm mov eax, val __asm crc32 eax, edx __asm mov val, eax } + #else + __asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) ); + #endif + return (int)h; + }" + HAVE_SSE42CRC_INLINE_ASM + ) + # Check whether compiler supports SSE4 CRC intrinsics + check_c_source_compile_or_run( + "#include + int main(void) { + unsigned crc = 0; + char c = 'c'; + #if defined(_MSC_VER) + crc = _mm_crc32_u32(crc, c); + #else + crc = __builtin_ia32_crc32qi(crc, c); + #endif + (void)crc; + return 0; + }" + HAVE_SSE42CRC_INTRIN + ) + # Check whether compiler supports SSE4.2 compare string instrinics + check_c_source_compile_or_run( + "#include + int main(void) { + unsigned char a[64] = { 0 }; + unsigned char b[64] = { 0 }; + __m128i xmm_src0, xmm_src1; + xmm_src0 = _mm_loadu_si128((__m128i *)(char *)a); + xmm_src1 = _mm_loadu_si128((__m128i *)(char *)b); + return _mm_cmpestri(xmm_src0, 16, xmm_src1, 16, 0); + }" + HAVE_SSE42CMPSTR_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() diff --git a/configure b/configure index 8cd48786ee..3e69da8976 100755 --- a/configure +++ b/configure @@ -972,76 +972,116 @@ else echo "Checking for __builtin_ctzll ... No." | tee -a configure.log fi -# Check for SSE2 intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF +check_avx2_intrinsics() { + # Check whether compiler supports AVX2 intrinsics + cat > $test.c << EOF #include int main(void) { - __m128i zero = _mm_setzero_si128(); - (void)zero; + __m256i x = _mm256_set1_epi16(2); + const __m256i y = _mm256_set1_epi16(1); + x = _mm256_subs_epu16(x, y); + (void)x; return 0; } EOF - if try ${CC} ${CFLAGS} ${sse2flag} $test.c; then - echo "Checking for SSE2 intrinsics ... Yes." | tee -a configure.log - HAVE_SSE2_INTRIN=1 - else - echo "Checking for SSE2 intrinsics ... No." | tee -a configure.log - HAVE_SSE2_INTRIN=0 - fi - ;; -esac + if try ${CC} ${CFLAGS} ${avx2flag} $test.c; then + echo "Checking for AVX2 intrinsics ... Yes." | tee -a configure.log + HAVE_AVX2_INTRIN=1 + else + echo "Checking for AVX2 intrinsics ... No." | tee -a configure.log + HAVE_AVX2_INTRIN=0 + fi +} -# Check for SSSE3 intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -#include -int main(void) -{ - __m128i u, v, w; - u = _mm_set1_epi32(1); - v = _mm_set1_epi32(2); - w = _mm_hadd_epi32(u, v); - (void)w; +check_neon_intrinsics() { + # Check whether -mfpu=neon is available on ARM processors. + cat > $test.c << EOF +int main() { return 0; } +EOF + if try $CC -c $CFLAGS -mfpu=neon $test.c; then + MFPU_NEON_AVAILABLE=1 + echo "Check whether -mfpu=neon is available ... Yes." | tee -a configure.log + else + MFPU_NEON_AVAILABLE=0 + echo "Check whether -mfpu=neon is available ... No." | tee -a configure.log + fi +} + +check_pclmulqdq_intrinsics() { + # Check whether compiler supports PCLMULQDQ intrinsics + cat > $test.c << EOF +#include +#include +int main(void) { + __m128i a = _mm_setzero_si128(); + __m128i b = _mm_setzero_si128(); + __m128i c = _mm_clmulepi64_si128(a, b, 0x10); + (void)c; return 0; } EOF - if try ${CC} ${CFLAGS} ${ssse3flag} $test.c; then - echo "Checking for SSSE3 intrinsics ... Yes." | tee -a configure.log - HAVE_SSSE3_INTRIN=1 - else - echo "Checking for SSSE3 intrinsics ... No." | tee -a configure.log - HAVE_SSSE3_INTRIN=0 - fi - ;; -esac + if try ${CC} ${CFLAGS} ${pclmulflag} $test.c; then + echo "Checking for PCLMULQDQ intrinsics ... Yes." | tee -a configure.log + HAVE_PCLMULQDQ_INTRIN=1 + else + echo "Checking for PCLMULQDQ intrinsics ... No." | tee -a configure.log + HAVE_PCLMULQDQ_INTRIN=0 + fi +} -# Check for SSE4.2 CRC inline assembly -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF +check_power8_intrinsics() { + # Check whether features needed by POWER optimisations are available + cat > $test.c << EOF +#include +int main() { return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); } +EOF + if try $CC -c $CFLAGS -mcpu=power8 $test.c; then + HAVE_POWER8_INTRIN=1 + echo "Check whether POWER8 instructions are available ... Yes." | tee -a configure.log + else + HAVE_POWER8_INTRIN=0 + echo "Check whether POWER8 instructions are available ... No." | tee -a configure.log + fi +} + +check_sse2_intrinsics() { + # Check whether compiler supports SSE2 intrinsics + cat > $test.c << EOF +#include +int main(void) { + __m128i zero = _mm_setzero_si128(); + (void)zero; + return 0; +} +EOF + if try ${CC} ${CFLAGS} ${sse2flag} $test.c; then + echo "Checking for SSE2 intrinsics ... Yes." | tee -a configure.log + HAVE_SSE2_INTRIN=1 + else + echo "Checking for SSE2 intrinsics ... No." | tee -a configure.log + HAVE_SSE2_INTRIN=0 + fi +} + +check_sse4_intrinsics() { + # Check whether compiler supports SSE4 CRC inline asm + cat > $test.c << EOF int main(void) { unsigned val = 0, h = 0; __asm__ __volatile__ ( "crc32 %1,%0" : "+r" (h) : "r" (val) ); return (int) h; } EOF - if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 CRC inline assembly ... Yes." | tee -a configure.log - HAVE_SSE42CRC_INLINE_ASM=1 - else - echo "Checking for SSE4.2 CRC inline assembly ... No." | tee -a configure.log - HAVE_SSE42CRC_INLINE_ASM=0 - fi - ;; -esac + if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then + echo "Checking for SSE4.2 CRC inline assembly ... Yes." | tee -a configure.log + HAVE_SSE42CRC_INLINE_ASM=1 + else + echo "Checking for SSE4.2 CRC inline assembly ... No." | tee -a configure.log + HAVE_SSE42CRC_INLINE_ASM=0 + fi -# Check for SSE4.2 CRC intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF + # Check whether compiler supports SSE4.2 CRC intrinsics + cat > $test.c << EOF int main(void) { unsigned crc = 0; char c = 'c'; @@ -1050,20 +1090,16 @@ int main(void) { return 0; } EOF - if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 CRC intrinsics ... Yes." | tee -a configure.log - HAVE_SSE42CRC_INTRIN=1 - else - echo "Checking for SSE4.2 CRC intrinsics ... No." | tee -a configure.log - HAVE_SSE42CRC_INTRIN=0 - fi - ;; -esac + if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then + echo "Checking for SSE4.2 CRC intrinsics ... Yes." | tee -a configure.log + HAVE_SSE42CRC_INTRIN=1 + else + echo "Checking for SSE4.2 CRC intrinsics ... No." | tee -a configure.log + HAVE_SSE42CRC_INTRIN=0 + fi -# Check for SSE4.2 compare string intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF + # Check whether compiler supports SSE4.2 compare string intrinsics + cat > $test.c << EOF #include int main(void) { @@ -1075,38 +1111,40 @@ int main(void) return _mm_cmpestri(xmm_src0, 16, xmm_src1, 16, 0); } EOF - if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then - echo "Checking for SSE4.2 compare string intrinsics ... Yes." | tee -a configure.log - HAVE_SSE42CMPSTR_INTRIN=1 - else - echo "Checking for SSE4.2 compare string intrinsics ... No." | tee -a configure.log - HAVE_SSE42CMPSTR_INTRIN=0 - fi - ;; -esac + if try ${CC} ${CFLAGS} ${sse42flag} $test.c; then + echo "Checking for SSE4.2 compare string intrinsics ... Yes." | tee -a configure.log + HAVE_SSE42CMPSTR_INTRIN=1 + else + echo "Checking for SSE4.2 compare string intrinsics ... No." | tee -a configure.log + HAVE_SSE42CMPSTR_INTRIN=0 + fi +} -# Check for PCLMULQDQ intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -#include -#include -int main(void) { - __m128i a = _mm_setzero_si128(); - __m128i b = _mm_setzero_si128(); - __m128i c = _mm_clmulepi64_si128(a, b, 0x10); - (void)c; +check_ssse3_intrinsics() { + # Check whether compiler supports SSSE3 intrinsics + cat > $test.c << EOF +#include +int main(void) +{ + __m128i u, v, w; + u = _mm_set1_epi32(1); + v = _mm_set1_epi32(2); + w = _mm_hadd_epi32(u, v); + (void)w; return 0; } EOF - if try ${CC} ${CFLAGS} ${pclmulflag} $test.c; then - echo "Checking for PCLMULQDQ intrinsics ... Yes." | tee -a configure.log - HAVE_PCLMULQDQ_INTRIN=1 - else - echo "Checking for PCLMULQDQ intrinsics ... No." | tee -a configure.log - HAVE_PCLMULQDQ_INTRIN=0 - fi + if try ${CC} ${CFLAGS} ${ssse3flag} $test.c; then + echo "Checking for SSSE3 intrinsics ... Yes." | tee -a configure.log + HAVE_SSSE3_INTRIN=1 + else + echo "Checking for SSSE3 intrinsics ... No." | tee -a configure.log + HAVE_SSSE3_INTRIN=0 + fi +} +case "${ARCH}" in + i386 | i486 | i586 | i686 | x86_64) # Enable deflate_medium at level 1 if test $without_new_strategies -eq 1; then CFLAGS="${CFLAGS} -DNO_QUICK_STRATEGY" @@ -1120,75 +1158,6 @@ EOF ;; esac -# Check for AVX2 intrinsics -case "${ARCH}" in - i386 | i486 | i586 | i686 | x86_64) - cat > $test.c << EOF -#include -int main(void) { - __m256i x = _mm256_set1_epi16(2); - const __m256i y = _mm256_set1_epi16(1); - x = _mm256_subs_epu16(x, y); - (void)x; - return 0; -} -EOF - if try ${CC} ${CFLAGS} ${avx2flag} $test.c; then - echo "Checking for AVX2 intrinsics ... Yes." | tee -a configure.log - HAVE_AVX2_INTRIN=1 - else - echo "Checking for AVX2 intrinsics ... No." | tee -a configure.log - HAVE_AVX2_INTRIN=0 - fi - ;; -esac - - -# Check whether -mfpu=neon is available on ARM processors. -case "${ARCH}" in - arm*) - cat > $test.c << EOF -int main() { return 0; } -EOF - if try $CC -c $CFLAGS -mfpu=neon $test.c; then - MFPU_NEON_AVAILABLE=1 - echo "Check whether -mfpu=neon is available ... Yes." | tee -a configure.log - else - MFPU_NEON_AVAILABLE=0 - echo "Check whether -mfpu=neon is available ... No." | tee -a configure.log - fi - ;; -esac - -# Check whether features needed by POWER optimisations are available -case "${ARCH}" in - powerpc*) - cat > $test.c << EOF -#include -int main() { return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); } -EOF - if try $CC -c $CFLAGS -mcpu=power8 $test.c; then - HAVE_POWER8=1 - echo "Check whether POWER8 instructions are available ... Yes." | tee -a configure.log - else - HAVE_POWER8=0 - echo "Check whether POWER8 instructions are available ... No." | tee -a configure.log - fi -esac - -# Check whether sys/sdt.h is available -cat > $test.c << EOF -#include -int main() { return 0; } -EOF -if try ${CC} ${CFLAGS} $test.c; then - echo "Checking for sys/sdt.h ... Yes." | tee -a configure.log - CFLAGS="$CFLAGS -DHAVE_SYS_SDT_H" - SFLAGS="$SFLAGS -DHAVE_SYS_SDT_H" -else - echo "Checking for sys/sdt.h ... No." | tee -a configure.log -fi - ARCHDIR='arch/generic' ARCH_STATIC_OBJS='' ARCH_SHARED_OBJS='' @@ -1210,6 +1179,8 @@ case "${ARCH}" in ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} x86.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} x86.lo" + check_avx2_intrinsics + if test ${HAVE_AVX2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" SFLAGS="${SFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" @@ -1217,6 +1188,8 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_avx.lo chunkset_avx.lo compare258_avx.lo adler32_avx.lo" fi + check_sse4_intrinsics + if test ${HAVE_SSE42CRC_INTRIN} -eq 1 || test ${HAVE_SSE42CRC_INLINE_ASM} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42_CRC_HASH" SFLAGS="${SFLAGS} -DX86_SSE42_CRC_HASH" @@ -1230,6 +1203,8 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse.lo" fi + check_sse4_intrinsics + if test ${HAVE_SSE42CMPSTR_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42_CMP_STR" SFLAGS="${SFLAGS} -DX86_SSE42_CMP_STR" @@ -1238,6 +1213,8 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} compare258_sse.lo" fi + check_sse2_intrinsics + if test ${HAVE_SSE2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" SFLAGS="${SFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" @@ -1250,6 +1227,8 @@ case "${ARCH}" in fi fi + check_ssse3_intrinsics + if test ${HAVE_SSSE3_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSSE3 -DX86_SSSE3_ADLER32" SFLAGS="${SFLAGS} -DX86_SSSE3 -DX86_SSSE3_ADLER32" @@ -1257,6 +1236,8 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_ssse3.lo" fi + check_pclmulqdq_intrinsics + if test ${HAVE_PCLMULQDQ_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_PCLMULQDQ_CRC" SFLAGS="${SFLAGS} -DX86_PCLMULQDQ_CRC" @@ -1351,6 +1332,10 @@ EOF SFLAGS="${SFLAGS} ${floatabi}" fi + if test $without_optimizations -eq 0; then + check_neon_intrinsics + fi + case "${ARCH}" in armv[345]*) if test $without_optimizations -eq 0; then @@ -1527,7 +1512,10 @@ EOF ARCHDIR=arch/power if test $without_optimizations -eq 0; then - if test $HAVE_POWER8 -eq 1; then + + check_power8_intrinsics + + if test $HAVE_POWER8_INTRIN -eq 1; then CFLAGS="${CFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_SLIDEHASH" SFLAGS="${SFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_SLIDEHASH" From e56238cbc4433b71b75f08deac35addb8426fef6 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 22 Mar 2021 18:33:50 -0700 Subject: [PATCH 070/798] Print architecture-specific static and shared object files in configure script similar to CMake. --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 3e69da8976..2bf16198b8 100755 --- a/configure +++ b/configure @@ -1558,6 +1558,8 @@ esac echo "ARCH: ${ARCH}" echo "Using arch directory: ${ARCHDIR}" +echo "Architecture-specific static object files:${ARCH_STATIC_OBJS}" +echo "Architecture-specific shared object files:${ARCH_SHARED_OBJS}" # show the results in the log echo >> configure.log From cf9127a2311eda5803ff9a84a8ce4089163034b8 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 10 May 2021 16:48:29 +0200 Subject: [PATCH 071/798] Separate MIN_MATCH into STD_MIN_MATCH and WANT_MIN_MATCH Rename MAX_MATCH to STD_MAX_MATCH --- deflate.c | 29 +++++++++++++---------------- deflate.h | 10 +++++----- deflate_fast.c | 26 +++++++++++++------------- deflate_medium.c | 36 ++++++++++++++++++------------------ deflate_p.h | 6 +++--- deflate_quick.c | 8 ++++---- deflate_rle.c | 18 +++++++++--------- deflate_slow.c | 20 ++++++++++---------- insert_string_tpl.h | 4 ++-- match_tpl.h | 4 ++-- tools/maketrees.c | 12 ++++++------ trees_emit.h | 4 ++-- trees_tbl.h | 2 +- zutil.h | 9 ++++++--- 14 files changed, 94 insertions(+), 94 deletions(-) diff --git a/deflate.c b/deflate.c index dd1f120c4d..f95c6859af 100644 --- a/deflate.c +++ b/deflate.c @@ -167,7 +167,7 @@ static const config configuration_table[10] = { /* 8 */ {32, 128, 258, 1024, deflate_slow}, /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 +/* Note: the deflate() code requires max_lazy >= STD_MIN_MATCH and max_chain >= 4 * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ @@ -431,19 +431,19 @@ int32_t Z_EXPORT PREFIX(deflateSetDictionary)(PREFIX3(stream) *strm, const uint8 strm->avail_in = dictLength; strm->next_in = (z_const unsigned char *)dictionary; fill_window(s); - while (s->lookahead >= MIN_MATCH) { + while (s->lookahead >= STD_MIN_MATCH) { str = s->strstart; - n = s->lookahead - (MIN_MATCH-1); + n = s->lookahead - (STD_MIN_MATCH-1); functable.insert_string(s, str, n); s->strstart = str + n; - s->lookahead = MIN_MATCH-1; + s->lookahead = STD_MIN_MATCH-1; fill_window(s); } s->strstart += s->lookahead; s->block_start = (int)s->strstart; s->insert = s->lookahead; s->lookahead = 0; - s->prev_length = MIN_MATCH-1; + s->prev_length = STD_MIN_MATCH-1; s->match_available = 0; strm->next_in = (z_const unsigned char *)next; strm->avail_in = avail; @@ -1160,7 +1160,7 @@ static void lm_init(deflate_state *s) { s->block_start = 0; s->lookahead = 0; s->insert = 0; - s->prev_length = MIN_MATCH-1; + s->prev_length = STD_MIN_MATCH-1; s->match_available = 0; s->match_start = 0; } @@ -1224,17 +1224,16 @@ void Z_INTERNAL fill_window(deflate_state *s) { s->lookahead += n; /* Initialize the hash value now that we have some input: */ - if (s->lookahead + s->insert >= MIN_MATCH) { + if (s->lookahead + s->insert >= STD_MIN_MATCH) { unsigned int str = s->strstart - s->insert; if (str >= 1) - functable.quick_insert_string(s, str + 2 - MIN_MATCH); -#if MIN_MATCH != 3 -#error Call insert_string() MIN_MATCH-3 more times + functable.quick_insert_string(s, str + 2 - STD_MIN_MATCH); +#if STD_MIN_MATCH != 3 while (s->insert) { functable.quick_insert_string(s, str); str++; s->insert--; - if (s->lookahead + s->insert < MIN_MATCH) + if (s->lookahead + s->insert < STD_MIN_MATCH) break; } #else @@ -1250,7 +1249,7 @@ void Z_INTERNAL fill_window(deflate_state *s) { } #endif } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + /* If the whole input has less than STD_MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. */ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); @@ -1259,8 +1258,8 @@ void Z_INTERNAL fill_window(deflate_state *s) { * written, then zero those bytes in order to avoid memory check reports of * the use of uninitialized (or uninitialised as Julian writes) bytes by * the longest match routines. Update the high water mark for the next - * time through here. WIN_INIT is set to MAX_MATCH since the longest match - * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + * time through here. WIN_INIT is set to STD_MAX_MATCH since the longest match + * routines allow scanning to strstart + STD_MAX_MATCH, ignoring lookahead. */ if (s->high_water < s->window_size) { unsigned int curr = s->strstart + s->lookahead; @@ -1292,8 +1291,6 @@ void Z_INTERNAL fill_window(deflate_state *s) { "not enough room for search"); } - - #ifndef ZLIB_COMPAT /* ========================================================================= * Checks whether buffer size is sufficient and whether this parameter is a duplicate. diff --git a/deflate.h b/deflate.h index 7243d1d9d8..cf7d490616 100644 --- a/deflate.h +++ b/deflate.h @@ -141,7 +141,7 @@ typedef struct internal_state { /* Sliding window. Input bytes are read into the second half of the window, * and move to the first half later to keep a dictionary of at least wSize * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always + * wSize-STD_MAX_MATCH bytes, but this ensures that IO is always * performed with a length multiple of the block size. Also, it limits * the window size to 64K, which is quite useful on MSDOS. * To do: use the user input buffer as sliding window. @@ -363,17 +363,17 @@ static inline void put_uint64(deflate_state *s, uint64_t lld) { #endif } -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +#define MIN_LOOKAHEAD (STD_MAX_MATCH + STD_MIN_MATCH + 1) /* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. + * See deflate.c for comments about the STD_MIN_MATCH+1. */ -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +#define MAX_DIST(s) ((s)->w_size - MIN_LOOKAHEAD) /* In order to simplify the code, particularly on 16 bit machines, match * distances are limited to MAX_DIST instead of WSIZE. */ -#define WIN_INIT MAX_MATCH +#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/deflate_fast.c b/deflate_fast.c index 1594886f8c..4d335a3dc6 100644 --- a/deflate_fast.c +++ b/deflate_fast.c @@ -24,8 +24,8 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { for (;;) { /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the + * at the end of the input file. We need STD_MAX_MATCH bytes + * for the next match, plus WANT_MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { @@ -40,14 +40,14 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ - if (s->lookahead >= MIN_MATCH) { + if (s->lookahead >= WANT_MIN_MATCH) { hash_head = functable.quick_insert_string(s, s->strstart); dist = (int64_t)s->strstart - hash_head; /* Find the longest match, discarding those <= prev_length. - * At this point we have always match length < MIN_MATCH + * At this point we have always match length < WANT_MIN_MATCH */ - + if (dist <= MAX_DIST(s) && dist > 0 && hash_head != 0) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match @@ -58,17 +58,17 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { } } - if (match_len >= MIN_MATCH) { + if (match_len >= WANT_MIN_MATCH) { check_match(s, s->strstart, s->match_start, match_len); - bflush = zng_tr_tally_dist(s, s->strstart - s->match_start, match_len - MIN_MATCH); + bflush = zng_tr_tally_dist(s, s->strstart - s->match_start, match_len - STD_MIN_MATCH); s->lookahead -= match_len; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ - if (match_len <= s->max_insert_length && s->lookahead >= MIN_MATCH) { + if (match_len <= s->max_insert_length && s->lookahead >= WANT_MIN_MATCH) { match_len--; /* string at strstart already in table */ s->strstart++; @@ -76,12 +76,12 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { s->strstart += match_len; } else { s->strstart += match_len; -#if MIN_MATCH != 3 - functable.insert_string(s, s->strstart + 2 - MIN_MATCH, MIN_MATCH - 2); +#if STD_MIN_MATCH != 3 + functable.insert_string(s, s->strstart + 2 - STD_MIN_MATCH, STD_MIN_MATCH - 2); #else - functable.quick_insert_string(s, s->strstart + 2 - MIN_MATCH); + functable.quick_insert_string(s, s->strstart + 2 - STD_MIN_MATCH); #endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + /* If lookahead < STD_MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } @@ -95,7 +95,7 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { if (UNLIKELY(bflush)) FLUSH_BLOCK(s, 0); } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + s->insert = s->strstart < STD_MIN_MATCH-1 ? s->strstart : STD_MIN_MATCH-1; if (UNLIKELY(flush == Z_FINISH)) { FLUSH_BLOCK(s, 1); return finish_done; diff --git a/deflate_medium.c b/deflate_medium.c index 303890a651..25f3a0b183 100644 --- a/deflate_medium.c +++ b/deflate_medium.c @@ -24,7 +24,7 @@ static int emit_match(deflate_state *s, struct match match) { int bflush = 0; /* matches that are not long enough we need to emit as literals */ - if (match.match_length < MIN_MATCH) { + if (match.match_length < WANT_MIN_MATCH) { while (match.match_length) { bflush += zng_tr_tally_lit(s, s->window[match.strstart]); s->lookahead--; @@ -36,18 +36,18 @@ static int emit_match(deflate_state *s, struct match match) { check_match(s, match.strstart, match.match_start, match.match_length); - bflush += zng_tr_tally_dist(s, match.strstart - match.match_start, match.match_length - MIN_MATCH); + bflush += zng_tr_tally_dist(s, match.strstart - match.match_start, match.match_length - STD_MIN_MATCH); s->lookahead -= match.match_length; return bflush; } static void insert_match(deflate_state *s, struct match match) { - if (UNLIKELY(s->lookahead <= (unsigned int)(match.match_length + MIN_MATCH))) + if (UNLIKELY(s->lookahead <= (unsigned int)(match.match_length + WANT_MIN_MATCH))) return; /* matches that are not long enough we need to emit as literals */ - if (LIKELY(match.match_length < MIN_MATCH)) { + if (LIKELY(match.match_length < WANT_MIN_MATCH)) { match.strstart++; match.match_length--; if (UNLIKELY(match.match_length > 0)) { @@ -67,7 +67,7 @@ static void insert_match(deflate_state *s, struct match match) { /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ - if (match.match_length <= 16* s->max_insert_length && s->lookahead >= MIN_MATCH) { + if (match.match_length <= 16* s->max_insert_length && s->lookahead >= WANT_MIN_MATCH) { match.match_length--; /* string at strstart already in table */ match.strstart++; @@ -85,13 +85,13 @@ static void insert_match(deflate_state *s, struct match match) { } else { match.strstart += match.match_length; match.match_length = 0; - if (match.strstart >= (MIN_MATCH - 2)) -#if MIN_MATCH != 3 - functable.insert_string(s, match.strstart + 2 - MIN_MATCH, MIN_MATCH - 2); + if (match.strstart >= (STD_MIN_MATCH - 2)) +#if STD_MIN_MATCH != 3 + functable.insert_string(s, match.strstart + 2 - STD_MIN_MATCH, STD_MIN_MATCH - 2); #else - functable.quick_insert_string(s, match.strstart + 2 - MIN_MATCH); + functable.quick_insert_string(s, match.strstart + 2 - STD_MIN_MATCH); #endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + /* If lookahead < WANT_MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } @@ -177,8 +177,8 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { int64_t dist; /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the + * at the end of the input file. We need STD_MAX_MATCH bytes + * for the next match, plus WANT_MIN_MATCH bytes to insert the * string following the next current_match. */ if (s->lookahead < MIN_LOOKAHEAD) { @@ -201,7 +201,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { next_match.match_length = 0; } else { hash_head = 0; - if (s->lookahead >= MIN_MATCH) { + if (s->lookahead >= WANT_MIN_MATCH) { hash_head = functable.quick_insert_string(s, s->strstart); } @@ -209,7 +209,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { current_match.orgstart = current_match.strstart; /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH + * At this point we have always match_length < WANT_MIN_MATCH */ dist = (int64_t)s->strstart - hash_head; @@ -220,7 +220,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { */ current_match.match_length = (uint16_t)functable.longest_match(s, hash_head); current_match.match_start = (uint16_t)s->match_start; - if (UNLIKELY(current_match.match_length < MIN_MATCH)) + if (UNLIKELY(current_match.match_length < WANT_MIN_MATCH)) current_match.match_length = 1; if (UNLIKELY(current_match.match_start >= current_match.strstart)) { /* this can happen due to some restarts */ @@ -244,7 +244,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { next_match.orgstart = next_match.strstart; /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH + * At this point we have always match_length < WANT_MIN_MATCH */ dist = (int64_t)s->strstart - hash_head; @@ -259,7 +259,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { /* this can happen due to some restarts */ next_match.match_length = 1; } - if (next_match.match_length < MIN_MATCH) + if (next_match.match_length < WANT_MIN_MATCH) next_match.match_length = 1; else fizzle_matches(s, ¤t_match, &next_match); @@ -283,7 +283,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { if (UNLIKELY(bflush)) FLUSH_BLOCK(s, 0); } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + s->insert = s->strstart < STD_MIN_MATCH-1 ? s->strstart : STD_MIN_MATCH-1; if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; diff --git a/deflate_p.h b/deflate_p.h index becaf71e3e..9b23c51eba 100644 --- a/deflate_p.h +++ b/deflate_p.h @@ -17,7 +17,7 @@ */ static inline void check_match(deflate_state *s, Pos start, Pos match, int length) { /* check that the match length is valid*/ - if (length < MIN_MATCH || length > MAX_MATCH) { + if (length < STD_MIN_MATCH || length > STD_MAX_MATCH) { fprintf(stderr, " start %u, match %u, length %d\n", start, match, length); z_error("invalid match length"); } @@ -65,13 +65,13 @@ static inline int zng_tr_tally_lit(deflate_state *s, unsigned char c) { s->sym_buf[s->sym_next++] = c; s->dyn_ltree[c].Freq++; Tracevv((stderr, "%c", c)); - Assert(c <= (MAX_MATCH-MIN_MATCH), "zng_tr_tally: bad literal"); + Assert(c <= (STD_MAX_MATCH-STD_MIN_MATCH), "zng_tr_tally: bad literal"); return (s->sym_next == s->sym_end); } static inline int zng_tr_tally_dist(deflate_state *s, uint32_t dist, uint32_t len) { /* dist: distance of matched string */ - /* len: match length-MIN_MATCH */ + /* len: match length-STD_MIN_MATCH */ s->sym_buf[s->sym_next++] = (uint8_t)(dist); s->sym_buf[s->sym_next++] = (uint8_t)(dist >> 8); s->sym_buf[s->sym_next++] = (uint8_t)len; diff --git a/deflate_quick.c b/deflate_quick.c index b439743498..50e861cceb 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -84,20 +84,20 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { } } - if (LIKELY(s->lookahead >= MIN_MATCH)) { + if (LIKELY(s->lookahead >= WANT_MIN_MATCH)) { hash_head = functable.quick_insert_string(s, s->strstart); dist = (int64_t)s->strstart - hash_head; if (dist <= MAX_DIST(s) && dist > 0) { match_len = functable.compare258(s->window + s->strstart, s->window + hash_head); - if (match_len >= MIN_MATCH) { + if (match_len >= WANT_MIN_MATCH) { if (UNLIKELY(match_len > s->lookahead)) match_len = s->lookahead; check_match(s, s->strstart, hash_head, match_len); - zng_tr_emit_dist(s, static_ltree, static_dtree, match_len - MIN_MATCH, (uint32_t)dist); + zng_tr_emit_dist(s, static_ltree, static_dtree, match_len - STD_MIN_MATCH, (uint32_t)dist); s->lookahead -= match_len; s->strstart += match_len; continue; @@ -110,7 +110,7 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { s->lookahead--; } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + s->insert = s->strstart < STD_MIN_MATCH-1 ? s->strstart : STD_MIN_MATCH-1; if (UNLIKELY(last)) { QUICK_END_BLOCK(s, 1); return finish_done; diff --git a/deflate_rle.c b/deflate_rle.c index c3899b7751..9e669ec545 100644 --- a/deflate_rle.c +++ b/deflate_rle.c @@ -22,40 +22,40 @@ Z_INTERNAL block_state deflate_rle(deflate_state *s, int flush) { for (;;) { /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes + * at the end of the input file. We need STD_MAX_MATCH bytes * for the longest run, plus one for the unrolled loop. */ - if (s->lookahead <= MAX_MATCH) { + if (s->lookahead <= STD_MAX_MATCH) { fill_window(s); - if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) + if (s->lookahead <= STD_MAX_MATCH && flush == Z_NO_FLUSH) return need_more; if (s->lookahead == 0) break; /* flush the current block */ } /* See how many times the previous byte repeats */ - if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + if (s->lookahead >= STD_MIN_MATCH && s->strstart > 0) { scan = s->window + s->strstart - 1; prev = *scan; if (prev == *++scan && prev == *++scan && prev == *++scan) { - strend = s->window + s->strstart + MAX_MATCH; + strend = s->window + s->strstart + STD_MAX_MATCH; do { } while (prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); - match_len = MAX_MATCH - (unsigned int)(strend - scan); + match_len = STD_MAX_MATCH - (unsigned int)(strend - scan); match_len = MIN(match_len, s->lookahead); } Assert(scan <= s->window + s->window_size - 1, "wild scan"); } - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (match_len >= MIN_MATCH) { + /* Emit match if have run of STD_MIN_MATCH or longer, else emit literal */ + if (match_len >= STD_MIN_MATCH) { check_match(s, s->strstart, s->strstart - 1, match_len); - bflush = zng_tr_tally_dist(s, 1, match_len - MIN_MATCH); + bflush = zng_tr_tally_dist(s, 1, match_len - STD_MIN_MATCH); s->lookahead -= match_len; s->strstart += match_len; diff --git a/deflate_slow.c b/deflate_slow.c index dc1c072391..d97eb2c974 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -23,8 +23,8 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { /* Process the input block. */ for (;;) { /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the + * at the end of the input file. We need STD_MAX_MATCH bytes + * for the next match, plus WANT_MIN_MATCH bytes to insert the * string following the next match. */ if (s->lookahead < MIN_LOOKAHEAD) { @@ -40,14 +40,14 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { * dictionary, and set hash_head to the head of the hash chain: */ hash_head = 0; - if (LIKELY(s->lookahead >= MIN_MATCH)) { + if (LIKELY(s->lookahead >= WANT_MIN_MATCH)) { hash_head = functable.quick_insert_string(s, s->strstart); } /* Find the longest match, discarding those <= prev_length. */ s->prev_match = (Pos)s->match_start; - match_len = MIN_MATCH-1; + match_len = STD_MIN_MATCH-1; dist = (int64_t)s->strstart - hash_head; if (dist <= MAX_DIST(s) && dist > 0 && s->prev_length < s->max_lazy_match && hash_head != 0) { @@ -59,22 +59,22 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { /* longest_match() sets match_start */ if (match_len <= 5 && (s->strategy == Z_FILTERED)) { - /* If prev_match is also MIN_MATCH, match_start is garbage + /* If prev_match is also WANT_MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ - match_len = MIN_MATCH-1; + match_len = STD_MIN_MATCH-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ - if (s->prev_length >= MIN_MATCH && match_len <= s->prev_length) { - unsigned int max_insert = s->strstart + s->lookahead - MIN_MATCH; + if (s->prev_length >= WANT_MIN_MATCH && match_len <= s->prev_length) { + unsigned int max_insert = s->strstart + s->lookahead - WANT_MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart-1, s->prev_match, s->prev_length); - bflush = zng_tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - MIN_MATCH); + bflush = zng_tr_tally_dist(s, s->strstart -1 - s->prev_match, s->prev_length - STD_MIN_MATCH); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not @@ -126,7 +126,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { (void) zng_tr_tally_lit(s, s->window[s->strstart-1]); s->match_available = 0; } - s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + s->insert = s->strstart < STD_MIN_MATCH-1 ? s->strstart : STD_MIN_MATCH-1; if (UNLIKELY(flush == Z_FINISH)) { FLUSH_BLOCK(s, 1); return finish_done; diff --git a/insert_string_tpl.h b/insert_string_tpl.h index 9796e5196c..11d54643fe 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -57,8 +57,8 @@ Z_INTERNAL Pos QUICK_INSERT_STRING(deflate_state *const s, const uint32_t str) { * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). + * input characters and the first STD_MIN_MATCH bytes of str are valid + * (except for the last STD_MIN_MATCH-1 bytes of the input file). */ Z_INTERNAL void INSERT_STRING(deflate_state *const s, const uint32_t str, uint32_t count) { uint8_t *strstart = s->window + str; diff --git a/match_tpl.h b/match_tpl.h index b15ca17b91..04eac1aa8f 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -52,8 +52,8 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { continue; \ return best_len; - /* The code is optimized for MAX_MATCH-2 multiple of 16. */ - Assert(MAX_MATCH == 258, "Code too clever"); + /* The code is optimized for STD_MAX_MATCH-2 multiple of 16. */ + Assert(STD_MAX_MATCH == 258, "Code too clever"); best_len = s->prev_length ? s->prev_length : 1; diff --git a/tools/maketrees.c b/tools/maketrees.c index c648a650c8..282bddc2e5 100644 --- a/tools/maketrees.c +++ b/tools/maketrees.c @@ -23,11 +23,11 @@ static unsigned char dist_code[DIST_CODE_LEN]; * the last 256 values correspond to the top 8 bits of the 15 bit distances. */ -static unsigned char length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ +static unsigned char length_code[STD_MAX_MATCH-STD_MIN_MATCH+1]; +/* length code for each normalized match length (0 == STD_MIN_MATCH) */ static int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ +/* First normalized length for each code (0 = STD_MIN_MATCH) */ static int base_dist[D_CODES]; /* First normalized distance for each code (0 = distance of 1) */ @@ -121,9 +121,9 @@ static void gen_trees_header() { printf("%2u%s", dist_code[i], SEPARATOR(i, DIST_CODE_LEN-1, 20)); } - printf("const unsigned char Z_INTERNAL zng_length_code[MAX_MATCH-MIN_MATCH+1] = {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - printf("%2u%s", length_code[i], SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + printf("const unsigned char Z_INTERNAL zng_length_code[STD_MAX_MATCH-STD_MIN_MATCH+1] = {\n"); + for (i = 0; i < STD_MAX_MATCH-STD_MIN_MATCH+1; i++) { + printf("%2u%s", length_code[i], SEPARATOR(i, STD_MAX_MATCH-STD_MIN_MATCH, 20)); } printf("Z_INTERNAL const int base_length[LENGTH_CODES] = {\n"); diff --git a/trees_emit.h b/trees_emit.h index 118dbb2d8f..454488edb3 100644 --- a/trees_emit.h +++ b/trees_emit.h @@ -16,7 +16,7 @@ extern Z_INTERNAL const ct_data static_ltree[L_CODES+2]; extern Z_INTERNAL const ct_data static_dtree[D_CODES]; extern const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN]; -extern const unsigned char Z_INTERNAL zng_length_code[MAX_MATCH-MIN_MATCH+1]; +extern const unsigned char Z_INTERNAL zng_length_code[STD_MAX_MATCH-STD_MIN_MATCH+1]; extern Z_INTERNAL const int base_length[LENGTH_CODES]; extern Z_INTERNAL const int base_dist[D_CODES]; @@ -126,7 +126,7 @@ static inline uint32_t zng_emit_dist(deflate_state *s, const ct_data *ltree, con uint32_t bi_valid = s->bi_valid; uint64_t bi_buf = s->bi_buf; - /* Send the length code, len is the match length - MIN_MATCH */ + /* Send the length code, len is the match length - STD_MIN_MATCH */ code = zng_length_code[lc]; c = code+LITERALS+1; Assert(c < L_CODES, "bad l_code"); diff --git a/trees_tbl.h b/trees_tbl.h index a4c68a5665..a3912b7fd7 100644 --- a/trees_tbl.h +++ b/trees_tbl.h @@ -102,7 +102,7 @@ const unsigned char Z_INTERNAL zng_dist_code[DIST_CODE_LEN] = { 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 }; -const unsigned char Z_INTERNAL zng_length_code[MAX_MATCH-MIN_MATCH+1] = { +const unsigned char Z_INTERNAL zng_length_code[STD_MAX_MATCH-STD_MIN_MATCH+1] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, diff --git a/zutil.h b/zutil.h index 11e4875761..fa08f2aa78 100644 --- a/zutil.h +++ b/zutil.h @@ -70,9 +70,12 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ #define DYN_TREES 2 /* The three kinds of block type */ -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ +#define STD_MIN_MATCH 3 +#define STD_MAX_MATCH 258 +/* The minimum and maximum match lengths mandated by the deflate standard */ + +#define WANT_MIN_MATCH 4 +/* The minimum wanted match length, affects deflate_quick, deflate_fast, deflate_medium and deflate_slow */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ From 6bea8508876f8b712f26a4130158f79e5e1fa6e0 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 10 May 2021 17:11:54 +0200 Subject: [PATCH 072/798] Minor formatting changes related to MIN_MATCH/MAX_MATCH --- deflate.c | 8 ++++---- deflate_fast.c | 2 +- deflate_medium.c | 4 ++-- deflate_quick.c | 2 +- deflate_slow.c | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/deflate.c b/deflate.c index f95c6859af..73cd58a448 100644 --- a/deflate.c +++ b/deflate.c @@ -433,17 +433,17 @@ int32_t Z_EXPORT PREFIX(deflateSetDictionary)(PREFIX3(stream) *strm, const uint8 fill_window(s); while (s->lookahead >= STD_MIN_MATCH) { str = s->strstart; - n = s->lookahead - (STD_MIN_MATCH-1); + n = s->lookahead - (STD_MIN_MATCH - 1); functable.insert_string(s, str, n); s->strstart = str + n; - s->lookahead = STD_MIN_MATCH-1; + s->lookahead = STD_MIN_MATCH - 1; fill_window(s); } s->strstart += s->lookahead; s->block_start = (int)s->strstart; s->insert = s->lookahead; s->lookahead = 0; - s->prev_length = STD_MIN_MATCH-1; + s->prev_length = STD_MIN_MATCH - 1; s->match_available = 0; strm->next_in = (z_const unsigned char *)next; strm->avail_in = avail; @@ -1160,7 +1160,7 @@ static void lm_init(deflate_state *s) { s->block_start = 0; s->lookahead = 0; s->insert = 0; - s->prev_length = STD_MIN_MATCH-1; + s->prev_length = STD_MIN_MATCH - 1; s->match_available = 0; s->match_start = 0; } diff --git a/deflate_fast.c b/deflate_fast.c index 4d335a3dc6..074e9676be 100644 --- a/deflate_fast.c +++ b/deflate_fast.c @@ -95,7 +95,7 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { if (UNLIKELY(bflush)) FLUSH_BLOCK(s, 0); } - s->insert = s->strstart < STD_MIN_MATCH-1 ? s->strstart : STD_MIN_MATCH-1; + s->insert = s->strstart < (STD_MIN_MATCH - 1) ? s->strstart : (STD_MIN_MATCH - 1); if (UNLIKELY(flush == Z_FINISH)) { FLUSH_BLOCK(s, 1); return finish_done; diff --git a/deflate_medium.c b/deflate_medium.c index 25f3a0b183..71eb48350e 100644 --- a/deflate_medium.c +++ b/deflate_medium.c @@ -67,7 +67,7 @@ static void insert_match(deflate_state *s, struct match match) { /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ - if (match.match_length <= 16* s->max_insert_length && s->lookahead >= WANT_MIN_MATCH) { + if (match.match_length <= 16 * s->max_insert_length && s->lookahead >= WANT_MIN_MATCH) { match.match_length--; /* string at strstart already in table */ match.strstart++; @@ -283,7 +283,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush) { if (UNLIKELY(bflush)) FLUSH_BLOCK(s, 0); } - s->insert = s->strstart < STD_MIN_MATCH-1 ? s->strstart : STD_MIN_MATCH-1; + s->insert = s->strstart < (STD_MIN_MATCH - 1) ? s->strstart : (STD_MIN_MATCH - 1); if (flush == Z_FINISH) { FLUSH_BLOCK(s, 1); return finish_done; diff --git a/deflate_quick.c b/deflate_quick.c index 50e861cceb..8b98397161 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -110,7 +110,7 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { s->lookahead--; } - s->insert = s->strstart < STD_MIN_MATCH-1 ? s->strstart : STD_MIN_MATCH-1; + s->insert = s->strstart < (STD_MIN_MATCH - 1) ? s->strstart : (STD_MIN_MATCH - 1); if (UNLIKELY(last)) { QUICK_END_BLOCK(s, 1); return finish_done; diff --git a/deflate_slow.c b/deflate_slow.c index d97eb2c974..ac7e87ee50 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -47,7 +47,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { /* Find the longest match, discarding those <= prev_length. */ s->prev_match = (Pos)s->match_start; - match_len = STD_MIN_MATCH-1; + match_len = STD_MIN_MATCH - 1; dist = (int64_t)s->strstart - hash_head; if (dist <= MAX_DIST(s) && dist > 0 && s->prev_length < s->max_lazy_match && hash_head != 0) { @@ -62,7 +62,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { /* If prev_match is also WANT_MIN_MATCH, match_start is garbage * but we will ignore the current match anyway. */ - match_len = STD_MIN_MATCH-1; + match_len = STD_MIN_MATCH - 1; } } /* If there was a match at the previous step and the current @@ -126,7 +126,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { (void) zng_tr_tally_lit(s, s->window[s->strstart-1]); s->match_available = 0; } - s->insert = s->strstart < STD_MIN_MATCH-1 ? s->strstart : STD_MIN_MATCH-1; + s->insert = s->strstart < (STD_MIN_MATCH - 1) ? s->strstart : (STD_MIN_MATCH - 1); if (UNLIKELY(flush == Z_FINISH)) { FLUSH_BLOCK(s, 1); return finish_done; From 94fd14ede7c17f88edd5bccb620ec4fea2dd0dbb Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 10 May 2021 18:29:40 +0200 Subject: [PATCH 073/798] Remove support for STD_MIN_MATCH != 3. It has always been broken and untested anyways. --- deflate.c | 10 ---------- deflate_fast.c | 5 +---- deflate_medium.c | 6 ++---- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/deflate.c b/deflate.c index 73cd58a448..87ab646292 100644 --- a/deflate.c +++ b/deflate.c @@ -1228,15 +1228,6 @@ void Z_INTERNAL fill_window(deflate_state *s) { unsigned int str = s->strstart - s->insert; if (str >= 1) functable.quick_insert_string(s, str + 2 - STD_MIN_MATCH); -#if STD_MIN_MATCH != 3 - while (s->insert) { - functable.quick_insert_string(s, str); - str++; - s->insert--; - if (s->lookahead + s->insert < STD_MIN_MATCH) - break; - } -#else unsigned int count; if (UNLIKELY(s->lookahead == 1)) { count = s->insert - 1; @@ -1247,7 +1238,6 @@ void Z_INTERNAL fill_window(deflate_state *s) { functable.insert_string(s, str, count); s->insert -= count; } -#endif } /* If the whole input has less than STD_MIN_MATCH bytes, ins_h is garbage, * but this is not important since only literal bytes will be emitted. diff --git a/deflate_fast.c b/deflate_fast.c index 074e9676be..4142a7aa4c 100644 --- a/deflate_fast.c +++ b/deflate_fast.c @@ -76,11 +76,8 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { s->strstart += match_len; } else { s->strstart += match_len; -#if STD_MIN_MATCH != 3 - functable.insert_string(s, s->strstart + 2 - STD_MIN_MATCH, STD_MIN_MATCH - 2); -#else functable.quick_insert_string(s, s->strstart + 2 - STD_MIN_MATCH); -#endif + /* If lookahead < STD_MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ diff --git a/deflate_medium.c b/deflate_medium.c index 71eb48350e..c8d3e7701f 100644 --- a/deflate_medium.c +++ b/deflate_medium.c @@ -85,12 +85,10 @@ static void insert_match(deflate_state *s, struct match match) { } else { match.strstart += match.match_length; match.match_length = 0; + if (match.strstart >= (STD_MIN_MATCH - 2)) -#if STD_MIN_MATCH != 3 - functable.insert_string(s, match.strstart + 2 - STD_MIN_MATCH, STD_MIN_MATCH - 2); -#else functable.quick_insert_string(s, match.strstart + 2 - STD_MIN_MATCH); -#endif + /* If lookahead < WANT_MIN_MATCH, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ From d7cac887af1f15833590ed8eb1de4eceb849249f Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Tue, 11 May 2021 13:56:35 +0200 Subject: [PATCH 074/798] Initialize s->prev_length to 0. --- deflate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deflate.c b/deflate.c index 87ab646292..695822ec31 100644 --- a/deflate.c +++ b/deflate.c @@ -443,7 +443,7 @@ int32_t Z_EXPORT PREFIX(deflateSetDictionary)(PREFIX3(stream) *strm, const uint8 s->block_start = (int)s->strstart; s->insert = s->lookahead; s->lookahead = 0; - s->prev_length = STD_MIN_MATCH - 1; + s->prev_length = 0; s->match_available = 0; strm->next_in = (z_const unsigned char *)next; strm->avail_in = avail; @@ -1160,7 +1160,7 @@ static void lm_init(deflate_state *s) { s->block_start = 0; s->lookahead = 0; s->insert = 0; - s->prev_length = STD_MIN_MATCH - 1; + s->prev_length = 0; s->match_available = 0; s->match_start = 0; } From 3f5801f151ce9ab74664e9b286ad3edaa5b12d7e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 4 Jun 2021 19:46:33 -0700 Subject: [PATCH 075/798] Use MIN and MAX macros. --- deflate.c | 7 +++---- deflate_stored.c | 4 ++-- infback.c | 7 +++---- inflate.c | 20 +++++++------------- inftrees.c | 4 ++-- zbuild.h | 2 ++ 6 files changed, 19 insertions(+), 25 deletions(-) diff --git a/deflate.c b/deflate.c index 695822ec31..e512e5e9df 100644 --- a/deflate.c +++ b/deflate.c @@ -552,8 +552,8 @@ int32_t Z_EXPORT PREFIX(deflatePrime)(PREFIX3(stream) *strm, int32_t bits, int32 return Z_BUF_ERROR; do { put = BIT_BUF_SIZE - s->bi_valid; - if (put > bits) - put = bits; + put = MIN(put, bits); + if (s->bi_valid == 0) s->bi_buf = value64; else @@ -1117,8 +1117,7 @@ int32_t Z_EXPORT PREFIX(deflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size) { uint32_t len = strm->avail_in; - if (len > size) - len = size; + len = MIN(len, size); if (len == 0) return 0; diff --git a/deflate_stored.c b/deflate_stored.c index 860d894ddd..92e57fad80 100644 --- a/deflate_stored.c +++ b/deflate_stored.c @@ -132,7 +132,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { } s->block_start = (int)s->strstart; } - s->high_water = MIN(s->high_water, s->strstart); + s->high_water = MAX(s->high_water, s->strstart); /* If the last block was written to next_out, then done. */ if (last) @@ -161,7 +161,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { s->strstart += have; s->insert += MIN(have, s->w_size - s->insert); } - s->high_water = MIN(s->high_water, s->strstart); + s->high_water = MAX(s->high_water, s->strstart); /* There was not enough avail_out to write a complete worthy or flushed * stored block to next_out. Write a stored block to pending instead, if we diff --git a/infback.c b/infback.c index 62369396ff..cab3f66cf6 100644 --- a/infback.c +++ b/infback.c @@ -210,8 +210,8 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in copy = state->length; PULL(); ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; + copy = MIN(copy, have); + copy = MIN(copy, left); memcpy(put, next, copy); have -= copy; next += copy; @@ -453,8 +453,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in from = put - state->offset; copy = left; } - if (copy > state->length) - copy = state->length; + copy = MIN(copy, state->length); state->length -= copy; left -= copy; do { diff --git a/inflate.c b/inflate.c index 5c30816ddf..e2a6f2c696 100644 --- a/inflate.c +++ b/inflate.c @@ -657,8 +657,8 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* copy stored block from input to output */ copy = state->length; if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; + copy = MIN(copy, have); + copy = MIN(copy, left); if (copy == 0) goto inf_leave; memcpy(put, next, copy); have -= copy; @@ -928,10 +928,8 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR Trace((stderr, "inflate.c too far\n")); copy -= state->whave; - if (copy > state->length) - copy = state->length; - if (copy > left) - copy = left; + copy = MIN(copy, state->length); + copy = MIN(copy, left); left -= copy; state->length -= copy; do { @@ -948,16 +946,12 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } else { from = state->window + (state->wnext - copy); } - if (copy > state->length) - copy = state->length; - if (copy > left) - copy = left; + copy = MIN(copy, state->length); + copy = MIN(copy, left); put = functable.chunkcopy_safe(put, from, copy, put + left); } else { /* copy from output */ - copy = state->length; - if (copy > left) - copy = left; + copy = MIN(state->length, left); put = functable.chunkmemset_safe(put, state->offset, copy, left); } diff --git a/inftrees.c b/inftrees.c index faf1d249d6..136e25c2b1 100644 --- a/inftrees.c +++ b/inftrees.c @@ -107,7 +107,7 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, root = *bits; for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; - if (root > max) root = max; + root = MIN(root, max); if (max == 0) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; @@ -119,7 +119,7 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, } for (min = 1; min < max; min++) if (count[min] != 0) break; - if (root < min) root = min; + root = MAX(root, min); /* check for an over-subscribed or incomplete set of lengths */ left = 1; diff --git a/zbuild.h b/zbuild.h index c68fb109e4..87b7426ab4 100644 --- a/zbuild.h +++ b/zbuild.h @@ -28,5 +28,7 @@ /* Minimum of a and b. */ #define MIN(a, b) ((a) > (b) ? (b) : (a)) +/* Maximum of a and b. */ +#define MAX(a, b) ((a) < (b) ? (b) : (a)) #endif From 616ab240601936160a2cd4b0a0e80e1f4012f7f0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 4 Jun 2021 15:24:23 -0700 Subject: [PATCH 076/798] Only need to add rem if it is greater than zero in chunkmemset. --- chunkset_tpl.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 96f08d118e..ae049e7e7c 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -153,9 +153,10 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { } /* Last, deal with the case when LEN is not a multiple of SZ. */ - if (rem) + if (rem) { memcpy(out, from, rem); - out += rem; + out += rem; + } return out; } From 76b9605f80b697ab3c527cb8638e6340e0e07ce4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 4 Jun 2021 15:27:26 -0700 Subject: [PATCH 077/798] Calculate from and out buffer advance only once in chunkcopy. --- chunkset_tpl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index ae049e7e7c..55e07088c4 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -19,11 +19,11 @@ Z_INTERNAL uint32_t CHUNKSIZE(void) { reliable. */ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { chunk_t chunk; - --len; + int32_t align = (--len % sizeof(chunk_t)) + 1; loadchunk(from, &chunk); storechunk(out, &chunk); - out += (len % sizeof(chunk_t)) + 1; - from += (len % sizeof(chunk_t)) + 1; + out += align; + from += align; len /= sizeof(chunk_t); while (len > 0) { loadchunk(from, &chunk); From e2705f826e281917c2c0b3ba4abaf594f7b85f37 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 10 Jun 2021 17:25:27 -0700 Subject: [PATCH 078/798] Added assert in chunkcopy to detect invalid length. --- chunkset_tpl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 55e07088c4..62cd4aa780 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -18,6 +18,7 @@ Z_INTERNAL uint32_t CHUNKSIZE(void) { without iteration, which will hopefully make the branch prediction more reliable. */ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { + Assert(len > 0, "chunkcopy should never have a length 0"); chunk_t chunk; int32_t align = (--len % sizeof(chunk_t)) + 1; loadchunk(from, &chunk); @@ -94,7 +95,7 @@ Z_INTERNAL uint8_t* CHUNKUNROLL(uint8_t *out, unsigned *dist, unsigned *len) { Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { /* Debug performance related issues when len < sizeof(uint64_t): Assert(len >= sizeof(uint64_t), "chunkmemset should be called on larger chunks"); */ - Assert(dist > 0, "cannot have a distance 0"); + Assert(dist > 0, "chunkmemset cannot have a distance 0"); unsigned char *from = out - dist; chunk_t chunk; From 7a6f62ea93a4ebb35768dce11038253633ba54e1 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 13 Jun 2021 15:11:23 +0200 Subject: [PATCH 079/798] Change WITH_SANITIZER to be a multi-option parameter (for ccmake etc). Add support for selcting Thread sanitizer. --- CMakeLists.txt | 7 ++++++- cmake/detect-sanitizer.cmake | 12 +++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fcef69042..fd696449cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,6 @@ add_option(WITH_GZFILEOP "Compile with support for gzFile related functions" ON) add_option(ZLIB_COMPAT "Compile with zlib compatible API" OFF) add_option(ZLIB_ENABLE_TESTS "Build test binaries" ON) add_option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) -add_option(WITH_SANITIZER "Build with sanitizer (Memory, Address, Undefined)" OFF) add_option(WITH_FUZZERS "Build test/fuzz" OFF) add_option(WITH_OPTIM "Build with optimisation" ON) add_option(WITH_NEW_STRATEGIES "Use new strategies" ON) @@ -91,6 +90,10 @@ add_option(WITH_INFLATE_STRICT "Build with strict inflate distance checking" OFF add_option(WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances" OFF) add_option(WITH_UNALIGNED "Support unaligned reads on platforms that support it" ON) +# Add multi-choice option +set(WITH_SANITIZER AUTO CACHE STRING "Enable sanitizer support") +set_property(CACHE WITH_SANITIZER PROPERTY STRINGS "Memory" "Address" "Undefined" "Thread") + if(BASEARCH_ARM_FOUND) add_option(WITH_ACLE "Build with ACLE" ON) add_option(WITH_NEON "Build with NEON intrinsics" ON) @@ -322,6 +325,8 @@ if(WITH_SANITIZER STREQUAL "Address") add_address_sanitizer() elseif(WITH_SANITIZER STREQUAL "Memory") add_memory_sanitizer() +elseif(WITH_SANITIZER STREQUAL "Thread") + add_thread_sanitizer() elseif(WITH_SANITIZER STREQUAL "Undefined") add_undefined_sanitizer() endif() diff --git a/cmake/detect-sanitizer.cmake b/cmake/detect-sanitizer.cmake index 172a8d5583..b0a0236e83 100644 --- a/cmake/detect-sanitizer.cmake +++ b/cmake/detect-sanitizer.cmake @@ -69,6 +69,16 @@ macro(add_memory_sanitizer) endif() endmacro() +macro(add_thread_sanitizer) + check_sanitizer_support("thread" supported_checks) + if(NOT ${supported_checks} STREQUAL "") + message(STATUS "Thread sanitizer is enabled: ${supported_checks}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + else() + message(STATUS "Thread sanitizer is not supported") + endif() +endmacro() + macro(add_undefined_sanitizer) set(known_checks array-bounds @@ -120,4 +130,4 @@ macro(add_undefined_sanitizer) else() message(STATUS "UNdefined behavior sanitizer is not supported") endif() -endmacro() \ No newline at end of file +endmacro() From 857e4f1e0481d87ac92b258804a00c501c75ceb4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 13 Jun 2021 15:16:20 -0700 Subject: [PATCH 080/798] Added Z_UNUSED define for ignore unused variables. --- deflate.h | 4 ++-- inflate.c | 2 +- test/example.c | 2 +- test/fuzz/checksum_fuzzer.c | 16 ++++++++-------- test/fuzz/standalone_fuzz_target_runner.c | 4 +++- test/infcover.c | 10 +++++----- trees_emit.h | 2 +- zbuild.h | 2 ++ zutil.c | 4 ++-- 9 files changed, 25 insertions(+), 21 deletions(-) diff --git a/deflate.h b/deflate.h index cf7d490616..16e63c75ab 100644 --- a/deflate.h +++ b/deflate.h @@ -402,9 +402,9 @@ void Z_INTERNAL flush_pending(PREFIX3(streamp) strm); # define sent_bits_add(s, bits) s->bits_sent += (bits) # define sent_bits_align(s) s->bits_sent = (s->bits_sent + 7) & ~7L #else -# define cmpr_bits_add(s, len) (void)(len) +# define cmpr_bits_add(s, len) Z_UNUSED(len) # define cmpr_bits_align(s) -# define sent_bits_add(s, bits) (void)(bits) +# define sent_bits_add(s, bits) Z_UNUSED(bits) # define sent_bits_align(s) #endif diff --git a/inflate.c b/inflate.c index e2a6f2c696..6ba6e83dea 100644 --- a/inflate.c +++ b/inflate.c @@ -1283,7 +1283,7 @@ int32_t Z_EXPORT PREFIX(inflateUndermine)(PREFIX3(stream) *strm, int32_t subvert state->sane = !subvert; return Z_OK; #else - (void)subvert; + Z_UNUSED(subvert); state->sane = 1; return Z_DATA_ERROR; #endif diff --git a/test/example.c b/test/example.c index 8a8905dd5b..339ea8cd6f 100644 --- a/test/example.c +++ b/test/example.c @@ -229,7 +229,7 @@ void test_gzio(const char *fname, unsigned char *uncompr, z_size_t uncomprLen) { fprintf(stderr, "gzclose unexpected return when handle null\n"); exit(1); } - (void)read; + Z_UNUSED(read); #endif } diff --git a/test/fuzz/checksum_fuzzer.c b/test/fuzz/checksum_fuzzer.c index ef99421116..da9f13059c 100644 --- a/test/fuzz/checksum_fuzzer.c +++ b/test/fuzz/checksum_fuzzer.c @@ -42,16 +42,16 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { uint32_t crc4 = PREFIX(crc32_combine_op)(crc1, crc3, op); crc1 = PREFIX(crc32_z)(crc1, data + offset, buffSize); assert(crc1 == crc4); - (void)crc1; - (void)crc4; + Z_UNUSED(crc1); + Z_UNUSED(crc4); } crc1 = PREFIX(crc32_z)(crc1, data + offset, dataLen % buffSize); crc2 = PREFIX(crc32_z)(crc2, data, dataLen); assert(crc1 == crc2); - (void)crc1; - (void)crc2; + Z_UNUSED(crc1); + Z_UNUSED(crc2); combine1 = PREFIX(crc32_combine)(crc1, crc2, (z_off_t)dataLen); combine2 = PREFIX(crc32_combine)(crc1, crc1, (z_off_t)dataLen); assert(combine1 == combine2); @@ -73,13 +73,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t dataLen) { adler2 = PREFIX(adler32_z)(adler2, data, dataLen); assert(adler1 == adler2); - (void)adler1; - (void)adler2; + Z_UNUSED(adler1); + Z_UNUSED(adler2); combine1 = PREFIX(adler32_combine)(adler1, adler2, (z_off_t)dataLen); combine2 = PREFIX(adler32_combine)(adler1, adler1, (z_off_t)dataLen); assert(combine1 == combine2); - (void)combine1; - (void)combine2; + Z_UNUSED(combine1); + Z_UNUSED(combine2); /* This function must return 0. */ return 0; diff --git a/test/fuzz/standalone_fuzz_target_runner.c b/test/fuzz/standalone_fuzz_target_runner.c index a291b48823..49f5e7fa19 100644 --- a/test/fuzz/standalone_fuzz_target_runner.c +++ b/test/fuzz/standalone_fuzz_target_runner.c @@ -2,6 +2,8 @@ #include #include +#include "zbuild.h" + extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); int main(int argc, char **argv) { @@ -28,7 +30,7 @@ int main(int argc, char **argv) { free(buf); err = fclose(f); assert(err == 0); - (void)err; + Z_UNUSED(err); fprintf(stderr, "Done: %s: (%d bytes)\n", argv[i], (int)n_read); } diff --git a/test/infcover.c b/test/infcover.c index 3466b202dc..3446289eff 100644 --- a/test/infcover.c +++ b/test/infcover.c @@ -348,7 +348,7 @@ static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int ret = PREFIX(inflateReset2)(&strm, -8); assert(ret == Z_OK); ret = PREFIX(inflateEnd)(&strm); assert(ret == Z_OK); mem_done(&strm, what); - (void)err; + Z_UNUSED(err); } /* cover all of the lines in inflate.c up to inflate() */ @@ -386,7 +386,7 @@ static void cover_support(void) { ret = PREFIX(inflateInit)(&strm); assert(ret == Z_OK); ret = PREFIX(inflateEnd)(&strm); assert(ret == Z_OK); fputs("inflate built-in memory routines\n", stderr); - (void)ret; + Z_UNUSED(ret); } /* cover all inflate() header and trailer cases and code after inflate() */ @@ -470,7 +470,7 @@ static unsigned pull(void *desc, z_const unsigned char **buf) { static int push(void *desc, unsigned char *buf, unsigned len) { buf += len; - (void)buf; + Z_UNUSED(buf); return desc != NULL; /* force error if desc not null */ } @@ -511,7 +511,7 @@ static void cover_back(void) { assert(ret == Z_OK); ret = PREFIX(inflateBackEnd)(&strm); assert(ret == Z_OK); fputs("inflateBack built-in memory routines\n", stderr); - (void)ret; + Z_UNUSED(ret); } /* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ @@ -647,7 +647,7 @@ static void cover_trees(void) { ret = zng_inflate_table(DISTS, lens, 16, &next, &bits, work); assert(ret == 1); fputs("inflate_table not enough errors\n", stderr); - (void)ret; + Z_UNUSED(ret); } /* cover remaining inffast.c decoding and window copying */ diff --git a/trees_emit.h b/trees_emit.h index 454488edb3..52af7a409d 100644 --- a/trees_emit.h +++ b/trees_emit.h @@ -175,7 +175,7 @@ static inline void zng_emit_end_block(deflate_state *s, const ct_data *ltree, co s->bi_buf = bi_buf; Tracev((stderr, "\n+++ Emit End Block: Last: %u Pending: %u Total Out: %" PRIu64 "\n", last, s->pending, (uint64_t)s->strm->total_out)); - (void)last; + Z_UNUSED(last); } /* =========================================================================== diff --git a/zbuild.h b/zbuild.h index 87b7426ab4..3c5e5fb407 100644 --- a/zbuild.h +++ b/zbuild.h @@ -30,5 +30,7 @@ #define MIN(a, b) ((a) > (b) ? (b) : (a)) /* Maximum of a and b. */ #define MAX(a, b) ((a) < (b) ? (b) : (a)) +/* Ignore unused variable warning */ +#define Z_UNUSED(var) (void)(var) #endif diff --git a/zutil.c b/zutil.c index 74d7524353..53e43b0dea 100644 --- a/zutil.c +++ b/zutil.c @@ -101,11 +101,11 @@ const char * Z_EXPORT PREFIX(zError)(int err) { } void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size) { - (void)opaque; + Z_UNUSED(opaque); return zng_alloc((size_t)items * (size_t)size); } void Z_INTERNAL zng_cfree(void *opaque, void *ptr) { - (void)opaque; + Z_UNUSED(opaque); zng_free(ptr); } From 450d56fca964ab8104db3491688cff24d5fc4581 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 13 Jun 2021 15:36:47 -0700 Subject: [PATCH 081/798] Fixed indentation in CMakeLists.txt after PR #906. --- CMakeLists.txt | 216 ++++++++++++++++++++++++------------------------- 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fd696449cc..5f1c50344e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,46 +175,46 @@ elseif(MSVC) endif() elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") # Enable warnings in GCC and Clang - set(WARNFLAGS "-Wall") - set(WARNFLAGS_MAINTAINER "-Wextra -Wpedantic") - set(WARNFLAGS_DISABLE "-Wno-implicit-fallthrough") + set(WARNFLAGS "-Wall") + set(WARNFLAGS_MAINTAINER "-Wextra -Wpedantic") + set(WARNFLAGS_DISABLE "-Wno-implicit-fallthrough") if(WITH_NATIVE_INSTRUCTIONS) - if(BASEARCH_PPC_FOUND) - set(NATIVEFLAG "-mcpu=native") - else() - set(NATIVEFLAG "-march=native") - endif() + if(BASEARCH_PPC_FOUND) + set(NATIVEFLAG "-mcpu=native") else() - if(BASEARCH_ARM_FOUND) - if("${ARCH}" MATCHES "arm" AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") - # Auto-detect support for ARM floating point ABI - check_c_compiler_flag(-mfloat-abi=softfp HAVE_FLOATABI_SOFTFP) - if(HAVE_FLOATABI_SOFTFP) - set(FLOATABI "-mfloat-abi=softfp") - else() - check_c_compiler_flag(-mfloat-abi=hard HAVE_FLOATABI_HARD) - if(HAVE_FLOATABI_HARD) - set(FLOATABI "-mfloat-abi=hard") - endif() - endif() - if(FLOATABI) - message(STATUS "ARM floating point arch: ${FLOATABI}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLOATABI}") - else() - message(STATUS "ARM floating point arch not auto-detected") + set(NATIVEFLAG "-march=native") + endif() + else() + if(BASEARCH_ARM_FOUND) + if("${ARCH}" MATCHES "arm" AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") + # Auto-detect support for ARM floating point ABI + check_c_compiler_flag(-mfloat-abi=softfp HAVE_FLOATABI_SOFTFP) + if(HAVE_FLOATABI_SOFTFP) + set(FLOATABI "-mfloat-abi=softfp") + else() + check_c_compiler_flag(-mfloat-abi=hard HAVE_FLOATABI_HARD) + if(HAVE_FLOATABI_HARD) + set(FLOATABI "-mfloat-abi=hard") endif() endif() - endif() - # Check whether -fno-lto is available - set(CMAKE_REQUIRED_FLAGS "-fno-lto") - check_c_source_compiles( - "int main() { return 0; }" - FNO_LTO_AVAILABLE FAIL_REGEX "not supported") - set(CMAKE_REQUIRED_FLAGS) - if(FNO_LTO_AVAILABLE) - set(NOLTOFLAG "-fno-lto") + if(FLOATABI) + message(STATUS "ARM floating point arch: ${FLOATABI}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLOATABI}") + else() + message(STATUS "ARM floating point arch not auto-detected") + endif() endif() endif() + # Check whether -fno-lto is available + set(CMAKE_REQUIRED_FLAGS "-fno-lto") + check_c_source_compiles( + "int main() { return 0; }" + FNO_LTO_AVAILABLE FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) + if(FNO_LTO_AVAILABLE) + set(NOLTOFLAG "-fno-lto") + endif() + endif() else() if(WITH_NATIVE_INSTRUCTIONS) message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration") @@ -564,41 +564,41 @@ if(WITH_OPTIM) if(WITH_ACLE AND NOT MSVC) check_acle_intrinsics() if(HAVE_ACLE_INTRIN) - add_definitions(-DARM_ACLE_CRC_HASH) - set(ACLE_SRCS ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c) - set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG} ${NOLTOFLAG}") - list(APPEND ZLIB_ARCH_SRCS ${ACLE_SRCS}) - add_feature_info(ACLE_CRC 1 "Support ACLE optimized CRC hash generation, using \"${ACLEFLAG}\"") - endif() + add_definitions(-DARM_ACLE_CRC_HASH) + set(ACLE_SRCS ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c) + set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG} ${NOLTOFLAG}") + list(APPEND ZLIB_ARCH_SRCS ${ACLE_SRCS}) + add_feature_info(ACLE_CRC 1 "Support ACLE optimized CRC hash generation, using \"${ACLEFLAG}\"") + endif() endif() if(WITH_NEON) check_neon_intrinsics() if(MFPU_NEON_AVAILABLE) - add_definitions(-DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) - set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_neon.c) - list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) - set_property(SOURCE ${NEON_SRCS} PROPERTY COMPILE_FLAGS "${NEONFLAG} ${NOLTOFLAG}") - if(MSVC) - add_definitions(-D__ARM_NEON__) + add_definitions(-DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) + set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_neon.c) + list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) + set_property(SOURCE ${NEON_SRCS} PROPERTY COMPILE_FLAGS "${NEONFLAG} ${NOLTOFLAG}") + if(MSVC) + add_definitions(-D__ARM_NEON__) + endif() + add_feature_info(NEON_ADLER32 1 "Support NEON instructions in adler32, using \"${NEONFLAG}\"") + add_feature_info(NEON_SLIDEHASH 1 "Support NEON instructions in slide_hash, using \"${NEONFLAG}\"") endif() - add_feature_info(NEON_ADLER32 1 "Support NEON instructions in adler32, using \"${NEONFLAG}\"") - add_feature_info(NEON_SLIDEHASH 1 "Support NEON instructions in slide_hash, using \"${NEONFLAG}\"") - endif() endif() elseif(BASEARCH_PPC_FOUND) if(WITH_POWER8) check_power8_intrinsics() if(HAVE_POWER8_INTRIN) - add_definitions(-DPOWER8) - add_definitions(-DPOWER_FEATURES) - add_definitions(-DPOWER8_VSX_ADLER32) - add_definitions(-DPOWER8_VSX_SLIDEHASH) - list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) - set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/slide_power8.c) - list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) - set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") - endif() + add_definitions(-DPOWER8) + add_definitions(-DPOWER_FEATURES) + add_definitions(-DPOWER8_VSX_ADLER32) + add_definitions(-DPOWER8_VSX_SLIDEHASH) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) + set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/slide_power8.c) + list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) + set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") + endif() endif() elseif(BASEARCH_S360_FOUND) if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) @@ -621,77 +621,77 @@ if(WITH_OPTIM) endif() if(WITH_AVX2) check_avx2_intrinsics() - if(HAVE_AVX2_INTRIN) - add_definitions(-DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET) - set(AVX2_SRCS ${ARCHDIR}/slide_avx.c) - add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx.c) - add_feature_info(AVX_CHUNKSET 1 "Support AVX optimized chunkset, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/compare258_avx.c) - add_feature_info(AVX2_COMPARE258 1 "Support AVX2 optimized compare258, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx.c) - add_feature_info(AVX2_ADLER32 1 "Support AVX2-accelerated adler32, using \"${AVX2FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) - set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG} ${NOLTOFLAG}") - endif() + if(HAVE_AVX2_INTRIN) + add_definitions(-DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET) + set(AVX2_SRCS ${ARCHDIR}/slide_avx.c) + add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") + list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx.c) + add_feature_info(AVX_CHUNKSET 1 "Support AVX optimized chunkset, using \"${AVX2FLAG}\"") + list(APPEND AVX2_SRCS ${ARCHDIR}/compare258_avx.c) + add_feature_info(AVX2_COMPARE258 1 "Support AVX2 optimized compare258, using \"${AVX2FLAG}\"") + list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx.c) + add_feature_info(AVX2_ADLER32 1 "Support AVX2-accelerated adler32, using \"${AVX2FLAG}\"") + list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) + set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG} ${NOLTOFLAG}") + endif() endif() if(WITH_SSE4) check_sse4_intrinsics() if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) - add_definitions(-DX86_SSE42_CRC_HASH) - set(SSE42_SRCS ${ARCHDIR}/insert_string_sse.c) - add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE4FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") - if(HAVE_SSE42CRC_INTRIN) - add_definitions(-DX86_SSE42_CRC_INTRIN) + add_definitions(-DX86_SSE42_CRC_HASH) + set(SSE42_SRCS ${ARCHDIR}/insert_string_sse.c) + add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE4FLAG}\"") + list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) + set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") + if(HAVE_SSE42CRC_INTRIN) + add_definitions(-DX86_SSE42_CRC_INTRIN) + endif() + endif() + if(HAVE_SSE42CMPSTR_INTRIN) + add_definitions(-DX86_SSE42_CMP_STR) + set(SSE42_SRCS ${ARCHDIR}/compare258_sse.c) + add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE4FLAG}\"") + list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) + set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") endif() - endif() - if(WITH_SSE4 AND HAVE_SSE42CMPSTR_INTRIN) - add_definitions(-DX86_SSE42_CMP_STR) - set(SSE42_SRCS ${ARCHDIR}/compare258_sse.c) - add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE4FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") - endif() endif() if(WITH_SSE2) check_sse2_intrinsics() if(HAVE_SSE2_INTRIN) - add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) - set(SSE2_SRCS ${ARCHDIR}/chunkset_sse.c ${ARCHDIR}/slide_sse.c) - list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) - if(NOT ${ARCH} MATCHES "x86_64") - set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG} ${NOLTOFLAG}") - add_feature_info(FORCE_SSE2 FORCE_SSE2 "Assume CPU is SSE2 capable") - if(FORCE_SSE2) - add_definitions(-DX86_NOCHECK_SSE2) + add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) + set(SSE2_SRCS ${ARCHDIR}/chunkset_sse.c ${ARCHDIR}/slide_sse.c) + list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) + if(NOT ${ARCH} MATCHES "x86_64") + set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG} ${NOLTOFLAG}") + add_feature_info(FORCE_SSE2 FORCE_SSE2 "Assume CPU is SSE2 capable") + if(FORCE_SSE2) + add_definitions(-DX86_NOCHECK_SSE2) + endif() endif() endif() endif() - endif() if(WITH_SSSE3) check_ssse3_intrinsics() if(HAVE_SSSE3_INTRIN) - add_definitions(-DX86_SSSE3 -DX86_SSSE3_ADLER32) - set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c) - add_feature_info(SSSE3_ADLER32 1 "Support SSSE3-accelerated adler32, using \"${SSSE3FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) - set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${NOLTOFLAG}") - endif() + add_definitions(-DX86_SSSE3 -DX86_SSSE3_ADLER32) + set(SSSE3_SRCS ${ARCHDIR}/adler32_ssse3.c) + add_feature_info(SSSE3_ADLER32 1 "Support SSSE3-accelerated adler32, using \"${SSSE3FLAG}\"") + list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) + set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${NOLTOFLAG}") + endif() endif() if(WITH_PCLMULQDQ AND WITH_SSSE3 AND WITH_SSE4) check_pclmulqdq_intrinsics() if(HAVE_PCLMULQDQ_INTRIN AND HAVE_SSSE3_INTRIN) - add_definitions(-DX86_PCLMULQDQ_CRC) - set(PCLMULQDQ_SRCS ${ARCHDIR}/crc_folding.c) - add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) - set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") + add_definitions(-DX86_PCLMULQDQ_CRC) + set(PCLMULQDQ_SRCS ${ARCHDIR}/crc_folding.c) + add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}\"") + list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) + set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") + endif() endif() endif() endif() -endif() message(STATUS "Architecture-specific source files: ${ZLIB_ARCH_SRCS}") From 815faea92c3d32c71fb68d08e8cb227ed3364357 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 13 Jun 2021 15:57:28 -0700 Subject: [PATCH 082/798] Reduce number of branches in partial chunk copy based on chunk size. --- arch/arm/chunkset_neon.c | 2 ++ arch/x86/chunkset_avx.c | 2 ++ arch/x86/chunkset_sse.c | 2 ++ chunkset.c | 2 ++ chunkset_tpl.h | 7 +++++-- 5 files changed, 13 insertions(+), 2 deletions(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index b153298275..22c3785c11 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -13,6 +13,8 @@ typedef uint8x16_t chunk_t; +#define CHUNK_SIZE 16 + #define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index eb76c0db99..7a9a56a096 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -9,6 +9,8 @@ typedef __m256i chunk_t; +#define CHUNK_SIZE 32 + #define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 diff --git a/arch/x86/chunkset_sse.c b/arch/x86/chunkset_sse.c index 1d5a0faa93..d38e99dad6 100644 --- a/arch/x86/chunkset_sse.c +++ b/arch/x86/chunkset_sse.c @@ -10,6 +10,8 @@ typedef __m128i chunk_t; +#define CHUNK_SIZE 16 + #define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 diff --git a/chunkset.c b/chunkset.c index 2aa8d4e47f..b07e6f4827 100644 --- a/chunkset.c +++ b/chunkset.c @@ -14,6 +14,8 @@ typedef struct chunk_t { uint32_t u32[2]; } chunk_t; typedef struct chunk_t { uint8_t u8[8]; } chunk_t; #endif +#define CHUNK_SIZE 8 + #define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_4 #define HAVE_CHUNKMEMSET_8 diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 62cd4aa780..2026ff37cc 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -40,17 +40,20 @@ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { Z_INTERNAL uint8_t* CHUNKCOPY_SAFE(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe) { len = MIN(len, safe - out + 1); if (len < sizeof(chunk_t)) { - int32_t use_chunk16 = sizeof(chunk_t) > 16 && (len & 16); - if (use_chunk16) { +#if CHUNK_SIZE > 16 + if (len & 16) { memcpy(out, from, 16); out += 16; from += 16; } +#endif +#if CHUNK_SIZE > 8 if (len & 8) { memcpy(out, from, 8); out += 8; from += 8; } +#endif if (len & 4) { memcpy(out, from, 4); out += 4; From 21d119e58b54a2a50e670dcf0316929f464239e0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 16 Jun 2021 08:11:33 -0700 Subject: [PATCH 083/798] Added aarch64 to pigz GitHub actions workflow. --- .github/workflows/pigz.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 92f9ee6df7..8260c82fb7 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -36,6 +36,14 @@ jobs: codecov: ubuntu_clang_pigz_no_threads cmake-args: -DWITH_THREADS=OFF + - name: Ubuntu GCC AARCH64 + os: ubuntu-latest + compiler: aarch64-linux-gnu-gcc + cmake-args: -DCMAKE_TOOLCHAIN_FILE=../../cmake/toolchain-aarch64.cmake + packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross + qemu-run: qemu-aarch64 + codecov: ubuntu_gcc_pigz_aarch64 + steps: - name: Checkout repository uses: actions/checkout@v2 From 40a12fe994798b7033373fcee322387c99d238e3 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 13 Jun 2021 13:38:32 +0200 Subject: [PATCH 084/798] Change requested compiler standard to C11 --- CMakeLists.txt | 6 +++--- README.md | 2 +- configure | 2 +- zbuild.h | 14 ++++++++++++++ zconf-ng.h.in | 8 -------- zconf.h.in | 8 -------- 6 files changed, 19 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f1c50344e..c69b93bbe2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,11 +8,11 @@ message(STATUS "Using CMake version ${CMAKE_VERSION}") set(CMAKE_MACOSX_RPATH 1) -# If not specified on the command line, enable C99 as the default +# If not specified on the command line, enable C11 as the default # Configuration items that affect the global compiler environment standards # should be issued before the "project" command. if(NOT CMAKE_C_STANDARD) - set(CMAKE_C_STANDARD 99) # The C standard whose features are requested to build this target + set(CMAKE_C_STANDARD 11) # The C standard whose features are requested to build this target endif() if(NOT CMAKE_C_STANDARD_REQUIRED) set(CMAKE_C_STANDARD_REQUIRED ON) # Boolean describing whether the value of C_STANDARD is a requirement @@ -22,7 +22,7 @@ if(NOT CMAKE_C_EXTENSIONS) endif() set(VALID_C_STANDARDS "99" "11") if(NOT CMAKE_C_STANDARD IN_LIST VALID_C_STANDARDS) - MESSAGE(FATAL_ERROR "CMAKE_C_STANDARD:STRING=${CMAKE_C_STANDARD} not in know standards list\n ${VALID_C_STANDARDS}") + MESSAGE(FATAL_ERROR "CMAKE_C_STANDARD:STRING=${CMAKE_C_STANDARD} not in known standards list\n ${VALID_C_STANDARDS}") endif() # Parse the full version number from zlib.h and include in ZLIB_FULL_VERSION diff --git a/README.md b/README.md index 68d935a42a..22b1e41647 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Features * Zlib compatible API with support for dual-linking * Modernized native API based on zlib API for ease of porting -* Modern C99 syntax and a clean code layout +* Modern C11 syntax and a clean code layout * Deflate medium and quick algorithms based on Intels zlib fork * Support for CPU intrinsics when available * Adler32 implementation using SSSE3, AVX2, Neon & VSX diff --git a/configure b/configure index 2bf16198b8..5d58e37cd3 100755 --- a/configure +++ b/configure @@ -283,7 +283,7 @@ show $cc -c $test.c if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then echo "$cc" | tee -a configure.log CC="$cc" - CFLAGS="${CFLAGS} -std=c99" + CFLAGS="${CFLAGS} -std=c11" # Re-check ARCH if the compiler is a cross-compiler. if $CC -print-multiarch 1> /dev/null 2>&1 && test -n "$($CC -print-multiarch)" 1> /dev/null 2>&1; then diff --git a/zbuild.h b/zbuild.h index 3c5e5fb407..0712b54fd6 100644 --- a/zbuild.h +++ b/zbuild.h @@ -1,6 +1,20 @@ #ifndef _ZBUILD_H #define _ZBUILD_H +/* Determine compiler version of C Standard */ +#ifdef __STDC_VERSION__ +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +# if __STDC_VERSION__ >= 201112L +# ifndef STDC11 +# define STDC11 +# endif +# endif +#endif + /* This has to be first include that defines any types */ #if defined(_MSC_VER) # if defined(_WIN64) diff --git a/zconf-ng.h.in b/zconf-ng.h.in index 7d54668d36..66ab4cf662 100644 --- a/zconf-ng.h.in +++ b/zconf-ng.h.in @@ -10,14 +10,6 @@ # define _WIN32 #endif -#ifdef __STDC_VERSION__ -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif - /* Clang macro for detecting declspec support * https://clang.llvm.org/docs/LanguageExtensions.html#has-declspec-attribute */ diff --git a/zconf.h.in b/zconf.h.in index ae2a309398..2c6b12dff1 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -10,14 +10,6 @@ # define _WIN32 #endif -#ifdef __STDC_VERSION__ -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif - /* Clang macro for detecting declspec support * https://clang.llvm.org/docs/LanguageExtensions.html#has-declspec-attribute */ From 101653c0201a2f487ca7268dd23c5b62c9ad9c79 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Sun, 13 Jun 2021 13:57:45 +0200 Subject: [PATCH 085/798] Add support for Thread Local Storage to ensure consistency in functable. --- zbuild.h | 14 ++++++++++++++ zutil.h | 4 ---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/zbuild.h b/zbuild.h index 0712b54fd6..e47acf5368 100644 --- a/zbuild.h +++ b/zbuild.h @@ -15,6 +15,20 @@ # endif #endif +/* Determine compiler support for TLS */ +#ifndef Z_TLS +# if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__ +# define Z_TLS _Thread_local +# elif defined(__GNUC__) || defined(__SUNPRO_C) +# define Z_TLS __thread +# elif defined(_WIN32) && (defined(_MSC_VER) || defined(__ICL)) +# define Z_TLS __declspec(thread) +# else +# warning Unable to detect Thread Local Storage support. +# define Z_TLS +# endif +#endif + /* This has to be first include that defines any types */ #if defined(_MSC_VER) # if defined(_WIN64) diff --git a/zutil.h b/zutil.h index fa08f2aa78..75f0c28ca4 100644 --- a/zutil.h +++ b/zutil.h @@ -24,10 +24,6 @@ # define Z_REGISTER #endif -#ifndef Z_TLS -# define Z_TLS -#endif - #include #include #include From 834e7d83eae9ff7bfb1b9769d9f311ea7ca8e746 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 14 Jun 2021 21:03:51 +0200 Subject: [PATCH 086/798] Fix MSVC warnings in hash_head_0.c test --- test/hash_head_0.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hash_head_0.c b/test/hash_head_0.c index 128ae3492c..1f615c5d67 100644 --- a/test/hash_head_0.c +++ b/test/hash_head_0.c @@ -63,14 +63,14 @@ int main() { return EXIT_FAILURE; } - strm.avail_in = next_in + sizeof(next_in) - strm.next_in; - strm.avail_out = next_out + sizeof(next_out) - strm.next_out; + strm.avail_in = (uint32_t)(next_in + sizeof(next_in) - strm.next_in); + strm.avail_out = (uint32_t)(next_out + sizeof(next_out) - strm.next_out); ret = PREFIX(deflate)(&strm, Z_FINISH); if (ret != Z_STREAM_END) { fprintf(stderr, "deflate() failed with code %d\n", ret); return EXIT_FAILURE; } - uint32_t compressed_size = strm.next_out - next_out; + uint32_t compressed_size = (uint32_t)(strm.next_out - next_out); ret = PREFIX(deflateEnd)(&strm); if (ret != Z_OK) { From 46af2953a7b79904bb3a9e143ad66564a1d6d0eb Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 18 Jun 2021 23:15:28 +0300 Subject: [PATCH 087/798] [chunkset_neon] Don't use signed vector types. * There is no need to convert between unsigned and signed vector types. All relevant intrinsics have versions for all unsigned vector types. --- arch/arm/chunkset_neon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 22c3785c11..b1fcb241d0 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -25,15 +25,15 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { } static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { - int16_t tmp; + uint16_t tmp; memcpy(&tmp, from, 2); - *chunk = vreinterpretq_u8_s16(vdupq_n_s16(tmp)); + *chunk = vreinterpretq_u8_u16(vdupq_n_u16(tmp)); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { - int32_t tmp; + uint32_t tmp; memcpy(&tmp, from, 4); - *chunk = vreinterpretq_u8_s32(vdupq_n_s32(tmp)); + *chunk = vreinterpretq_u8_u32(vdupq_n_u32(tmp)); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { From 31aed006c39118721929112f62805712183fc730 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sat, 19 Jun 2021 00:10:44 +0300 Subject: [PATCH 088/798] [chunkset_neon] Use vdupq_n_u64. * Using vdupq_n_u64 duplicates the unsigned 64-bit integer to two consecutive aligned memory locations in stack so compiler can use wider load instructions. All different-sized general-purpose registers overlay on ARM/AArch64, so any vector cast is no-op in assembly. --- arch/arm/chunkset_neon.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index b1fcb241d0..e0ad3e04ea 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -37,7 +37,9 @@ static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { - *chunk = vcombine_u8(vld1_u8(from), vld1_u8(from)); + uint64_t tmp; + memcpy(&tmp, from, 8); + *chunk = vreinterpretq_u8_u64(vdupq_n_u64(tmp)); } #define CHUNKSIZE chunksize_neon From 4521023854777be478bb187ffc051cbf0a1687cf Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sat, 19 Jun 2021 02:08:20 +0300 Subject: [PATCH 089/798] [chunkcopy_safe] Don't call chunkcopy(). * chunkcopy() can read or write more than the safe length if the length is not multiple of chunk size. --- chunkset_tpl.h | 65 ++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 2026ff37cc..256475a641 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -39,37 +39,46 @@ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { /* Behave like chunkcopy, but avoid writing beyond of legal output. */ Z_INTERNAL uint8_t* CHUNKCOPY_SAFE(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe) { len = MIN(len, safe - out + 1); - if (len < sizeof(chunk_t)) { -#if CHUNK_SIZE > 16 - if (len & 16) { - memcpy(out, from, 16); - out += 16; - from += 16; - } +#if CHUNK_SIZE >= 32 + while (len >= 32) { + memcpy(out, from, 32); + out += 32; + from += 32; + len -= 32; + } #endif -#if CHUNK_SIZE > 8 - if (len & 8) { - memcpy(out, from, 8); - out += 8; - from += 8; - } +#if CHUNK_SIZE >= 16 + while (len >= 16) { + memcpy(out, from, 16); + out += 16; + from += 16; + len -= 16; + } #endif - if (len & 4) { - memcpy(out, from, 4); - out += 4; - from += 4; - } - if (len & 2) { - memcpy(out, from, 2); - out += 2; - from += 2; - } - if (len & 1) { - *out++ = *from++; - } - return out; +#if CHUNK_SIZE >= 8 + while (len >= 8) { + memcpy(out, from, 8); + out += 8; + from += 8; + len -= 8; + } +#endif + if (len >= 4) { + memcpy(out, from, 4); + out += 4; + from += 4; + len -= 4; } - return CHUNKCOPY(out, from, len); + if (len >= 2) { + memcpy(out, from, 2); + out += 2; + from += 2; + len -= 2; + } + if (len == 1) { + *out++ = *from++; + } + return out; } /* Perform short copies until distance can be rewritten as being at least From 31e6377a8205cc53be5d90d8f840942ca3e08966 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 13 Jun 2021 15:39:58 -0700 Subject: [PATCH 090/798] Separate option and add_feature_info in cases where intrinsics are not available we can report feature is disabled. --- CMakeLists.txt | 112 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c69b93bbe2..b477ff37af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,46 +70,42 @@ endif() # # Options parsing # -macro(add_option name description value) - option(${name} ${description} ${value}) - add_feature_info(${name} ${name} ${description}) -endmacro() - -add_option(WITH_GZFILEOP "Compile with support for gzFile related functions" ON) -add_option(ZLIB_COMPAT "Compile with zlib compatible API" OFF) -add_option(ZLIB_ENABLE_TESTS "Build test binaries" ON) -add_option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) -add_option(WITH_FUZZERS "Build test/fuzz" OFF) -add_option(WITH_OPTIM "Build with optimisation" ON) -add_option(WITH_NEW_STRATEGIES "Use new strategies" ON) -add_option(WITH_NATIVE_INSTRUCTIONS +option(WITH_GZFILEOP "Compile with support for gzFile related functions" ON) +option(ZLIB_COMPAT "Compile with zlib compatible API" OFF) +option(ZLIB_ENABLE_TESTS "Build test binaries" ON) +option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) +option(WITH_FUZZERS "Build test/fuzz" OFF) +option(WITH_OPTIM "Build with optimisation" ON) +option(WITH_NEW_STRATEGIES "Use new strategies" ON) +option(WITH_NATIVE_INSTRUCTIONS "Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)" OFF) -add_option(WITH_MAINTAINER_WARNINGS "Build with project maintainer warnings" OFF) -add_option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF) -add_option(WITH_INFLATE_STRICT "Build with strict inflate distance checking" OFF) -add_option(WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances" OFF) -add_option(WITH_UNALIGNED "Support unaligned reads on platforms that support it" ON) +option(WITH_MAINTAINER_WARNINGS "Build with project maintainer warnings" OFF) +option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF) +option(WITH_INFLATE_STRICT "Build with strict inflate distance checking" OFF) +option(WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances" OFF) +option(WITH_UNALIGNED "Support unaligned reads on platforms that support it" ON) # Add multi-choice option set(WITH_SANITIZER AUTO CACHE STRING "Enable sanitizer support") set_property(CACHE WITH_SANITIZER PROPERTY STRINGS "Memory" "Address" "Undefined" "Thread") if(BASEARCH_ARM_FOUND) - add_option(WITH_ACLE "Build with ACLE" ON) - add_option(WITH_NEON "Build with NEON intrinsics" ON) + option(WITH_ACLE "Build with ACLE" ON) + option(WITH_NEON "Build with NEON intrinsics" ON) elseif(BASEARCH_PPC_FOUND) - add_option(WITH_POWER8 "Build with optimisations for POWER8" ON) + option(WITH_POWER8 "Build with optimisations for POWER8" ON) elseif(BASEARCH_S360_FOUND) - add_option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF) - add_option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF) + option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF) + option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF) elseif(BASEARCH_X86_FOUND) - add_option(WITH_AVX2 "Build with AVX2" ON) - add_option(WITH_SSE2 "Build with SSE2" ON) - add_option(WITH_SSSE3 "Build with SSSE3" ON) - add_option(WITH_SSE4 "Build with SSE4" ON) - add_option(WITH_PCLMULQDQ "Build with PCLMULQDQ" ON) + option(WITH_AVX2 "Build with AVX2" ON) + option(WITH_SSE2 "Build with SSE2" ON) + option(WITH_SSSE3 "Build with SSSE3" ON) + option(WITH_SSE4 "Build with SSE4" ON) + option(WITH_PCLMULQDQ "Build with PCLMULQDQ" ON) endif() -add_option(INSTALL_UTILS "Copy minigzip and minideflate during install" OFF) + +option(INSTALL_UTILS "Copy minigzip and minideflate during install" OFF) mark_as_advanced(FORCE ZLIB_DUAL_LINK @@ -150,6 +146,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "Intel") endif() if(WITH_NATIVE_INSTRUCTIONS) message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") + set(WITH_NATIVE_INSTRUCTIONS OFF) endif() elseif(MSVC) # Minimum supported MSVC version is 1800 = Visual Studio 12.0/2013 @@ -172,6 +169,7 @@ elseif(MSVC) endif() if(WITH_NATIVE_INSTRUCTIONS) message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") + set(WITH_NATIVE_INSTRUCTIONS OFF) endif() elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") # Enable warnings in GCC and Clang @@ -218,6 +216,7 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") else() if(WITH_NATIVE_INSTRUCTIONS) message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration") + set(WITH_NATIVE_INSTRUCTIONS OFF) endif() endif() @@ -569,7 +568,11 @@ if(WITH_OPTIM) set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG} ${NOLTOFLAG}") list(APPEND ZLIB_ARCH_SRCS ${ACLE_SRCS}) add_feature_info(ACLE_CRC 1 "Support ACLE optimized CRC hash generation, using \"${ACLEFLAG}\"") + else() + set(WITH_ACLE OFF) endif() + else() + set(WITH_ACLE OFF) endif() if(WITH_NEON) check_neon_intrinsics() @@ -583,6 +586,8 @@ if(WITH_OPTIM) endif() add_feature_info(NEON_ADLER32 1 "Support NEON instructions in adler32, using \"${NEONFLAG}\"") add_feature_info(NEON_SLIDEHASH 1 "Support NEON instructions in slide_hash, using \"${NEONFLAG}\"") + else() + set(WITH_NEON OFF) endif() endif() elseif(BASEARCH_PPC_FOUND) @@ -598,6 +603,8 @@ if(WITH_OPTIM) set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/slide_power8.c) list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") + else() + set(WITH_POWER8 OFF) endif() endif() elseif(BASEARCH_S360_FOUND) @@ -633,6 +640,8 @@ if(WITH_OPTIM) add_feature_info(AVX2_ADLER32 1 "Support AVX2-accelerated adler32, using \"${AVX2FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG} ${NOLTOFLAG}") + else() + set(WITH_AVX2 OFF) endif() endif() if(WITH_SSE4) @@ -654,6 +663,9 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") endif() + if(NOT HAVE_SSE42CRC_INLINE_ASM AND NOT HAVE_SSE42CRC_INTRIN AND NOT HAVE_SSE42CMPSTR_INTRIN) + set(WITH_SSE4 OFF) + endif() endif() if(WITH_SSE2) check_sse2_intrinsics() @@ -668,6 +680,8 @@ if(WITH_OPTIM) add_definitions(-DX86_NOCHECK_SSE2) endif() endif() + else() + set(WITH_SSE2 OFF) endif() endif() if(WITH_SSSE3) @@ -678,6 +692,8 @@ if(WITH_OPTIM) add_feature_info(SSSE3_ADLER32 1 "Support SSSE3-accelerated adler32, using \"${SSSE3FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSSE3_SRCS}) set_property(SOURCE ${SSSE3_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${NOLTOFLAG}") + else() + set(WITH_SSSE3 OFF) endif() endif() if(WITH_PCLMULQDQ AND WITH_SSSE3 AND WITH_SSE4) @@ -688,7 +704,11 @@ if(WITH_OPTIM) add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") + else() + set(WITH_PCLMULQDQ OFF) endif() + else() + set(WITH_PCLMULQDQ OFF) endif() endif() endif() @@ -1240,4 +1260,38 @@ if(ZLIB_ENABLE_TESTS) add_simple_test_executable(hash_head_0) endif() +add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile related functions") +add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Compile with zlib compatible API") +add_feature_info(ZLIB_ENABLE_TESTS ZLIB_ENABLE_TESTS "Build test binaries") +add_feature_info(ZLIB_DUAL_LINK ZLIB_DUAL_LINK "Dual link tests against system zlib") +add_feature_info(WITH_SANITIZER WITH_SANITIZER "Enable sanitizer support") +add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz") +add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation") +add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies") +add_feature_info(WITH_NATIVE_INSTRUCTIONS WITH_NATIVE_INSTRUCTIONS + "Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)") +add_feature_info(WITH_MAINTAINER_WARNINGS WITH_MAINTAINER_WARNINGS "Build with project maintainer warnings") +add_feature_info(WITH_CODE_COVERAGE WITH_CODE_COVERAGE "Enable code coverage reporting") +add_feature_info(WITH_INFLATE_STRICT WITH_INFLATE_STRICT "Build with strict inflate distance checking") +add_feature_info(WITH_INFLATE_ALLOW_INVALID_DIST WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances") +add_feature_info(WITH_UNALIGNED WITH_UNALIGNED "Support unaligned reads on platforms that support it") + +if(BASEARCH_ARM_FOUND) + add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE") + add_feature_info(WITH_NEON WITH_NEON "Build with NEON intrinsics") +elseif(BASEARCH_PPC_FOUND) + add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8") +elseif(BASEARCH_S360_FOUND) + add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z") + add_feature_info(WITH_DFLTCC_INFLATE WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z") +elseif(BASEARCH_X86_FOUND) + add_feature_info(WITH_AVX2 WITH_AVX2 "Build with AVX2") + add_feature_info(WITH_SSE2 WITH_SSE2 "Build with SSE2") + add_feature_info(WITH_SSSE3 WITH_SSSE3 "Build with SSSE3") + add_feature_info(WITH_SSE4 WITH_SSE4 "Build with SSE4") + add_feature_info(WITH_PCLMULQDQ WITH_PCLMULQDQ "Build with PCLMULQDQ") +endif() + +add_feature_info(INSTALL_UTILS INSTALL_UTILS "Copy minigzip and minideflate during install") + FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES) From 5b9a497d0d2421b01c6a370bdb1a1f1c17639721 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Thu, 17 Jun 2021 22:47:57 +0200 Subject: [PATCH 091/798] Minor optimization of inftrees.c based on profiling --- inftrees.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/inftrees.c b/inftrees.c index 136e25c2b1..eb82ff4427 100644 --- a/inftrees.c +++ b/inftrees.c @@ -108,7 +108,7 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, for (max = MAXBITS; max >= 1; max--) if (count[max] != 0) break; root = MIN(root, max); - if (max == 0) { /* no symbols to code at all */ + if (UNLIKELY(max == 0)) { /* no symbols to code at all */ here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)1; here.val = (uint16_t)0; @@ -208,12 +208,12 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); - if (work[sym] + 1U < match) { - here.op = (unsigned char)0; - here.val = work[sym]; - } else if (work[sym] >= match) { + if (LIKELY(work[sym] >= match)) { here.op = (unsigned char)(extra[work[sym] - match]); here.val = base[work[sym] - match]; + } else if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ here.val = 0; @@ -283,7 +283,7 @@ int Z_INTERNAL zng_inflate_table(codetype type, uint16_t *lens, unsigned codes, /* fill in remaining table entry if code is incomplete (guaranteed to have at most one remaining entry, since if the code is incomplete, the maximum code length that was allowed to get this far is one bit) */ - if (huff != 0) { + if (UNLIKELY(huff != 0)) { here.op = (unsigned char)64; /* invalid code marker */ here.bits = (unsigned char)(len - drop); here.val = (uint16_t)0; From 21050e06c511a67f3239d1bca444616be6853bfe Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Mon, 21 Jun 2021 09:07:59 +0300 Subject: [PATCH 092/798] Cast calculation of safe length to unsigned int to avoid compiler warnings. --- chunkset_tpl.h | 3 ++- inffast.c | 2 +- win32/Makefile.msc | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 256475a641..ff760fcf69 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -38,7 +38,8 @@ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { /* Behave like chunkcopy, but avoid writing beyond of legal output. */ Z_INTERNAL uint8_t* CHUNKCOPY_SAFE(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe) { - len = MIN(len, safe - out + 1); + unsigned safelen = (unsigned)((safe - out) + 1); + len = MIN(len, safelen); #if CHUNK_SIZE >= 32 while (len >= 32) { memcpy(out, from, 32); diff --git a/inffast.c b/inffast.c index c431e50fc1..136b98d5a6 100644 --- a/inffast.c +++ b/inffast.c @@ -270,7 +270,7 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { if (dist >= len || dist >= state->chunksize) out = functable.chunkcopy_safe(out, out - dist, len, safe); else - out = functable.chunkmemset_safe(out, dist, len, safe - out + 1); + out = functable.chunkmemset_safe(out, dist, len, (unsigned)((safe - out) + 1)); } else { /* Whole reference is in range of current output. No range checks are necessary because we start with room for at least 258 bytes of output, diff --git a/win32/Makefile.msc b/win32/Makefile.msc index ee6f857d76..b7166616b3 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -114,7 +114,7 @@ $(IMPLIB): $(SHAREDLIB) $(SHAREDLIB): zconf $(TOP)/win32/$(DEFFILE) $(OBJS) $(RESFILE) $(LD) $(LDFLAGS) -def:$(TOP)/win32/$(DEFFILE) -dll -implib:$(IMPLIB) \ - -out:$@ -base:0x5A4C0000 $(OBJS) $(RESFILE) + -out:$@ $(OBJS) $(RESFILE) if exist $@.manifest \ mt -nologo -manifest $@.manifest -outputresource:$@;2 From c0cca0854206e25b41f1ee403dfb9a522ba85328 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 22 Jun 2021 01:41:16 +0300 Subject: [PATCH 093/798] [functable] Add missing call to cpu_check_features(). --- functable.c | 1 + 1 file changed, 1 insertion(+) diff --git a/functable.c b/functable.c index acae446419..32ab90ed3a 100644 --- a/functable.c +++ b/functable.c @@ -241,6 +241,7 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ Z_INTERNAL uint32_t chunksize_stub(void) { // Initialize default functable.chunksize = &chunksize_c; + cpu_check_features(); #ifdef X86_SSE2_CHUNKSET # if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) From 694878996926ba75373d62c9a8011c1b01a1cb0b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 10 Jun 2021 17:25:27 -0700 Subject: [PATCH 094/798] Added rolling hash functions for hash table. --- CMakeLists.txt | 1 + Makefile.in | 2 ++ arch/arm/insert_string_acle.c | 8 +++-- arch/x86/insert_string_sse.c | 14 +++++--- deflate.c | 1 + deflate.h | 2 ++ insert_string.c | 20 +++++------ insert_string_roll.c | 24 +++++++++++++ insert_string_tpl.h | 67 +++++++++++++++++++---------------- win32/Makefile.a64 | 1 + win32/Makefile.arm | 1 + win32/Makefile.msc | 1 + 12 files changed, 93 insertions(+), 49 deletions(-) create mode 100644 insert_string_roll.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b477ff37af..678f9e3e68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -821,6 +821,7 @@ set(ZLIB_SRCS inflate.c inftrees.c insert_string.c + insert_string_roll.c trees.c uncompr.c zutil.c diff --git a/Makefile.in b/Makefile.in index 2c70ee1d52..379cab5292 100644 --- a/Makefile.in +++ b/Makefile.in @@ -92,6 +92,7 @@ OBJZ = \ inflate.o \ inftrees.o \ insert_string.o \ + insert_string_roll.o \ trees.o \ uncompr.o \ zutil.o \ @@ -125,6 +126,7 @@ PIC_OBJZ = \ inflate.lo \ inftrees.lo \ insert_string.lo \ + insert_string_roll.lo \ trees.lo \ uncompr.lo \ zutil.lo \ diff --git a/arch/arm/insert_string_acle.c b/arch/arm/insert_string_acle.c index 2daf9ba3e1..de99023844 100644 --- a/arch/arm/insert_string_acle.c +++ b/arch/arm/insert_string_acle.c @@ -1,4 +1,4 @@ -/* insert_string_acle.c -- insert_string variant using ACLE's CRC instructions +/* insert_string_acle.c -- insert_string integer hash variant using ACLE's CRC instructions * * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h @@ -12,9 +12,13 @@ #include "../../zbuild.h" #include "../../deflate.h" -#define UPDATE_HASH(s, h, val) \ +#define HASH_CALC(s, h, val) \ h = __crc32w(0, val) +#define HASH_CALC_VAR h +#define HASH_CALC_VAR_INIT uint32_t h = 0 + +#define UPDATE_HASH update_hash_acle #define INSERT_STRING insert_string_acle #define QUICK_INSERT_STRING quick_insert_string_acle diff --git a/arch/x86/insert_string_sse.c b/arch/x86/insert_string_sse.c index d0c316b199..7a63b2a7bf 100644 --- a/arch/x86/insert_string_sse.c +++ b/arch/x86/insert_string_sse.c @@ -1,4 +1,4 @@ -/* insert_string_sse -- insert_string variant using SSE4.2's CRC instructions +/* insert_string_sse.c -- insert_string integer hash variant using SSE4.2's CRC instructions * * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h @@ -14,22 +14,22 @@ #ifdef X86_SSE42_CRC_INTRIN # ifdef _MSC_VER -# define UPDATE_HASH(s, h, val)\ +# define HASH_CALC(s, h, val)\ h = _mm_crc32_u32(h, val) # else -# define UPDATE_HASH(s, h, val)\ +# define HASH_CALC(s, h, val)\ h = __builtin_ia32_crc32si(h, val) # endif #else # ifdef _MSC_VER -# define UPDATE_HASH(s, h, val) {\ +# define HASH_CALC(s, h, val) {\ __asm mov edx, h\ __asm mov eax, val\ __asm crc32 eax, edx\ __asm mov val, eax\ } # else -# define UPDATE_HASH(s, h, val) \ +# define HASH_CALC(s, h, val) \ __asm__ __volatile__ (\ "crc32 %1,%0\n\t"\ : "+r" (h)\ @@ -38,6 +38,10 @@ # endif #endif +#define HASH_CALC_VAR h +#define HASH_CALC_VAR_INIT uint32_t h = 0 + +#define UPDATE_HASH update_hash_sse4 #define INSERT_STRING insert_string_sse4 #define QUICK_INSERT_STRING quick_insert_string_sse4 diff --git a/deflate.c b/deflate.c index e512e5e9df..466e6e9bb3 100644 --- a/deflate.c +++ b/deflate.c @@ -1162,6 +1162,7 @@ static void lm_init(deflate_state *s) { s->prev_length = 0; s->match_available = 0; s->match_start = 0; + s->ins_h = 0; } /* =========================================================================== diff --git a/deflate.h b/deflate.h index 16e63c75ab..808060a385 100644 --- a/deflate.h +++ b/deflate.h @@ -155,6 +155,8 @@ typedef struct internal_state { Pos *head; /* Heads of the hash chains or 0. */ + uint32_t ins_h; /* hash index of string to be inserted */ + int block_start; /* Window position at the beginning of the current output block. Gets * negative when the window is moved backwards. diff --git a/insert_string.c b/insert_string.c index 4ddf9ae5db..cfe39837f8 100644 --- a/insert_string.c +++ b/insert_string.c @@ -1,4 +1,4 @@ -/* insert_string_c -- insert_string variant for c +/* insert_string.c -- insert_string integer hash variant * * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h @@ -8,18 +8,14 @@ #include "zbuild.h" #include "deflate.h" -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define HASH_SLIDE 16 // Number of bits to slide hash +#define HASH_SLIDE 16 -#define UPDATE_HASH(s, h, val) \ - h = ((val * 2654435761U) >> HASH_SLIDE); +#define HASH_CALC(s, h, val) h = ((val * 2654435761U) >> HASH_SLIDE); +#define HASH_CALC_VAR h +#define HASH_CALC_VAR_INIT uint32_t h = 0 -#define INSERT_STRING insert_string_c -#define QUICK_INSERT_STRING quick_insert_string_c +#define UPDATE_HASH update_hash_c +#define INSERT_STRING insert_string_c +#define QUICK_INSERT_STRING quick_insert_string_c #include "insert_string_tpl.h" diff --git a/insert_string_roll.c b/insert_string_roll.c new file mode 100644 index 0000000000..dfea347bcc --- /dev/null +++ b/insert_string_roll.c @@ -0,0 +1,24 @@ +/* insert_string_roll.c -- insert_string rolling hash variant + * + * 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" + +#define HASH_SLIDE 5 + +#define HASH_CALC(s, h, val) h = ((h << HASH_SLIDE) ^ ((uint8_t)val)) +#define HASH_CALC_VAR s->ins_h +#define HASH_CALC_VAR_INIT +#define HASH_CALC_READ val = strstart[0] +#define HASH_CALC_MASK (32768u - 1u) +#define HASH_CALC_OFFSET (STD_MIN_MATCH-1) + +#define UPDATE_HASH update_hash_roll +#define INSERT_STRING insert_string_roll +#define QUICK_INSERT_STRING quick_insert_string_roll + +#include "insert_string_tpl.h" diff --git a/insert_string_tpl.h b/insert_string_tpl.h index 11d54643fe..e2c840bb2d 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -22,27 +22,40 @@ * */ +#ifndef HASH_CALC_OFFSET +# define HASH_CALC_OFFSET 0 +#endif +#ifndef HASH_CALC_MASK +# define HASH_CALC_MASK HASH_MASK +#endif +#ifndef HASH_CALC_READ +# ifdef UNALIGNED_OK +# define HASH_CALC_READ \ + val = *(uint32_t *)(strstart); +# else +# define HASH_CALC_READ \ + val = ((uint32_t)(strstart[0])); \ + val |= ((uint32_t)(strstart[1]) << 8); \ + val |= ((uint32_t)(strstart[2]) << 16); \ + val |= ((uint32_t)(strstart[3]) << 24); +# endif +#endif + /* =========================================================================== * Quick insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return * the previous length of the hash chain. */ -Z_INTERNAL Pos QUICK_INSERT_STRING(deflate_state *const s, const uint32_t str) { +Z_INTERNAL Pos QUICK_INSERT_STRING(deflate_state *const s, uint32_t str) { Pos head; - uint8_t *strstart = s->window + str; - uint32_t val, hm, h = 0; + uint8_t *strstart = s->window + str + HASH_CALC_OFFSET; + uint32_t val, hm; -#ifdef UNALIGNED_OK - val = *(uint32_t *)(strstart); -#else - val = ((uint32_t)(strstart[0])); - val |= ((uint32_t)(strstart[1]) << 8); - val |= ((uint32_t)(strstart[2]) << 16); - val |= ((uint32_t)(strstart[3]) << 24); -#endif - - UPDATE_HASH(s, h, val); - hm = h & HASH_MASK; + HASH_CALC_VAR_INIT; + HASH_CALC_READ; + HASH_CALC(s, HASH_CALC_VAR, val); + HASH_CALC_VAR &= HASH_CALC_MASK; + hm = HASH_CALC_VAR; head = s->head[hm]; if (LIKELY(head != str)) { @@ -60,24 +73,18 @@ Z_INTERNAL Pos QUICK_INSERT_STRING(deflate_state *const s, const uint32_t str) { * input characters and the first STD_MIN_MATCH bytes of str are valid * (except for the last STD_MIN_MATCH-1 bytes of the input file). */ -Z_INTERNAL void INSERT_STRING(deflate_state *const s, const uint32_t str, uint32_t count) { - uint8_t *strstart = s->window + str; - uint8_t *strend = strstart + count - 1; /* last position */ - - for (Pos idx = (Pos)str; strstart <= strend; idx++, strstart++) { - uint32_t val, hm, h = 0; +Z_INTERNAL void INSERT_STRING(deflate_state *const s, uint32_t str, uint32_t count) { + uint8_t *strstart = s->window + str + HASH_CALC_OFFSET; + uint8_t *strend = strstart + count; -#ifdef UNALIGNED_OK - val = *(uint32_t *)(strstart); -#else - val = ((uint32_t)(strstart[0])); - val |= ((uint32_t)(strstart[1]) << 8); - val |= ((uint32_t)(strstart[2]) << 16); - val |= ((uint32_t)(strstart[3]) << 24); -#endif + for (Pos idx = (Pos)str; strstart < strend; idx++, strstart++) { + uint32_t val, hm; - UPDATE_HASH(s, h, val); - hm = h & HASH_MASK; + HASH_CALC_VAR_INIT; + HASH_CALC_READ; + HASH_CALC(s, HASH_CALC_VAR, val); + HASH_CALC_VAR &= HASH_CALC_MASK; + hm = HASH_CALC_VAR; Pos head = s->head[hm]; if (LIKELY(head != idx)) { diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 136e32d4d7..a272810a87 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -63,6 +63,7 @@ OBJS = \ inftrees.obj \ inffast.obj \ insert_string.obj \ + insert_string_roll.obj \ trees.obj \ uncompr.obj \ zutil.obj \ diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 92eed88ad6..23ed761a4a 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -66,6 +66,7 @@ OBJS = \ inftrees.obj \ inffast.obj \ insert_string.obj \ + insert_string_roll.obj \ trees.obj \ uncompr.obj \ zutil.obj \ diff --git a/win32/Makefile.msc b/win32/Makefile.msc index b7166616b3..94462f5968 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -73,6 +73,7 @@ OBJS = \ inftrees.obj \ inffast.obj \ insert_string.obj \ + insert_string_roll.obj \ insert_string_sse.obj \ slide_avx.obj \ slide_sse.obj \ From 5998d5b63211784bd8e44b2ba80ee63d2643f65c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Jun 2021 17:27:37 -0700 Subject: [PATCH 095/798] Added update_hash to build hash incrementally. --- functable.c | 28 +++++++++++++++++++++++++++- functable.h | 5 +++-- insert_string_tpl.h | 12 ++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/functable.c b/functable.c index 32ab90ed3a..8fc94c5c11 100644 --- a/functable.c +++ b/functable.c @@ -14,6 +14,14 @@ # include "fallback_builtins.h" #endif +/* update_hash */ +extern uint32_t update_hash_c(deflate_state *const s, uint32_t h, uint32_t val); +#ifdef X86_SSE42_CRC_HASH +extern uint32_t update_hash_sse4(deflate_state *const s, uint32_t h, uint32_t val); +#elif defined(ARM_ACLE_CRC_HASH) +extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); +#endif + /* insert_string */ extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); #ifdef X86_SSE42_CRC_HASH @@ -152,7 +160,24 @@ Z_INTERNAL void cpu_check_features(void) } /* stub functions */ -Z_INTERNAL void insert_string_stub(deflate_state *const s, const uint32_t str, uint32_t count) { +Z_INTERNAL uint32_t update_hash_stub(deflate_state *const s, uint32_t h, uint32_t val) { + // Initialize default + + functable.update_hash = &update_hash_c; + cpu_check_features(); + +#ifdef X86_SSE42_CRC_HASH + if (x86_cpu_has_sse42) + functable.update_hash = &update_hash_sse4; +#elif defined(ARM_ACLE_CRC_HASH) + if (arm_cpu_has_crc32) + functable.update_hash = &update_hash_acle; +#endif + + return functable.update_hash(s, h, val); +} + +Z_INTERNAL void insert_string_stub(deflate_state *const s, uint32_t str, uint32_t count) { // Initialize default functable.insert_string = &insert_string_c; @@ -451,6 +476,7 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { + update_hash_stub, insert_string_stub, quick_insert_string_stub, adler32_stub, diff --git a/functable.h b/functable.h index 276c284a09..49d2f5d569 100644 --- a/functable.h +++ b/functable.h @@ -9,8 +9,9 @@ #include "deflate.h" struct functable_s { - void (* insert_string) (deflate_state *const s, const uint32_t str, uint32_t count); - Pos (* quick_insert_string)(deflate_state *const s, const uint32_t str); + uint32_t (* update_hash) (deflate_state *const s, uint32_t h, uint32_t val); + void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); + Pos (* quick_insert_string)(deflate_state *const s, uint32_t str); uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, size_t len); uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); void (* slide_hash) (deflate_state *s); diff --git a/insert_string_tpl.h b/insert_string_tpl.h index e2c840bb2d..c116544f9d 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -41,6 +41,18 @@ # endif #endif +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +Z_INTERNAL uint32_t UPDATE_HASH(deflate_state *const s, uint32_t h, uint32_t val) { + (void)s; + HASH_CALC(s, h, val); + return h & HASH_CALC_MASK; +} + /* =========================================================================== * Quick insert string str in the dictionary and set match_head to the previous head * of the hash chain (the most recent string with same hash key). Return From 1c766dbf67fdae3f1f7be25b4af9995e00adcd35 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Jun 2021 17:36:55 -0700 Subject: [PATCH 096/798] Setup hash functions to be switched based on compression level. --- deflate.c | 33 ++++++++++++++++++++++----------- deflate.h | 16 ++++++++++++++-- deflate_slow.c | 5 ++--- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/deflate.c b/deflate.c index 466e6e9bb3..e361b38393 100644 --- a/deflate.c +++ b/deflate.c @@ -113,6 +113,7 @@ Z_INTERNAL block_state deflate_medium(deflate_state *s, int flush); Z_INTERNAL block_state deflate_slow (deflate_state *s, int flush); Z_INTERNAL block_state deflate_rle (deflate_state *s, int flush); Z_INTERNAL block_state deflate_huff (deflate_state *s, int flush); +static void lm_set_level (deflate_state *s, int level); static void lm_init (deflate_state *s); Z_INTERNAL unsigned read_buf (PREFIX3(stream) *strm, unsigned char *buf, unsigned size); @@ -602,11 +603,8 @@ int32_t Z_EXPORT PREFIX(deflateParams)(PREFIX3(stream) *strm, int32_t level, int } s->matches = 0; } - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; + + lm_set_level(s, level); } s->strategy = strategy; return Z_OK; @@ -1140,6 +1138,22 @@ Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned return len; } +/* =========================================================================== + * Set longest match variables based on level configuration + */ +static void lm_set_level(deflate_state *s, int level) { + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + + s->update_hash = functable.update_hash; + s->insert_string = functable.insert_string; + s->quick_insert_string = functable.quick_insert_string; + + s->level = level; +} + /* =========================================================================== * Initialize the "longest match" routines for a new zlib stream */ @@ -1150,10 +1164,7 @@ static void lm_init(deflate_state *s) { /* Set the default configuration parameters: */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; + lm_set_level(s, s->level); s->strstart = 0; s->block_start = 0; @@ -1227,7 +1238,7 @@ void Z_INTERNAL fill_window(deflate_state *s) { if (s->lookahead + s->insert >= STD_MIN_MATCH) { unsigned int str = s->strstart - s->insert; if (str >= 1) - functable.quick_insert_string(s, str + 2 - STD_MIN_MATCH); + s->quick_insert_string(s, str + 2 - STD_MIN_MATCH); unsigned int count; if (UNLIKELY(s->lookahead == 1)) { count = s->insert - 1; @@ -1235,7 +1246,7 @@ void Z_INTERNAL fill_window(deflate_state *s) { count = s->insert; } if (count > 0) { - functable.insert_string(s, str, count); + s->insert_string(s, str, count); s->insert -= count; } } diff --git a/deflate.h b/deflate.h index 808060a385..0a50afe23a 100644 --- a/deflate.h +++ b/deflate.h @@ -99,8 +99,14 @@ typedef uint16_t Pos; /* A Pos is an index in the character window. We use short instead of int to * save space in the various tables. */ +/* Type definitions for hash callbacks */ +typedef struct internal_state deflate_state; -typedef struct internal_state { +typedef uint32_t (* update_hash_cb) (deflate_state *const s, uint32_t h, uint32_t val); +typedef void (* insert_string_cb) (deflate_state *const s, uint32_t str, uint32_t count); +typedef Pos (* quick_insert_string_cb)(deflate_state *const s, uint32_t str); + +struct internal_state { PREFIX3(stream) *strm; /* pointer back to this zlib stream */ unsigned char *pending_buf; /* output still pending */ unsigned char *pending_out; /* next pending byte to output to the stream */ @@ -188,6 +194,12 @@ typedef struct internal_state { * max_insert_length is used only for compression levels <= 3. */ + update_hash_cb update_hash; + insert_string_cb insert_string; + quick_insert_string_cb quick_insert_string; + /* Hash function callbacks that can be configured depending on the deflate + * algorithm being used */ + int level; /* compression level (1..9) */ int strategy; /* favor or force Huffman coding*/ @@ -269,7 +281,7 @@ typedef struct internal_state { /* Reserved for future use and alignment purposes */ int32_t reserved[11]; -} ALIGNED_(8) deflate_state; +} ALIGNED_(8); typedef enum { need_more, /* block not completed, need more input or more output */ diff --git a/deflate_slow.c b/deflate_slow.c index ac7e87ee50..0cb40f5ca0 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -41,7 +41,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { */ hash_head = 0; if (LIKELY(s->lookahead >= WANT_MIN_MATCH)) { - hash_head = functable.quick_insert_string(s, s->strstart); + hash_head = s->quick_insert_string(s, s->strstart); } /* Find the longest match, discarding those <= prev_length. @@ -88,8 +88,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { unsigned int insert_cnt = mov_fwd; if (UNLIKELY(insert_cnt > max_insert - s->strstart)) insert_cnt = max_insert - s->strstart; - - functable.insert_string(s, s->strstart + 1, insert_cnt); + s->insert_string(s, s->strstart + 1, insert_cnt); } s->prev_length = 0; s->match_available = 0; From 823a61bc972b1c08267b752a84dd959160c9f73d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 13 Jun 2021 14:59:32 -0700 Subject: [PATCH 097/798] Use STD_MIN_MATCH instead of WANT_MIN_MATCH in deflate_slow for fast-zlib. --- deflate_slow.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deflate_slow.c b/deflate_slow.c index 0cb40f5ca0..a3af11bcfe 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -68,8 +68,8 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { /* If there was a match at the previous step and the current * match is not better, output the previous match: */ - if (s->prev_length >= WANT_MIN_MATCH && match_len <= s->prev_length) { - unsigned int max_insert = s->strstart + s->lookahead - WANT_MIN_MATCH; + if (s->prev_length >= STD_MIN_MATCH && match_len <= s->prev_length) { + unsigned int max_insert = s->strstart + s->lookahead - STD_MIN_MATCH; /* Do not insert strings in hash table beyond this. */ check_match(s, s->strstart-1, s->prev_match, s->prev_length); From d87a9f96d0dd863e9cd330a8400e66e93760997d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Jun 2021 17:40:03 -0700 Subject: [PATCH 098/798] Incorporate fast-zlib algorithm changes into longest_match. --- match_tpl.h | 112 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 106 insertions(+), 6 deletions(-) diff --git a/match_tpl.h b/match_tpl.h index 04eac1aa8f..3d8ac4e3c5 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -1,3 +1,12 @@ +/* match_tpl.h -- find longest match template for compare256 variants + * + * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Portions copyright (C) 2014-2021 Konstantin Nosov + * Fast-zlib optimized longest_match + * https://github.com/gildor2/fast_zlib + */ #include "zbuild.h" #include "deflate.h" @@ -36,10 +45,12 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { Z_REGISTER unsigned char *mbase_start = window; Z_REGISTER unsigned char *mbase_end; const Pos *prev = s->prev; - Pos limit; + Pos limit, limit_base; int32_t early_exit; uint32_t chain_length, nice_match, best_len, offset; uint32_t lookahead = s->lookahead; + Pos match_offset = 0; + int32_t rolling_hash; bestcmp_t scan_end; #ifndef UNALIGNED_OK bestcmp_t scan_end0; @@ -55,7 +66,7 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { /* The code is optimized for STD_MAX_MATCH-2 multiple of 16. */ Assert(STD_MAX_MATCH == 258, "Code too clever"); - best_len = s->prev_length ? s->prev_length : 1; + best_len = s->prev_length ? s->prev_length : STD_MIN_MATCH-1; /* Calculate read offset which should only extend an extra byte * to find the next best match length. @@ -81,6 +92,7 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { /* Do not waste too much time if we already have a good match */ chain_length = s->max_chain_length; + rolling_hash = chain_length > 1024; early_exit = s->level < EARLY_EXIT_TRIGGER_LEVEL; if (best_len >= s->good_match) chain_length >>= 2; @@ -89,7 +101,38 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0 */ - limit = strstart > MAX_DIST(s) ? (Pos)(strstart - MAX_DIST(s)) : 0; + limit = limit_base = strstart > MAX_DIST(s) ? (Pos)(strstart - MAX_DIST(s)) : 0; + + if (best_len >= STD_MIN_MATCH && rolling_hash) { + /* We're continuing search (lazy evaluation). */ + uint32_t i, hash; + Pos pos; + + /* Find a most distant chain starting from scan with index=1 (index=0 corresponds + * to cur_match). We cannot use s->prev[strstart+1,...] immediately, because + * these strings are not yet inserted into the hash table. + */ + hash = s->update_hash(s, 0, scan[1]); + hash = s->update_hash(s, hash, scan[2]); + + for (i = 3; i <= best_len; i++) { + hash = s->update_hash(s, hash, scan[i]); + + /* If we're starting with best_len >= 3, we can use offset search. */ + pos = s->head[hash]; + if (pos < cur_match) { + match_offset = (Pos)(i - 2); + cur_match = pos; + } + } + + /* Update offset-dependent variables */ + limit = limit_base+match_offset; + if (cur_match <= limit) + goto break_matching; + mbase_start -= match_offset; + mbase_end -= match_offset; + } Assert((unsigned long)strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); for (;;) { @@ -140,7 +183,9 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { Assert(scan+len <= window+(unsigned)(s->window_size-1), "wild scan"); if (len > best_len) { - s->match_start = cur_match; + uint32_t match_start = cur_match - match_offset; + s->match_start = match_start; + /* Do not look for matches beyond the end of the input. */ if (len > lookahead) return lookahead; @@ -162,7 +207,56 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #ifndef UNALIGNED_OK scan_end0 = *(bestcmp_t *)(scan+offset+1); #endif - mbase_end = (mbase_start+offset); + /* Look for a better string offset */ + if (len > STD_MIN_MATCH && match_start + len < strstart && rolling_hash) { + Pos pos, next_pos; + uint32_t i, hash; + unsigned char *scan_endstr; + + /* Go back to offset 0 */ + cur_match -= match_offset; + match_offset = 0; + next_pos = cur_match; + for (i = 0; i <= len - STD_MIN_MATCH; i++) { + pos = prev[(cur_match + i) & wmask]; + if (pos < next_pos) { + /* Hash chain is more distant, use it */ + if (pos <= limit_base + i) + goto break_matching; + next_pos = pos; + match_offset = (Pos)i; + } + } + /* Switch cur_match to next_pos chain */ + cur_match = next_pos; + + /* Try hash head at len-(STD_MIN_MATCH-1) position to see if we could get + * a better cur_match at the end of string. Using (STD_MIN_MATCH-1) lets + * us include one more byte into hash - the byte which will be checked + * in main loop now, and which allows to grow match by 1. + */ + scan_endstr = scan + len - (STD_MIN_MATCH+1); + + hash = s->update_hash(s, 0, scan_endstr[0]); + hash = s->update_hash(s, hash, scan_endstr[1]); + hash = s->update_hash(s, hash, scan_endstr[2]); + + pos = s->head[hash]; + if (pos < cur_match) { + match_offset = (Pos)(len - (STD_MIN_MATCH+1)); + if (pos <= limit_base + match_offset) + goto break_matching; + cur_match = pos; + } + + /* Update offset-dependent variables */ + limit = limit_base+match_offset; + mbase_start = window-match_offset; + mbase_end = (mbase_start+offset); + continue; + } else { + mbase_end = (mbase_start+offset); + } } else if (UNLIKELY(early_exit)) { /* The probability of finding a match later if we here is pretty low, so for * performance it's best to outright stop here for the lower compression levels @@ -171,8 +265,14 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { } GOTO_NEXT_CHAIN; } - return best_len; + +break_matching: + + if (best_len < s->lookahead) + return best_len; + + return s->lookahead; } #undef LONGEST_MATCH From 608b1c2020b7e41618dc3a005d68927097253246 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Jun 2021 17:41:37 -0700 Subject: [PATCH 099/798] Enable rolling hash function switching for fast-zlib. --- deflate.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/deflate.c b/deflate.c index e361b38393..2c0c8499f4 100644 --- a/deflate.c +++ b/deflate.c @@ -123,6 +123,10 @@ extern void crc_finalize(deflate_state *const s); #endif extern void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size); +extern uint32_t update_hash_roll (deflate_state *const s, uint32_t h, uint32_t val); +extern void insert_string_roll (deflate_state *const s, uint32_t str, uint32_t count); +extern Pos quick_insert_string_roll(deflate_state *const s, uint32_t str); + /* =========================================================================== * Local data */ @@ -1147,9 +1151,18 @@ static void lm_set_level(deflate_state *s, int level) { s->nice_match = configuration_table[level].nice_length; s->max_chain_length = configuration_table[level].max_chain; - s->update_hash = functable.update_hash; - s->insert_string = functable.insert_string; - s->quick_insert_string = functable.quick_insert_string; + /* Use rolling hash for deflate_slow algorithm with level 9. It allows us to + * properly lookup different hash chains to speed up longest_match search. Since hashing + * method changes depending on the level we cannot put this into functable. */ + if (s->max_chain_length > 1024) { + s->update_hash = &update_hash_roll; + s->insert_string = &insert_string_roll; + s->quick_insert_string = &quick_insert_string_roll; + } else { + s->update_hash = functable.update_hash; + s->insert_string = functable.insert_string; + s->quick_insert_string = functable.quick_insert_string; + } s->level = level; } @@ -1237,8 +1250,11 @@ void Z_INTERNAL fill_window(deflate_state *s) { /* Initialize the hash value now that we have some input: */ if (s->lookahead + s->insert >= STD_MIN_MATCH) { unsigned int str = s->strstart - s->insert; - if (str >= 1) + if (s->max_chain_length > 1024) { + s->ins_h = s->update_hash(s, s->window[str], s->window[str+1]); + } else if (str >= 1) { s->quick_insert_string(s, str + 2 - STD_MIN_MATCH); + } unsigned int count; if (UNLIKELY(s->lookahead == 1)) { count = s->insert - 1; From a8543ecaa4824994827708d3e5684777eaeb4cfc Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Jun 2021 17:42:24 -0700 Subject: [PATCH 100/798] Minor prev_length calculation improvement in deflate_slow. --- deflate_slow.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deflate_slow.c b/deflate_slow.c index a3af11bcfe..e0232c0a13 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -81,9 +81,10 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { * enough lookahead, the last two strings are not inserted in * the hash table. */ - s->lookahead -= s->prev_length-1; + s->prev_length -= 1; + s->lookahead -= s->prev_length; - unsigned int mov_fwd = s->prev_length - 2; + unsigned int mov_fwd = s->prev_length - 1; if (max_insert > s->strstart) { unsigned int insert_cnt = mov_fwd; if (UNLIKELY(insert_cnt > max_insert - s->strstart)) From ef416b7e2747620189b666ec82179bff369c35a7 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 21 Jun 2021 20:38:51 -0700 Subject: [PATCH 101/798] Separate fast-zlib matching algorithm into its own longest_match variant. --- arch/x86/compare258_avx.c | 13 +++++++--- arch/x86/compare258_sse.c | 13 +++++++--- compare258.c | 52 ++++++++++++++++++++++++++++++--------- functable.c | 42 +++++++++++++++++++++++++++++++ functable.h | 1 + match_tpl.h | 31 +++++++++++++++++------ 6 files changed, 126 insertions(+), 26 deletions(-) diff --git a/arch/x86/compare258_avx.c b/arch/x86/compare258_avx.c index d9108fdeb0..3452127f5a 100644 --- a/arch/x86/compare258_avx.c +++ b/arch/x86/compare258_avx.c @@ -58,9 +58,16 @@ Z_INTERNAL uint32_t compare258_unaligned_avx2(const unsigned char *src0, const u return compare258_unaligned_avx2_static(src0, src1); } -#define LONGEST_MATCH longest_match_unaligned_avx2 -#define COMPARE256 compare256_unaligned_avx2_static -#define COMPARE258 compare258_unaligned_avx2_static +#define LONGEST_MATCH longest_match_unaligned_avx2 +#define COMPARE256 compare256_unaligned_avx2_static +#define COMPARE258 compare258_unaligned_avx2_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_avx2 +#define COMPARE256 compare256_unaligned_avx2_static +#define COMPARE258 compare258_unaligned_avx2_static #include "match_tpl.h" diff --git a/arch/x86/compare258_sse.c b/arch/x86/compare258_sse.c index 17534c0519..1bea2e95bd 100644 --- a/arch/x86/compare258_sse.c +++ b/arch/x86/compare258_sse.c @@ -65,9 +65,16 @@ Z_INTERNAL uint32_t compare258_unaligned_sse4(const unsigned char *src0, const u return compare258_unaligned_sse4_static(src0, src1); } -#define LONGEST_MATCH longest_match_unaligned_sse4 -#define COMPARE256 compare256_unaligned_sse4_static -#define COMPARE258 compare258_unaligned_sse4_static +#define LONGEST_MATCH longest_match_unaligned_sse4 +#define COMPARE256 compare256_unaligned_sse4_static +#define COMPARE258 compare258_unaligned_sse4_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_sse4 +#define COMPARE256 compare256_unaligned_sse4_static +#define COMPARE258 compare258_unaligned_sse4_static #include "match_tpl.h" diff --git a/compare258.c b/compare258.c index 6b452b89cc..f4f1936c45 100644 --- a/compare258.c +++ b/compare258.c @@ -57,9 +57,16 @@ Z_INTERNAL uint32_t compare258_c(const unsigned char *src0, const unsigned char return compare258_c_static(src0, src1); } -#define LONGEST_MATCH longest_match_c -#define COMPARE256 compare256_c_static -#define COMPARE258 compare258_c_static +#define LONGEST_MATCH longest_match_c +#define COMPARE256 compare256_c_static +#define COMPARE258 compare258_c_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_c +#define COMPARE256 compare256_c_static +#define COMPARE258 compare258_c_staticc #include "match_tpl.h" @@ -97,9 +104,16 @@ Z_INTERNAL uint32_t compare258_unaligned_16(const unsigned char *src0, const uns return compare258_unaligned_16_static(src0, src1); } -#define LONGEST_MATCH longest_match_unaligned_16 -#define COMPARE256 compare256_unaligned_16_static -#define COMPARE258 compare258_unaligned_16_static +#define LONGEST_MATCH longest_match_unaligned_16 +#define COMPARE256 compare256_unaligned_16_static +#define COMPARE258 compare258_unaligned_16_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_16 +#define COMPARE256 compare256_unaligned_16_static +#define COMPARE258 compare258_unaligned_16_static #include "match_tpl.h" @@ -135,9 +149,16 @@ Z_INTERNAL uint32_t compare258_unaligned_32(const unsigned char *src0, const uns return compare258_unaligned_32_static(src0, src1); } -#define LONGEST_MATCH longest_match_unaligned_32 -#define COMPARE256 compare256_unaligned_32_static -#define COMPARE258 compare258_unaligned_32_static +#define LONGEST_MATCH longest_match_unaligned_32 +#define COMPARE256 compare256_unaligned_32_static +#define COMPARE258 compare258_unaligned_32_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_32 +#define COMPARE256 compare256_unaligned_32_static +#define COMPARE258 compare258_unaligned_32_static #include "match_tpl.h" @@ -175,9 +196,16 @@ Z_INTERNAL uint32_t compare258_unaligned_64(const unsigned char *src0, const uns return compare258_unaligned_64_static(src0, src1); } -#define LONGEST_MATCH longest_match_unaligned_64 -#define COMPARE256 compare256_unaligned_64_static -#define COMPARE258 compare258_unaligned_64_static +#define LONGEST_MATCH longest_match_unaligned_64 +#define COMPARE256 compare256_unaligned_64_static +#define COMPARE258 compare258_unaligned_64_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_64 +#define COMPARE256 compare256_unaligned_64_static +#define COMPARE258 compare258_unaligned_64_static #include "match_tpl.h" diff --git a/functable.c b/functable.c index 8fc94c5c11..5ed930c108 100644 --- a/functable.c +++ b/functable.c @@ -142,6 +142,22 @@ extern uint32_t longest_match_unaligned_avx2(deflate_state *const s, Pos cur_mat #endif #endif +/* longest_match_slow */ +extern uint32_t longest_match_slow_c(deflate_state *const s, Pos cur_match); +#ifdef UNALIGNED_OK +extern uint32_t longest_match_slow_unaligned_16(deflate_state *const s, Pos cur_match); +extern uint32_t longest_match_slow_unaligned_32(deflate_state *const s, Pos cur_match); +#ifdef UNALIGNED64_OK +extern uint32_t longest_match_slow_unaligned_64(deflate_state *const s, Pos cur_match); +#endif +#ifdef X86_SSE42_CMP_STR +extern uint32_t longest_match_slow_unaligned_sse4(deflate_state *const s, Pos cur_match); +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_slow_unaligned_avx2(deflate_state *const s, Pos cur_match); +#endif +#endif + Z_INTERNAL Z_TLS struct functable_s functable; Z_INTERNAL void cpu_check_features(void) @@ -474,6 +490,31 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { return functable.longest_match(s, cur_match); } +Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_match) { + + functable.longest_match_slow = &longest_match_slow_c; + +#ifdef UNALIGNED_OK +# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) + functable.longest_match_slow = &longest_match_slow_unaligned_64; +# elif defined(HAVE_BUILTIN_CTZ) + functable.longest_match_slow = &longest_match_slow_unaligned_32; +# else + functable.longest_match_slow = &longest_match_slow_unaligned_16; +# endif +# ifdef X86_SSE42_CMP_STR + if (x86_cpu_has_sse42) + functable.longest_match_slow = &longest_match_slow_unaligned_sse4; +# endif +# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_avx2) + functable.longest_match_slow = &longest_match_slow_unaligned_avx2; +# endif +#endif + + return functable.longest_match_slow(s, cur_match); +} + /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { update_hash_stub, @@ -484,6 +525,7 @@ Z_INTERNAL Z_TLS struct functable_s functable = { slide_hash_stub, compare258_stub, longest_match_stub, + longest_match_slow_stub, chunksize_stub, chunkcopy_stub, chunkcopy_safe_stub, diff --git a/functable.h b/functable.h index 49d2f5d569..f4b17569ac 100644 --- a/functable.h +++ b/functable.h @@ -17,6 +17,7 @@ struct functable_s { void (* slide_hash) (deflate_state *s); uint32_t (* compare258) (const unsigned char *src0, const unsigned char *src1); uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); + uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); uint32_t (* chunksize) (void); uint8_t* (* chunkcopy) (uint8_t *out, uint8_t const *from, unsigned len); uint8_t* (* chunkcopy_safe) (uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); diff --git a/match_tpl.h b/match_tpl.h index 3d8ac4e3c5..6e66654556 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -45,12 +45,16 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { Z_REGISTER unsigned char *mbase_start = window; Z_REGISTER unsigned char *mbase_end; const Pos *prev = s->prev; - Pos limit, limit_base; + Pos limit; +#ifdef LONGEST_MATCH_SLOW + Pos limit_base; + int32_t rolling_hash; +#else int32_t early_exit; +#endif uint32_t chain_length, nice_match, best_len, offset; uint32_t lookahead = s->lookahead; Pos match_offset = 0; - int32_t rolling_hash; bestcmp_t scan_end; #ifndef UNALIGNED_OK bestcmp_t scan_end0; @@ -92,8 +96,11 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { /* Do not waste too much time if we already have a good match */ chain_length = s->max_chain_length; +#ifdef LONGEST_MATCH_SLOW rolling_hash = chain_length > 1024; +#else early_exit = s->level < EARLY_EXIT_TRIGGER_LEVEL; +#endif if (best_len >= s->good_match) chain_length >>= 2; nice_match = (uint32_t)s->nice_match; @@ -101,8 +108,9 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0 */ - limit = limit_base = strstart > MAX_DIST(s) ? (Pos)(strstart - MAX_DIST(s)) : 0; - + limit = strstart > MAX_DIST(s) ? (Pos)(strstart - MAX_DIST(s)) : 0; +#ifdef LONGEST_MATCH_SLOW + limit_base = limit; if (best_len >= STD_MIN_MATCH && rolling_hash) { /* We're continuing search (lazy evaluation). */ uint32_t i, hash; @@ -133,7 +141,7 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { mbase_start -= match_offset; mbase_end -= match_offset; } - +#endif Assert((unsigned long)strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); for (;;) { if (cur_match >= strstart) @@ -207,6 +215,7 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #ifndef UNALIGNED_OK scan_end0 = *(bestcmp_t *)(scan+offset+1); #endif +#ifdef LONGEST_MATCH_SLOW /* Look for a better string offset */ if (len > STD_MIN_MATCH && match_start + len < strstart && rolling_hash) { Pos pos, next_pos; @@ -254,27 +263,33 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { mbase_start = window-match_offset; mbase_end = (mbase_start+offset); continue; - } else { - mbase_end = (mbase_start+offset); } - } else if (UNLIKELY(early_exit)) { +#endif + mbase_end = (mbase_start+offset); + } +#ifndef LONGEST_MATCH_SLOW + else if (UNLIKELY(early_exit)) { /* The probability of finding a match later if we here is pretty low, so for * performance it's best to outright stop here for the lower compression levels */ break; } +#endif GOTO_NEXT_CHAIN; } return best_len; +#ifdef LONGEST_MATCH_SLOW break_matching: if (best_len < s->lookahead) return best_len; return s->lookahead; +#endif } +#undef LONGEST_MATCH_SLOW #undef LONGEST_MATCH #undef COMPARE256 #undef COMPARE258 From a0fe6c590d04ce67a52b417287651fa64d8d1e53 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 21 Jun 2021 20:39:47 -0700 Subject: [PATCH 102/798] Use longest_match_slow in deflate_slow. --- deflate_slow.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deflate_slow.c b/deflate_slow.c index e0232c0a13..19bd09fb6e 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -55,7 +55,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ - match_len = functable.longest_match(s, hash_head); + match_len = functable.longest_match_slow(s, hash_head); /* longest_match() sets match_start */ if (match_len <= 5 && (s->strategy == Z_FILTERED)) { From 8916f295e00a942d184a750730740251e9c6aaa7 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 21 Jun 2021 20:43:51 -0700 Subject: [PATCH 103/798] Use UNLIKELY for branches related to rolling hash based on performance profiling. Co-authored-by: Nathan Moinvaziri --- deflate.c | 2 +- match_tpl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deflate.c b/deflate.c index 2c0c8499f4..fa86df0c64 100644 --- a/deflate.c +++ b/deflate.c @@ -1250,7 +1250,7 @@ void Z_INTERNAL fill_window(deflate_state *s) { /* Initialize the hash value now that we have some input: */ if (s->lookahead + s->insert >= STD_MIN_MATCH) { unsigned int str = s->strstart - s->insert; - if (s->max_chain_length > 1024) { + if (UNLIKELY(s->max_chain_length > 1024)) { s->ins_h = s->update_hash(s, s->window[str], s->window[str+1]); } else if (str >= 1) { s->quick_insert_string(s, str + 2 - STD_MIN_MATCH); diff --git a/match_tpl.h b/match_tpl.h index 6e66654556..920f715ad0 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -217,7 +217,7 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif #ifdef LONGEST_MATCH_SLOW /* Look for a better string offset */ - if (len > STD_MIN_MATCH && match_start + len < strstart && rolling_hash) { + if (UNLIKELY(len > STD_MIN_MATCH && match_start + len < strstart && rolling_hash)) { Pos pos, next_pos; uint32_t i, hash; unsigned char *scan_endstr; From e4c622371d8fb4c3700a6da25fd49b88a13f7431 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 22 Jun 2021 17:22:52 -0700 Subject: [PATCH 104/798] Switch longest_match in deflate_slow based on whether or not rolling hash is being used. Co-authored-by: Hans Kristian Rosbach --- deflate.c | 3 --- deflate_p.h | 5 +++++ deflate_slow.c | 8 +++++++- match_tpl.h | 12 ++++-------- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/deflate.c b/deflate.c index fa86df0c64..c66c1e17a5 100644 --- a/deflate.c +++ b/deflate.c @@ -100,9 +100,6 @@ const char PREFIX(deflate_copyright)[] = " deflate 1.2.11.f Copyright 1995-2016 /* =========================================================================== * Function prototypes. */ -typedef block_state (*compress_func) (deflate_state *s, int flush); -/* Compression function. Returns the block state after the call. */ - static int deflateStateCheck (PREFIX3(stream) *strm); Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush); Z_INTERNAL block_state deflate_fast (deflate_state *s, int flush); diff --git a/deflate_p.h b/deflate_p.h index 9b23c51eba..da667a0f9d 100644 --- a/deflate_p.h +++ b/deflate_p.h @@ -108,4 +108,9 @@ static inline int zng_tr_tally_dist(deflate_state *s, uint32_t dist, uint32_t le /* Maximum stored block length in deflate format (not including header). */ #define MAX_STORED 65535 +/* Compression function. Returns the block state after the call. */ +typedef block_state (*compress_func) (deflate_state *s, int flush); +/* Match function. Returns the longest match. */ +typedef uint32_t (*match_func) (deflate_state *const s, Pos cur_match); + #endif diff --git a/deflate_slow.c b/deflate_slow.c index 19bd09fb6e..b8beec9ccd 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -19,6 +19,12 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ int64_t dist; uint32_t match_len; + match_func longest_match; + + if (s->max_chain_length <= 1024) + longest_match = functable.longest_match; + else + longest_match = functable.longest_match_slow; /* Process the input block. */ for (;;) { @@ -55,7 +61,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ - match_len = functable.longest_match_slow(s, hash_head); + match_len = longest_match(s, hash_head); /* longest_match() sets match_start */ if (match_len <= 5 && (s->strategy == Z_FILTERED)) { diff --git a/match_tpl.h b/match_tpl.h index 920f715ad0..e4e31e9819 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -48,7 +48,6 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { Pos limit; #ifdef LONGEST_MATCH_SLOW Pos limit_base; - int32_t rolling_hash; #else int32_t early_exit; #endif @@ -96,11 +95,6 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { /* Do not waste too much time if we already have a good match */ chain_length = s->max_chain_length; -#ifdef LONGEST_MATCH_SLOW - rolling_hash = chain_length > 1024; -#else - early_exit = s->level < EARLY_EXIT_TRIGGER_LEVEL; -#endif if (best_len >= s->good_match) chain_length >>= 2; nice_match = (uint32_t)s->nice_match; @@ -111,7 +105,7 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { limit = strstart > MAX_DIST(s) ? (Pos)(strstart - MAX_DIST(s)) : 0; #ifdef LONGEST_MATCH_SLOW limit_base = limit; - if (best_len >= STD_MIN_MATCH && rolling_hash) { + if (best_len >= STD_MIN_MATCH) { /* We're continuing search (lazy evaluation). */ uint32_t i, hash; Pos pos; @@ -141,6 +135,8 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { mbase_start -= match_offset; mbase_end -= match_offset; } +#else + early_exit = s->level < EARLY_EXIT_TRIGGER_LEVEL; #endif Assert((unsigned long)strstart <= s->window_size - MIN_LOOKAHEAD, "need lookahead"); for (;;) { @@ -217,7 +213,7 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif #ifdef LONGEST_MATCH_SLOW /* Look for a better string offset */ - if (UNLIKELY(len > STD_MIN_MATCH && match_start + len < strstart && rolling_hash)) { + if (UNLIKELY(len > STD_MIN_MATCH && match_start + len < strstart)) { Pos pos, next_pos; uint32_t i, hash; unsigned char *scan_endstr; From 5a66b109d6cf9eb518b815f016edf41302f68eaf Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 17 Mar 2021 23:00:44 -0700 Subject: [PATCH 105/798] Added reduced memory configuration option to CMake and configure. --- CMakeLists.txt | 9 +++++++++ configure | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 678f9e3e68..3ea40b502b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ option(ZLIB_ENABLE_TESTS "Build test binaries" ON) option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) option(WITH_FUZZERS "Build test/fuzz" OFF) option(WITH_OPTIM "Build with optimisation" ON) +option(WITH_REDUCED_MEM "Reduced memory usage for special cases (reduces performance)" ON) option(WITH_NEW_STRATEGIES "Use new strategies" ON) option(WITH_NATIVE_INSTRUCTIONS "Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)" OFF) @@ -109,6 +110,7 @@ option(INSTALL_UTILS "Copy minigzip and minideflate during install" OFF) mark_as_advanced(FORCE ZLIB_DUAL_LINK + WITH_REDUCED_MEM WITH_ACLE WITH_NEON WITH_DFLTCC_DEFLATE WITH_DFLTCC_INFLATE @@ -469,6 +471,13 @@ if(WITH_INFLATE_ALLOW_INVALID_DIST) add_definitions(-DINFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR) message(STATUS "Inflate zero data for invalid distances enabled") endif() +# +# Enable reduced memory configuration +# +if(WITH_REDUCED_MEM) + add_definitions(-DHASH_SIZE=32768u -DGZBUFSIZE=8192) + message(STATUS "Configured for reduced memory environment") +endif() set(ZLIB_ARCH_SRCS) diff --git a/configure b/configure index 5d58e37cd3..911269254d 100755 --- a/configure +++ b/configure @@ -110,6 +110,7 @@ neonflag= noltoflag="-fno-lto" without_optimizations=0 without_new_strategies=0 +reducedmem=0 gcc=0 warn=0 debug=0 @@ -154,6 +155,7 @@ case "$1" in echo ' [--without-neon] Compiles without ARM Neon SIMD instruction set' | tee -a configure.log echo ' [--with-dfltcc-deflate] Use DEFLATE CONVERSION CALL instruction for compression on IBM Z' | tee -a configure.log echo ' [--with-dfltcc-inflate] Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z' | tee -a configure.log + echo ' [--with-reduced-mem] Reduced memory usage for special cases (reduces performance)' | tee -a configure.log echo ' [--force-sse2] Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log echo ' [--with-sanitizer] Build with sanitizer (memory, address, undefined)' | tee -a configure.log echo ' [--with-fuzzers] Build test/fuzz (disabled by default)' | tee -a configure.log @@ -180,6 +182,7 @@ case "$1" in --without-neon) buildneon=0; shift ;; --with-dfltcc-deflate) builddfltccdeflate=1; shift ;; --with-dfltcc-inflate) builddfltccinflate=1; shift ;; + --with-reduced-mem) reducedmem=1; shift ;; --force-sse2) forcesse2=1; shift ;; -n | --native) native=1; shift ;; -a*=* | --archs=*) ARCHS=$(echo $1 | sed 's/.*=//'); shift ;; @@ -843,6 +846,12 @@ if test $gzfileops -eq 1; then PIC_OBJC="${PIC_OBJC} \$(PIC_OBJG)" fi +# enable reduced memory configuration +if test $reducedmem -eq 1; then + echo "Configuring for reduced memory environment." | tee -a configure.log + CFLAGS="${CFLAGS} -DHASH_SIZE=32768u -DGZBUFSIZE=8192" +fi + # if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X if test $cover -eq 1; then CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" From 564d473c6d86a001c4dd37c0cec84894d5ab47ae Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sat, 19 Jun 2021 08:58:09 +0300 Subject: [PATCH 106/798] [Power8] Add chunk*_power8. --- CMakeLists.txt | 3 +- README.md | 2 +- arch/power/Makefile.in | 8 +++++ arch/power/chunkset_power8.c | 58 ++++++++++++++++++++++++++++++++++++ configure | 8 ++--- functable.c | 33 ++++++++++++++++++++ 6 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 arch/power/chunkset_power8.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ea40b502b..98dbec9db4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -606,10 +606,11 @@ if(WITH_OPTIM) add_definitions(-DPOWER8) add_definitions(-DPOWER_FEATURES) add_definitions(-DPOWER8_VSX_ADLER32) + add_definitions(-DPOWER8_VSX_CHUNKSET) add_definitions(-DPOWER8_VSX_SLIDEHASH) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) - set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/slide_power8.c) + set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/chunkset_power8.c ${ARCHDIR}/slide_power8.c) list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") else() diff --git a/README.md b/README.md index 22b1e41647..6efbda5dc6 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Features * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon & VSX * Compare256/258 implementations using SSE4.2 & AVX2 - * Inflate chunk copying using SSE2, AVX2 & Neon + * Inflate chunk copying using SSE2, AVX2, Neon & VSX * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements * Includes improvements from Cloudflare and Intel forks diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index e7a2473a39..f58c49e81e 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -19,6 +19,8 @@ all: power.o \ power.lo \ adler32_power8.o \ adler32_power8.lo \ + chunkset_power8.o \ + chunkset_power8.lo \ slide_power8.o \ slide_power8.lo @@ -34,6 +36,12 @@ adler32_power8.o: adler32_power8.lo: $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c +chunkset_power8.o: + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_power8.c + +chunkset_power8.lo: + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_power8.c + slide_power8.o: $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_power8.c diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c new file mode 100644 index 0000000000..a76f66334c --- /dev/null +++ b/arch/power/chunkset_power8.c @@ -0,0 +1,58 @@ +/* chunkset_power8.c -- VSX inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef POWER8_VSX_CHUNKSET +#include +#include "zbuild.h" +#include "zutil.h" + +typedef vector unsigned char chunk_t; + +#define CHUNK_SIZE 16 + +#define HAVE_CHUNKMEMSET_1 +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 + +static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { + *chunk = vec_splats(*from); +} + +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + uint16_t tmp; + memcpy(&tmp, from, 2); + *chunk = (vector unsigned char)vec_splats(tmp); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + uint32_t tmp; + memcpy(&tmp, from, 4); + *chunk = (vector unsigned char)vec_splats(tmp); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + uint64_t tmp; + memcpy(&tmp, from, 8); + *chunk = (vector unsigned char)vec_splats(tmp); +} + +#define CHUNKSIZE chunksize_power8 +#define CHUNKCOPY chunkcopy_power8 +#define CHUNKCOPY_SAFE chunkcopy_safe_power8 +#define CHUNKUNROLL chunkunroll_power8 +#define CHUNKMEMSET chunkmemset_power8 +#define CHUNKMEMSET_SAFE chunkmemset_safe_power8 + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + *chunk = vec_xl(0, s); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + vec_xst(*chunk, 0, out); +} + +#include "chunkset_tpl.h" + +#endif diff --git a/configure b/configure index 911269254d..e4738dca16 100755 --- a/configure +++ b/configure @@ -1525,11 +1525,11 @@ EOF check_power8_intrinsics if test $HAVE_POWER8_INTRIN -eq 1; then - CFLAGS="${CFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_SLIDEHASH" - SFLAGS="${SFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_SLIDEHASH" + CFLAGS="${CFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_CHUNKSET -DPOWER8_VSX_SLIDEHASH" + SFLAGS="${SFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_CHUNKSET -DPOWER8_VSX_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o adler32_power8.o slide_power8.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo adler32_power8.lo slide_power8.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o adler32_power8.o chunkset_power8.o slide_power8.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo adler32_power8.lo chunkset_power8.lo slide_power8.lo" fi fi ;; diff --git a/functable.c b/functable.c index 5ed930c108..12feedfb31 100644 --- a/functable.c +++ b/functable.c @@ -96,6 +96,14 @@ extern uint8_t* chunkunroll_neon(uint8_t *out, unsigned *dist, unsigned *len); extern uint8_t* chunkmemset_neon(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif +#ifdef POWER8_VSX_CHUNKSET +extern uint32_t chunksize_power8(void); +extern uint8_t* chunkcopy_power8(uint8_t *out, uint8_t const *from, unsigned len); +extern uint8_t* chunkcopy_safe_power8(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); +extern uint8_t* chunkunroll_power8(uint8_t *out, unsigned *dist, unsigned *len); +extern uint8_t* chunkmemset_power8(uint8_t *out, unsigned dist, unsigned len); +extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif /* CRC32 */ Z_INTERNAL uint32_t crc32_generic(uint32_t, const unsigned char *, uint64_t); @@ -298,6 +306,10 @@ Z_INTERNAL uint32_t chunksize_stub(void) { if (arm_cpu_has_neon) functable.chunksize = &chunksize_neon; #endif +#ifdef POWER8_VSX_CHUNKSET + if (power_cpu_has_arch_2_07) + functable.chunksize = &chunksize_power8; +#endif return functable.chunksize(); } @@ -320,6 +332,10 @@ Z_INTERNAL uint8_t* chunkcopy_stub(uint8_t *out, uint8_t const *from, unsigned l if (arm_cpu_has_neon) functable.chunkcopy = &chunkcopy_neon; #endif +#ifdef POWER8_VSX_CHUNKSET + if (power_cpu_has_arch_2_07) + functable.chunkcopy = &chunkcopy_power8; +#endif return functable.chunkcopy(out, from, len); } @@ -342,6 +358,10 @@ Z_INTERNAL uint8_t* chunkcopy_safe_stub(uint8_t *out, uint8_t const *from, unsig if (arm_cpu_has_neon) functable.chunkcopy_safe = &chunkcopy_safe_neon; #endif +#ifdef POWER8_VSX_CHUNKSET + if (power_cpu_has_arch_2_07) + functable.chunkcopy_safe = &chunkcopy_safe_power8; +#endif return functable.chunkcopy_safe(out, from, len, safe); } @@ -364,6 +384,10 @@ Z_INTERNAL uint8_t* chunkunroll_stub(uint8_t *out, unsigned *dist, unsigned *len if (arm_cpu_has_neon) functable.chunkunroll = &chunkunroll_neon; #endif +#ifdef POWER8_VSX_CHUNKSET + if (power_cpu_has_arch_2_07) + functable.chunkunroll = &chunkunroll_power8; +#endif return functable.chunkunroll(out, dist, len); } @@ -386,6 +410,11 @@ Z_INTERNAL uint8_t* chunkmemset_stub(uint8_t *out, unsigned dist, unsigned len) if (arm_cpu_has_neon) functable.chunkmemset = &chunkmemset_neon; #endif +#ifdef POWER8_VSX_CHUNKSET + if (power_cpu_has_arch_2_07) + functable.chunkmemset = &chunkmemset_power8; +#endif + return functable.chunkmemset(out, dist, len); } @@ -408,6 +437,10 @@ Z_INTERNAL uint8_t* chunkmemset_safe_stub(uint8_t *out, unsigned dist, unsigned if (arm_cpu_has_neon) functable.chunkmemset_safe = &chunkmemset_safe_neon; #endif +#ifdef POWER8_VSX_CHUNKSET + if (power_cpu_has_arch_2_07) + functable.chunkmemset_safe = &chunkmemset_safe_power8; +#endif return functable.chunkmemset_safe(out, dist, len, left); } From 3e471800de82c610f97d57f92d0c23a13d889c22 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 25 Jun 2021 12:52:14 -0700 Subject: [PATCH 107/798] Turn off reduced memory cmake option by default. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 98dbec9db4..a194d13b5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,7 +76,7 @@ option(ZLIB_ENABLE_TESTS "Build test binaries" ON) option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) option(WITH_FUZZERS "Build test/fuzz" OFF) option(WITH_OPTIM "Build with optimisation" ON) -option(WITH_REDUCED_MEM "Reduced memory usage for special cases (reduces performance)" ON) +option(WITH_REDUCED_MEM "Reduced memory usage for special cases (reduces performance)" OFF) option(WITH_NEW_STRATEGIES "Use new strategies" ON) option(WITH_NATIVE_INSTRUCTIONS "Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)" OFF) From 6ead1d9589115338c19b99ab9109ebeaf96656e8 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 25 Jun 2021 12:53:39 -0700 Subject: [PATCH 108/798] Added reduced memory cmake CI job. --- .github/workflows/cmake.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 6b5cea4e12..cfbf002a21 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -275,6 +275,14 @@ jobs: gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_inflate_allow_invalid_dist + - name: Ubuntu Clang Reduced Memory + os: ubuntu-latest + compiler: clang-11 + cmake-args: -DWITH_REDUCED_MEM=ON + packages: llvm-11-tools + gcov-exec: llvm-cov-11 gcov + codecov: ubuntu_clang_reduced_mem + - name: Ubuntu Clang Memory Map os: ubuntu-latest compiler: clang-11 From d06be1bcd10db5faebdafc34a67252755b817db4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 25 Jun 2021 21:44:22 -0700 Subject: [PATCH 109/798] Don't define HASH_SIZE if it is already defined. --- deflate.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deflate.h b/deflate.h index 0a50afe23a..8c443d0c1d 100644 --- a/deflate.h +++ b/deflate.h @@ -65,7 +65,9 @@ /* Stream status */ #define HASH_BITS 16u /* log2(HASH_SIZE) */ -#define HASH_SIZE 65536u /* number of elements in hash table */ +#ifndef HASH_SIZE +# define HASH_SIZE 65536u /* number of elements in hash table */ +#endif #define HASH_MASK (HASH_SIZE - 1u) /* HASH_SIZE-1 */ From a575b0817cdf3aee2b351abf658a15d3f48e12a5 Mon Sep 17 00:00:00 2001 From: cenobit Date: Fri, 25 Jun 2021 19:57:00 -0700 Subject: [PATCH 110/798] Fixed missing enclosing parentheses for ZSWAP64 in zutil.h to avoid erroneous result in inffast.c. --- zutil.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zutil.h b/zutil.h index 75f0c28ca4..f8d8d07b91 100644 --- a/zutil.h +++ b/zutil.h @@ -203,14 +203,14 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr); # define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) # define ZSWAP64(q) \ - ((q & 0xFF00000000000000u) >> 56u) | \ + (((q & 0xFF00000000000000u) >> 56u) | \ ((q & 0x00FF000000000000u) >> 40u) | \ ((q & 0x0000FF0000000000u) >> 24u) | \ ((q & 0x000000FF00000000u) >> 8u) | \ ((q & 0x00000000FF000000u) << 8u) | \ ((q & 0x0000000000FF0000u) << 24u) | \ ((q & 0x000000000000FF00u) << 40u) | \ - ((q & 0x00000000000000FFu) << 56u) + ((q & 0x00000000000000FFu) << 56u)) #endif /* Only enable likely/unlikely if the compiler is known to support it */ From f5d8abb47eadb60b514f067da754f3fd374f5356 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 19 Jun 2021 17:24:00 -0700 Subject: [PATCH 111/798] Remove deflate_state dependency from crc_folding. --- arch/x86/crc_folding.c | 43 +++++++++++++++++++++--------------------- arch/x86/crc_folding.h | 8 ++++---- crc32.c | 6 +++--- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/arch/x86/crc_folding.c b/arch/x86/crc_folding.c index 4030db5988..2f38f6332e 100644 --- a/arch/x86/crc_folding.c +++ b/arch/x86/crc_folding.c @@ -18,21 +18,20 @@ #ifdef X86_PCLMULQDQ_CRC -#include "../../zbuild.h" #include #include #include #include "crc_folding.h" -Z_INTERNAL void crc_fold_init(deflate_state *const s) { +Z_INTERNAL uint32_t crc_fold_init(unsigned int crc0[4 * 5]) { /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)s->crc0 + 0, _mm_cvtsi32_si128(0x9db42487)); - _mm_storeu_si128((__m128i *)s->crc0 + 1, _mm_setzero_si128()); - _mm_storeu_si128((__m128i *)s->crc0 + 2, _mm_setzero_si128()); - _mm_storeu_si128((__m128i *)s->crc0 + 3, _mm_setzero_si128()); + _mm_storeu_si128((__m128i *)crc0 + 0, _mm_cvtsi32_si128(0x9db42487)); + _mm_storeu_si128((__m128i *)crc0 + 1, _mm_setzero_si128()); + _mm_storeu_si128((__m128i *)crc0 + 2, _mm_setzero_si128()); + _mm_storeu_si128((__m128i *)crc0 + 3, _mm_setzero_si128()); - s->strm->adler = 0; + return 0; } static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { @@ -227,16 +226,16 @@ static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, *xmm_crc3 = _mm_castps_si128(ps_res); } -Z_INTERNAL void crc_fold_copy(deflate_state *const s, unsigned char *dst, const unsigned char *src, long len) { +Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *dst, const unsigned char *src, long len) { unsigned long algn_diff; __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; char ALIGNED_(16) partial_buf[16] = { 0 }; /* CRC_LOAD */ - __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0); - __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1); - __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2); - __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3); + __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)crc0 + 0); + __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)crc0 + 1); + __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)crc0 + 2); + __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)crc0 + 3); __m128i xmm_crc_part; if (len < 16) { @@ -361,11 +360,11 @@ Z_INTERNAL void crc_fold_copy(deflate_state *const s, unsigned char *dst, const partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); done: /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)s->crc0 + 0, xmm_crc0); - _mm_storeu_si128((__m128i *)s->crc0 + 1, xmm_crc1); - _mm_storeu_si128((__m128i *)s->crc0 + 2, xmm_crc2); - _mm_storeu_si128((__m128i *)s->crc0 + 3, xmm_crc3); - _mm_storeu_si128((__m128i *)s->crc0 + 4, xmm_crc_part); + _mm_storeu_si128((__m128i *)crc0 + 0, xmm_crc0); + _mm_storeu_si128((__m128i *)crc0 + 1, xmm_crc1); + _mm_storeu_si128((__m128i *)crc0 + 2, xmm_crc2); + _mm_storeu_si128((__m128i *)crc0 + 3, xmm_crc3); + _mm_storeu_si128((__m128i *)crc0 + 4, xmm_crc_part); } static const unsigned ALIGNED_(16) crc_k[] = { @@ -385,7 +384,7 @@ static const unsigned ALIGNED_(16) crc_mask2[4] = { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; -uint32_t Z_INTERNAL crc_fold_512to32(deflate_state *const s) { +uint32_t Z_INTERNAL crc_fold_512to32(unsigned int crc0[4 * 5]) { const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); @@ -393,10 +392,10 @@ uint32_t Z_INTERNAL crc_fold_512to32(deflate_state *const s) { __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; /* CRC_LOAD */ - __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)s->crc0 + 0); - __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)s->crc0 + 1); - __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)s->crc0 + 2); - __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)s->crc0 + 3); + __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)crc0 + 0); + __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)crc0 + 1); + __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)crc0 + 2); + __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)crc0 + 3); /* * k1 diff --git a/arch/x86/crc_folding.h b/arch/x86/crc_folding.h index 0d3c24b29f..a9ed41f3c0 100644 --- a/arch/x86/crc_folding.h +++ b/arch/x86/crc_folding.h @@ -10,10 +10,10 @@ #ifndef CRC_FOLDING_H_ #define CRC_FOLDING_H_ -#include "../../deflate.h" +#include "../../zutil.h" -Z_INTERNAL void crc_fold_init(deflate_state *const); -Z_INTERNAL uint32_t crc_fold_512to32(deflate_state *const); -Z_INTERNAL void crc_fold_copy(deflate_state *const, unsigned char *, const unsigned char *, long); +Z_INTERNAL uint32_t crc_fold_init(unsigned int crc0[4 * 5]); +Z_INTERNAL uint32_t crc_fold_512to32(unsigned int crc0[4 * 5]); +Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *, const unsigned char *, long); #endif diff --git a/crc32.c b/crc32.c index 4b488e617e..74d9c414c2 100644 --- a/crc32.c +++ b/crc32.c @@ -175,7 +175,7 @@ Z_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_t l Z_INTERNAL void crc_finalize(deflate_state *const s) { if (x86_cpu_has_pclmulqdq) - s->strm->adler = crc_fold_512to32(s); + s->strm->adler = crc_fold_512to32(s->crc0); } #endif @@ -183,7 +183,7 @@ Z_INTERNAL void crc_reset(deflate_state *const s) { #ifdef X86_PCLMULQDQ_CRC x86_check_features(); if (x86_cpu_has_pclmulqdq) { - crc_fold_init(s); + s->strm->adler = crc_fold_init(s->crc0); return; } #endif @@ -193,7 +193,7 @@ Z_INTERNAL void crc_reset(deflate_state *const s) { Z_INTERNAL void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size) { #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) { - crc_fold_copy(strm->state, dst, strm->next_in, size); + crc_fold_copy(strm->state->crc0, dst, strm->next_in, size); return; } #endif From b937afdc758381a152390342e281ac1e51033ebd Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 10 Jun 2021 18:03:08 -0700 Subject: [PATCH 112/798] Remove extra division operation in chunkcopy. --- chunkset_tpl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index ff760fcf69..1018aac3a3 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -20,18 +20,18 @@ Z_INTERNAL uint32_t CHUNKSIZE(void) { Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { Assert(len > 0, "chunkcopy should never have a length 0"); chunk_t chunk; - int32_t align = (--len % sizeof(chunk_t)) + 1; + int32_t align = ((len - 1) % sizeof(chunk_t)) + 1; loadchunk(from, &chunk); storechunk(out, &chunk); out += align; from += align; - len /= sizeof(chunk_t); + len -= align; while (len > 0) { loadchunk(from, &chunk); storechunk(out, &chunk); out += sizeof(chunk_t); from += sizeof(chunk_t); - --len; + len -= sizeof(chunk_t); } return out; } From 0573840dd07fdd85f249af267fcfc3a6dafaed35 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 6 Apr 2021 13:51:16 +0200 Subject: [PATCH 113/798] IBM Z: Add vectorized CRC32 implementation While DFLTCC takes care of accelerating compression on level 1, other levels can be sped up too by computing CRC32 using various vector instructions. Take the Linux kernel assembly code that does that - its original author (Hendrik Brueckner) works for IBM at the time of writing and has allowed reusing the code under the zlib license. Rewrite it in C for better maintainability, but keep the original structure, variable names and comments. Update the documentation. Add CI configurations. --- .github/workflows/cmake.yml | 10 ++ .github/workflows/configure.yml | 10 ++ CMakeLists.txt | 18 +++ README.md | 2 + arch/s390/Makefile.in | 14 ++ arch/s390/crc32-vx.c | 222 ++++++++++++++++++++++++++++++++ arch/s390/s390.c | 10 ++ arch/s390/s390.h | 10 ++ cmake/detect-intrinsics.cmake | 25 ++++ configure | 59 +++++++++ crc32_p.h | 9 ++ functable.c | 14 +- zutil.h | 2 + 13 files changed, 400 insertions(+), 5 deletions(-) create mode 100644 arch/s390/crc32-vx.c create mode 100644 arch/s390/s390.c create mode 100644 arch/s390/s390.h diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index cfbf002a21..a172451bbf 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -209,6 +209,16 @@ jobs: ldflags: -static codecov: ubuntu_gcc_s390x + - name: Ubuntu GCC S390X No vectorized CRC32 + os: ubuntu-latest + compiler: s390x-linux-gnu-gcc + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_CRC32_VX=OFF -DWITH_SANITIZER=Address + asan-options: detect_leaks=0 + packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross + qemu-run: qemu-s390x + ldflags: -static + codecov: ubuntu_gcc_s390x + - name: Ubuntu GCC S390X DFLTCC os: ubuntu-latest compiler: s390x-linux-gnu-gcc diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index c3bc867896..9d9dc35985 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -148,6 +148,16 @@ jobs: cflags: -static ldflags: -static + - name: Ubuntu GCC S390X No vectorized CRC32 + os: ubuntu-latest + compiler: s390x-linux-gnu-gcc + configure-args: --warn --static --without-crc32-vx + chost: s390x-linux-gnu + packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross + qemu-run: qemu-s390x + cflags: -static + ldflags: -static + - name: Ubuntu GCC S390X DFLTCC os: ubuntu-latest compiler: s390x-linux-gnu-gcc diff --git a/CMakeLists.txt b/CMakeLists.txt index a194d13b5a..1530e4f911 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,7 @@ elseif(BASEARCH_PPC_FOUND) elseif(BASEARCH_S360_FOUND) option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF) option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF) + option(WITH_CRC32_VX "Build with vectorized CRC32 on IBM Z" ON) elseif(BASEARCH_X86_FOUND) option(WITH_AVX2 "Build with AVX2" ON) option(WITH_SSE2 "Build with SSE2" ON) @@ -114,6 +115,7 @@ mark_as_advanced(FORCE WITH_ACLE WITH_NEON WITH_DFLTCC_DEFLATE WITH_DFLTCC_INFLATE + WITH_CRC32_VX WITH_AVX2 WITH_SSE2 WITH_SSSE3 WITH_SSE4 WITH_PCLMULQDQ @@ -618,6 +620,10 @@ if(WITH_OPTIM) endif() endif() elseif(BASEARCH_S360_FOUND) + if(WITH_CRC32_VX) + add_definitions(-DS390_FEATURES) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/s390.c) + endif() if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/dfltcc_common.c) endif() @@ -629,6 +635,17 @@ if(WITH_OPTIM) add_definitions(-DS390_DFLTCC_INFLATE) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/dfltcc_inflate.c) endif() + if(WITH_CRC32_VX) + check_vgfma_intrinsics() + if(HAVE_VGFMA_INTRIN) + add_definitions(-DS390_CRC32_VX) + set(CRC32_VX_SRCS ${ARCHDIR}/crc32-vx.c) + list(APPEND ZLIB_ARCH_SRCS ${CRC32_VX_SRCS}) + set_property(SOURCE ${CRC32_VX_SRCS} PROPERTY COMPILE_FLAGS "${VGFMAFLAG} ${NOLTOFLAG}") + else() + set(WITH_CRC32_VX OFF) + endif() + endif() elseif(BASEARCH_X86_FOUND) add_definitions(-DX86_FEATURES) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/x86.h) @@ -1295,6 +1312,7 @@ elseif(BASEARCH_PPC_FOUND) elseif(BASEARCH_S360_FOUND) add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z") add_feature_info(WITH_DFLTCC_INFLATE WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z") + add_feature_info(WITH_CRC32_VX WITH_CRC32_VX "Build with vectorized CRC32 on IBM Z") elseif(BASEARCH_X86_FOUND) add_feature_info(WITH_AVX2 WITH_AVX2 "Build with AVX2") add_feature_info(WITH_SSE2 WITH_SSE2 "Build with SSE2") diff --git a/README.md b/README.md index 6efbda5dc6..161a1b6333 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Features * Slide hash implementations using SSE2, AVX2, Neon & VSX * Compare256/258 implementations using SSE4.2 & AVX2 * Inflate chunk copying using SSE2, AVX2, Neon & VSX + * CRC32 implementation using IBM Z vector instructions * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements * Includes improvements from Cloudflare and Intel forks @@ -202,6 +203,7 @@ Advanced Build Options | WITH_ACLE | --without-acle | Build with ACLE intrinsics | ON | | WITH_NEON | --without-neon | Build with NEON intrinsics | ON | | WITH_POWER8 | | Build with POWER8 optimisations | ON | +| WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON | | WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF | | WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF | | WITH_UNALIGNED | | Allow optimizations that use unaligned reads if safe on current arch| ON | diff --git a/arch/s390/Makefile.in b/arch/s390/Makefile.in index 2652fe62d9..9780f24cff 100644 --- a/arch/s390/Makefile.in +++ b/arch/s390/Makefile.in @@ -7,11 +7,19 @@ CFLAGS= SFLAGS= INCLUDES= SUFFIX= +VGFMAFLAG= +NOLTOFLAG= SRCDIR=. SRCTOP=../.. TOPDIR=$(SRCTOP) +s390.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/s390.c + +s390.lo: + $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/s390.c + dfltcc_common.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_common.c @@ -30,6 +38,12 @@ dfltcc_inflate.o: dfltcc_inflate.lo: $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_inflate.c +crc32-vx.o: + $(CC) $(CFLAGS) $(VGFMAFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32-vx.c + +crc32-vx.lo: + $(CC) $(SFLAGS) $(VGFMAFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32-vx.c + mostlyclean: clean clean: rm -f *.o *.lo *~ diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c new file mode 100644 index 0000000000..bb23289cd1 --- /dev/null +++ b/arch/s390/crc32-vx.c @@ -0,0 +1,222 @@ +/* + * Hardware-accelerated CRC-32 variants for Linux on z Systems + * + * Use the z/Architecture Vector Extension Facility to accelerate the + * computing of bitreflected CRC-32 checksums. + * + * This CRC-32 implementation algorithm is bitreflected and processes + * the least-significant bit first (Little-Endian). + * + * This code was originally written by Hendrik Brueckner + * for use in the Linux kernel and has been + * relicensed under the zlib license. + */ + +#include "../../zutil.h" +#include "../../crc32_p.h" + +#include + +typedef unsigned char uv16qi __attribute__((vector_size(16))); +typedef unsigned int uv4si __attribute__((vector_size(16))); +typedef unsigned long long uv2di __attribute__((vector_size(16))); + +static uint32_t crc32_le_vgfm_16(uint32_t crc, const unsigned char *buf, size_t len) { + /* + * The CRC-32 constant block contains reduction constants to fold and + * process particular chunks of the input data stream in parallel. + * + * For the CRC-32 variants, the constants are precomputed according to + * these definitions: + * + * R1 = [(x4*128+32 mod P'(x) << 32)]' << 1 + * R2 = [(x4*128-32 mod P'(x) << 32)]' << 1 + * R3 = [(x128+32 mod P'(x) << 32)]' << 1 + * R4 = [(x128-32 mod P'(x) << 32)]' << 1 + * R5 = [(x64 mod P'(x) << 32)]' << 1 + * R6 = [(x32 mod P'(x) << 32)]' << 1 + * + * The bitreflected Barret reduction constant, u', is defined as + * the bit reversal of floor(x**64 / P(x)). + * + * where P(x) is the polynomial in the normal domain and the P'(x) is the + * polynomial in the reversed (bitreflected) domain. + * + * CRC-32 (IEEE 802.3 Ethernet, ...) polynomials: + * + * P(x) = 0x04C11DB7 + * P'(x) = 0xEDB88320 + */ + const uv16qi perm_le2be = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; /* BE->LE mask */ + const uv2di r2r1 = {0x1C6E41596, 0x154442BD4}; /* R2, R1 */ + const uv2di r4r3 = {0x0CCAA009E, 0x1751997D0}; /* R4, R3 */ + const uv2di r5 = {0, 0x163CD6124}; /* R5 */ + const uv2di ru_poly = {0, 0x1F7011641}; /* u' */ + const uv2di crc_poly = {0, 0x1DB710641}; /* P'(x) << 1 */ + + /* + * Load the initial CRC value. + * + * The CRC value is loaded into the rightmost word of the + * vector register and is later XORed with the LSB portion + * of the loaded input data. + */ + uv2di v0 = {0, 0}; + v0 = (uv2di)vec_insert(crc, (uv4si)v0, 3); + + /* Load a 64-byte data chunk and XOR with CRC */ + uv2di v1 = vec_perm(((uv2di *)buf)[0], ((uv2di *)buf)[0], perm_le2be); + uv2di v2 = vec_perm(((uv2di *)buf)[1], ((uv2di *)buf)[1], perm_le2be); + uv2di v3 = vec_perm(((uv2di *)buf)[2], ((uv2di *)buf)[2], perm_le2be); + uv2di v4 = vec_perm(((uv2di *)buf)[3], ((uv2di *)buf)[3], perm_le2be); + + v1 ^= v0; + buf += 64; + len -= 64; + + while (len >= 64) { + /* Load the next 64-byte data chunk */ + uv16qi part1 = vec_perm(((uv16qi *)buf)[0], ((uv16qi *)buf)[0], perm_le2be); + uv16qi part2 = vec_perm(((uv16qi *)buf)[1], ((uv16qi *)buf)[1], perm_le2be); + uv16qi part3 = vec_perm(((uv16qi *)buf)[2], ((uv16qi *)buf)[2], perm_le2be); + uv16qi part4 = vec_perm(((uv16qi *)buf)[3], ((uv16qi *)buf)[3], perm_le2be); + + /* + * Perform a GF(2) multiplication of the doublewords in V1 with + * the R1 and R2 reduction constants in V0. The intermediate result + * is then folded (accumulated) with the next data chunk in PART1 and + * stored in V1. Repeat this step for the register contents + * in V2, V3, and V4 respectively. + */ + v1 = (uv2di)vec_gfmsum_accum_128(r2r1, v1, part1); + v2 = (uv2di)vec_gfmsum_accum_128(r2r1, v2, part2); + v3 = (uv2di)vec_gfmsum_accum_128(r2r1, v3, part3); + v4 = (uv2di)vec_gfmsum_accum_128(r2r1, v4, part4); + + buf += 64; + len -= 64; + } + + /* + * Fold V1 to V4 into a single 128-bit value in V1. Multiply V1 with R3 + * and R4 and accumulating the next 128-bit chunk until a single 128-bit + * value remains. + */ + v1 = (uv2di)vec_gfmsum_accum_128(r4r3, v1, (uv16qi)v2); + v1 = (uv2di)vec_gfmsum_accum_128(r4r3, v1, (uv16qi)v3); + v1 = (uv2di)vec_gfmsum_accum_128(r4r3, v1, (uv16qi)v4); + + while (len >= 16) { + /* Load next data chunk */ + v2 = vec_perm(*(uv2di *)buf, *(uv2di *)buf, perm_le2be); + + /* Fold next data chunk */ + v1 = (uv2di)vec_gfmsum_accum_128(r4r3, v1, (uv16qi)v2); + + buf += 16; + len -= 16; + } + + /* + * Set up a vector register for byte shifts. The shift value must + * be loaded in bits 1-4 in byte element 7 of a vector register. + * Shift by 8 bytes: 0x40 + * Shift by 4 bytes: 0x20 + */ + uv16qi v9 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + v9 = vec_insert((unsigned char)0x40, v9, 7); + + /* + * Prepare V0 for the next GF(2) multiplication: shift V0 by 8 bytes + * to move R4 into the rightmost doubleword and set the leftmost + * doubleword to 0x1. + */ + v0 = vec_srb(r4r3, (uv2di)v9); + v0[0] = 1; + + /* + * Compute GF(2) product of V1 and V0. The rightmost doubleword + * of V1 is multiplied with R4. The leftmost doubleword of V1 is + * multiplied by 0x1 and is then XORed with rightmost product. + * Implicitly, the intermediate leftmost product becomes padded + */ + v1 = (uv2di)vec_gfmsum_128(v0, v1); + + /* + * Now do the final 32-bit fold by multiplying the rightmost word + * in V1 with R5 and XOR the result with the remaining bits in V1. + * + * To achieve this by a single VGFMAG, right shift V1 by a word + * and store the result in V2 which is then accumulated. Use the + * vector unpack instruction to load the rightmost half of the + * doubleword into the rightmost doubleword element of V1; the other + * half is loaded in the leftmost doubleword. + * The vector register with CONST_R5 contains the R5 constant in the + * rightmost doubleword and the leftmost doubleword is zero to ignore + * the leftmost product of V1. + */ + v9 = vec_insert((unsigned char)0x20, v9, 7); + v2 = vec_srb(v1, (uv2di)v9); + v1 = vec_unpackl((uv4si)v1); /* Split rightmost doubleword */ + v1 = (uv2di)vec_gfmsum_accum_128(r5, v1, (uv16qi)v2); + + /* + * Apply a Barret reduction to compute the final 32-bit CRC value. + * + * The input values to the Barret reduction are the degree-63 polynomial + * in V1 (R(x)), degree-32 generator polynomial, and the reduction + * constant u. The Barret reduction result is the CRC value of R(x) mod + * P(x). + * + * The Barret reduction algorithm is defined as: + * + * 1. T1(x) = floor( R(x) / x^32 ) GF2MUL u + * 2. T2(x) = floor( T1(x) / x^32 ) GF2MUL P(x) + * 3. C(x) = R(x) XOR T2(x) mod x^32 + * + * Note: The leftmost doubleword of vector register containing + * CONST_RU_POLY is zero and, thus, the intermediate GF(2) product + * is zero and does not contribute to the final result. + */ + + /* T1(x) = floor( R(x) / x^32 ) GF2MUL u */ + v2 = vec_unpackl((uv4si)v1); + v2 = (uv2di)vec_gfmsum_128(ru_poly, v2); + + /* + * Compute the GF(2) product of the CRC polynomial with T1(x) in + * V2 and XOR the intermediate result, T2(x), with the value in V1. + * The final result is stored in word element 2 of V2. + */ + v2 = vec_unpackl((uv4si)v2); + v2 = (uv2di)vec_gfmsum_accum_128(crc_poly, v2, (uv16qi)v1); + + return ((uv4si)v2)[2]; +} + +#define VX_MIN_LEN 64 +#define VX_ALIGNMENT 16L +#define VX_ALIGN_MASK (VX_ALIGNMENT - 1) + +uint32_t Z_INTERNAL s390_crc32_vx(uint32_t crc, const unsigned char *buf, uint64_t len) { + uint64_t prealign, aligned, remaining; + + if (len < VX_MIN_LEN + VX_ALIGN_MASK) + return crc32_big(crc, buf, len); + + if ((uintptr_t)buf & VX_ALIGN_MASK) { + prealign = VX_ALIGNMENT - ((uintptr_t)buf & VX_ALIGN_MASK); + len -= prealign; + crc = crc32_big(crc, buf, prealign); + buf += prealign; + } + aligned = len & ~VX_ALIGN_MASK; + remaining = len & VX_ALIGN_MASK; + + crc = crc32_le_vgfm_16(crc ^ 0xffffffff, buf, (size_t)aligned) ^ 0xffffffff; + + if (remaining) + crc = crc32_big(crc, buf + aligned, remaining); + + return crc; +} diff --git a/arch/s390/s390.c b/arch/s390/s390.c new file mode 100644 index 0000000000..6dd5252ce3 --- /dev/null +++ b/arch/s390/s390.c @@ -0,0 +1,10 @@ +#include "../../zutil.h" +#include "s390.h" + +#include + +Z_INTERNAL int s390_cpu_has_vx; + +void Z_INTERNAL s390_check_features(void) { + s390_cpu_has_vx = getauxval(AT_HWCAP) & HWCAP_S390_VX; +} diff --git a/arch/s390/s390.h b/arch/s390/s390.h new file mode 100644 index 0000000000..dec035b3d9 --- /dev/null +++ b/arch/s390/s390.h @@ -0,0 +1,10 @@ +#ifndef S390_H_ +#define S390_H_ + +#include "../../zutil.h" + +extern int s390_cpu_has_vx; + +void Z_INTERNAL s390_check_features(void); + +#endif diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index a360b7e664..90c5f3bee1 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -219,3 +219,28 @@ macro(check_sse4_intrinsics) ) set(CMAKE_REQUIRED_FLAGS) endmacro() + +macro(check_vgfma_intrinsics) + if(NOT NATIVEFLAG) + set(VGFMAFLAG "-march=z13") + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + set(VGFMAFLAG "${VGFMAFLAG} -mzarch") + endif() + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + set(VGFMAFLAG "${VGFMAFLAG} -fzvector") + endif() + endif() + # Check whether compiler supports "VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE" intrinsic + set(CMAKE_REQUIRED_FLAGS "${VGFMAFLAG}") + check_c_source_compiles( + "#include + int main(void) { + unsigned long long a __attribute__((vector_size(16))) = { 0 }; + unsigned long long b __attribute__((vector_size(16))) = { 0 }; + unsigned char c __attribute__((vector_size(16))) = { 0 }; + c = vec_gfmsum_accum_128(a, b, c); + return c[0]; + }" + HAVE_VGFMA_INTRIN FAIL_REGEX "not supported") + set(CMAKE_REQUIRED_FLAGS) +endmacro() diff --git a/configure b/configure index e4738dca16..0dc1dd6a76 100755 --- a/configure +++ b/configure @@ -94,6 +94,7 @@ buildacle=1 buildneon=1 builddfltccdeflate=0 builddfltccinflate=0 +buildcrc32vx=1 with_sanitizer="" with_fuzzers=0 floatabi= @@ -108,6 +109,7 @@ pclmulflag="-mpclmul" acleflag= neonflag= noltoflag="-fno-lto" +vgfmaflag="-march=z13" without_optimizations=0 without_new_strategies=0 reducedmem=0 @@ -155,6 +157,7 @@ case "$1" in echo ' [--without-neon] Compiles without ARM Neon SIMD instruction set' | tee -a configure.log echo ' [--with-dfltcc-deflate] Use DEFLATE CONVERSION CALL instruction for compression on IBM Z' | tee -a configure.log echo ' [--with-dfltcc-inflate] Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z' | tee -a configure.log + echo ' [--without-crc32-vx] Build without vectorized CRC32 on IBM Z' | tee -a configure.log echo ' [--with-reduced-mem] Reduced memory usage for special cases (reduces performance)' | tee -a configure.log echo ' [--force-sse2] Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log echo ' [--with-sanitizer] Build with sanitizer (memory, address, undefined)' | tee -a configure.log @@ -182,6 +185,7 @@ case "$1" in --without-neon) buildneon=0; shift ;; --with-dfltcc-deflate) builddfltccdeflate=1; shift ;; --with-dfltcc-inflate) builddfltccinflate=1; shift ;; + --without-crc32-vx) buildcrc32vx=0; shift ;; --with-reduced-mem) reducedmem=1; shift ;; --force-sse2) forcesse2=1; shift ;; -n | --native) native=1; shift ;; @@ -1152,6 +1156,42 @@ EOF fi } +check_vgfma_intrinsics() { + # Check whether "VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE" intrinsic is available + echo -n "Checking for -mzarch... " | tee -a configure.log + if try $CC -x c -c /dev/null -o /dev/null -mzarch; then + echo Yes. | tee -a configure.log + vgfmaflag="${vgfmaflag} -mzarch" + else + echo No. | tee -a configure.log + fi + echo -n "Checking for -fzvector... " | tee -a configure.log + if try $CC -x c -c /dev/null -o /dev/null -fzvector; then + echo Yes. | tee -a configure.log + vgfmaflag="${vgfmaflag} -fzvector" + else + echo No. | tee -a configure.log + fi + cat > $test.c << EOF +#include +int main(void) { + unsigned long long a __attribute__((vector_size(16))) = { 0 }; + unsigned long long b __attribute__((vector_size(16))) = { 0 }; + unsigned char c __attribute__((vector_size(16))) = { 0 }; + c = vec_gfmsum_accum_128(a, b, c); + return c[0]; +} +EOF + echo -n "Checking for VGFMA support... " | tee -a configure.log + if try $CC -c $CFLAGS $vgfmaflag $test.c; then + HAVE_VGFMA_INTRIN=1 + echo "Yes." | tee -a configure.log + else + HAVE_VGFMA_INTRIN=0 + echo "No." | tee -a configure.log + fi +} + case "${ARCH}" in i386 | i486 | i586 | i686 | x86_64) # Enable deflate_medium at level 1 @@ -1538,6 +1578,13 @@ EOF ARCHDIR=arch/s390 if test $without_optimizations -eq 0; then + if test $buildcrc32vx -eq 1; then + CFLAGS="${CFLAGS} -DS390_FEATURES" + SFLAGS="${SFLAGS} -DS390_FEATURES" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} s390.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} s390.lo" + fi + if test $builddfltccdeflate -eq 1 -o $builddfltccinflate -eq 1; then ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} dfltcc_common.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} dfltcc_common.lo" @@ -1558,6 +1605,17 @@ EOF ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} dfltcc_inflate.lo" ARCH="${ARCH}+dfltcc-inflate" fi + + if test $buildcrc32vx -eq 1; then + check_vgfma_intrinsics + if test $HAVE_VGFMA_INTRIN -eq 1; then + CFLAGS="${CFLAGS} -DS390_CRC32_VX" + SFLAGS="${SFLAGS} -DS390_CRC32_VX" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32-vx.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32-vx.lo" + ARCH="${ARCH}+crc32-vx" + fi + fi fi ;; *) @@ -1751,6 +1809,7 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^ACLEFLAG *=/s#=.*#=$acleflag# /^NEONFLAG *=/s#=.*#=$neonflag# /^NOLTOFLAG *=/s#=.*#=$noltoflag# +/^VGFMAFLAG *=/s#=.*#=$vgfmaflag# " > $ARCHDIR/Makefile # Append header files dependences. diff --git a/crc32_p.h b/crc32_p.h index 47b4b3751b..fbaf8db88c 100644 --- a/crc32_p.h +++ b/crc32_p.h @@ -1,6 +1,9 @@ #ifndef CRC32_P_H_ #define CRC32_P_H_ +#include "zutil.h" +#include "zendian.h" + #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ @@ -16,4 +19,10 @@ static inline uint32_t gf2_matrix_times(const uint32_t *mat, uint32_t vec) { } +#if BYTE_ORDER == LITTLE_ENDIAN +extern uint32_t crc32_little(uint32_t, const unsigned char *, uint64_t); +#elif BYTE_ORDER == BIG_ENDIAN +extern uint32_t crc32_big(uint32_t, const unsigned char *, uint64_t); +#endif + #endif /* CRC32_P_H_ */ diff --git a/functable.c b/functable.c index 12feedfb31..af3aaa2d8b 100644 --- a/functable.c +++ b/functable.c @@ -5,6 +5,7 @@ #include "zbuild.h" #include "zendian.h" +#include "crc32_p.h" #include "deflate.h" #include "deflate_p.h" @@ -111,11 +112,8 @@ Z_INTERNAL uint32_t crc32_generic(uint32_t, const unsigned char *, uint64_t); #ifdef ARM_ACLE_CRC_HASH extern uint32_t crc32_acle(uint32_t, const unsigned char *, uint64_t); #endif - -#if BYTE_ORDER == LITTLE_ENDIAN -extern uint32_t crc32_little(uint32_t, const unsigned char *, uint64_t); -#elif BYTE_ORDER == BIG_ENDIAN -extern uint32_t crc32_big(uint32_t, const unsigned char *, uint64_t); +#ifdef S390_CRC32_VX +extern uint32_t s390_crc32_vx(uint32_t, const unsigned char *, uint64_t); #endif /* compare258 */ @@ -179,6 +177,8 @@ Z_INTERNAL void cpu_check_features(void) arm_check_features(); #elif defined(POWER_FEATURES) power_check_features(); +#elif defined(S390_FEATURES) + s390_check_features(); #endif features_checked = 1; } @@ -463,6 +463,10 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t # endif #elif BYTE_ORDER == BIG_ENDIAN functable.crc32 = crc32_big; +# if defined(S390_CRC32_VX) + if (s390_cpu_has_vx) + functable.crc32 = s390_crc32_vx; +# endif #else # error No endian defined #endif diff --git a/zutil.h b/zutil.h index f8d8d07b91..4e89509555 100644 --- a/zutil.h +++ b/zutil.h @@ -252,6 +252,8 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr); # include "arch/arm/arm.h" #elif defined(POWER_FEATURES) # include "arch/power/power.h" +#elif defined(S390_FEATURES) +# include "arch/s390/s390.h" #endif #endif /* ZUTIL_H_ */ From 3aa7b0bb5fb158139618c11d9ba6e54d97b12161 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 25 Jun 2021 17:23:56 -0700 Subject: [PATCH 114/798] Use STDC11 defined earlier in zbuild.h for Z_TLS check. --- zbuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zbuild.h b/zbuild.h index e47acf5368..dc90e11038 100644 --- a/zbuild.h +++ b/zbuild.h @@ -17,7 +17,7 @@ /* Determine compiler support for TLS */ #ifndef Z_TLS -# if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__ +# if defined(STDC11) && !defined(__STDC_NO_THREADS__) # define Z_TLS _Thread_local # elif defined(__GNUC__) || defined(__SUNPRO_C) # define Z_TLS __thread From 88d077a40a737cc771f90db1e718c9e2dc341e88 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 25 Jun 2021 17:23:34 -0700 Subject: [PATCH 115/798] Added build system check for posix_memalign support. Co-authored-by: concatime Co-authored-by: Mika Lindqvist --- CMakeLists.txt | 6 ++++++ configure | 19 +++++++++++++++++++ zutil.c | 2 +- zutil_p.h | 8 ++++++-- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1530e4f911..51b4555d00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -323,6 +323,12 @@ check_function_exists(strerror HAVE_STRERROR) if(NOT HAVE_STRERROR) add_definitions(-DNO_STRERROR) endif() +set(CMAKE_REQUIRED_DEFINITIONS -D _POSIX_C_SOURCE=200112L) +check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN) +if(HAVE_POSIX_MEMALIGN) + add_definitions(-DHAVE_POSIX_MEMALIGN) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) if(WITH_SANITIZER STREQUAL "Address") add_address_sanitizer() diff --git a/configure b/configure index 0dc1dd6a76..3c278cfcdd 100755 --- a/configure +++ b/configure @@ -747,7 +747,26 @@ EOF echo "Checking for fseeko... No." | tee -a configure.log fi fi +echo >> configure.log +cat > $test.c < +int main(void) { + void *ptr = 0; + int ret = posix_memalign(&ptr, 64, 10); + if (ptr) + free(ptr); + return ret; +} +EOF +if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then + echo "Checking for posix_memalign... Yes." | tee -a configure.log + CFLAGS="${CFLAGS} -DHAVE_POSIX_MEMALIGN" + SFLAGS="${SFLAGS} -DHAVE_POSIX_MEMALIGN" +else + echo "Checking for posix_memalign... No." | tee -a configure.log +fi echo >> configure.log # check for strerror() for use by gz* functions diff --git a/zutil.c b/zutil.c index 53e43b0dea..18db2fe00f 100644 --- a/zutil.c +++ b/zutil.c @@ -4,8 +4,8 @@ */ #include "zbuild.h" -#include "zutil.h" #include "zutil_p.h" +#include "zutil.h" z_const char * const PREFIX(z_errmsg)[10] = { (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ diff --git a/zutil_p.h b/zutil_p.h index c8122607ea..55f00611b3 100644 --- a/zutil_p.h +++ b/zutil_p.h @@ -5,7 +5,11 @@ #ifndef ZUTIL_P_H #define ZUTIL_P_H -#if defined(__APPLE__) || defined(__OpenBSD__) +#if defined(HAVE_POSIX_MEMALIGN) && !defined(_POSIX_C_SOURCE) +# define _POSIX_C_SOURCE 200112L /* For posix_memalign(). */ +#endif + +#if defined(__APPLE__) || defined(HAVE_POSIX_MEMALIGN) # include #elif defined(__FreeBSD__) # include @@ -16,7 +20,7 @@ /* Function to allocate 16 or 64-byte aligned memory */ static inline void *zng_alloc(size_t size) { -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#ifdef HAVE_POSIX_MEMALIGN void *ptr; return posix_memalign(&ptr, 64, size) ? NULL : ptr; #elif defined(_WIN32) From e52d08ea92ec33ca140cbdcd0c8e9cb639e80cfe Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Jun 2021 19:55:09 -0700 Subject: [PATCH 116/798] Separate slide_hash_c in the same way that insert_string_c is separated from deflate.c. --- CMakeLists.txt | 1 + Makefile.in | 2 ++ deflate.c | 44 --------------------------------------- slide_hash.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ win32/Makefile.a64 | 2 ++ win32/Makefile.arm | 2 ++ win32/Makefile.msc | 2 ++ 7 files changed, 61 insertions(+), 44 deletions(-) create mode 100644 slide_hash.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 51b4555d00..4deef8235a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -855,6 +855,7 @@ set(ZLIB_SRCS inftrees.c insert_string.c insert_string_roll.c + slide_hash.c trees.c uncompr.c zutil.c diff --git a/Makefile.in b/Makefile.in index 379cab5292..de37b19067 100644 --- a/Makefile.in +++ b/Makefile.in @@ -93,6 +93,7 @@ OBJZ = \ inftrees.o \ insert_string.o \ insert_string_roll.o \ + slide_hash.o \ trees.o \ uncompr.o \ zutil.o \ @@ -127,6 +128,7 @@ PIC_OBJZ = \ inftrees.lo \ insert_string.lo \ insert_string_roll.lo \ + slide_hash.lo \ trees.lo \ uncompr.lo \ zutil.lo \ diff --git a/deflate.c b/deflate.c index c66c1e17a5..c1ee6d4104 100644 --- a/deflate.c +++ b/deflate.c @@ -185,50 +185,6 @@ static const config configuration_table[10] = { memset((unsigned char *)s->head, 0, HASH_SIZE * sizeof(*s->head)); \ } while (0) -/* =========================================================================== - * 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); - } - /* ========================================================================= */ int32_t Z_EXPORT PREFIX(deflateInit_)(PREFIX3(stream) *strm, int32_t level, const char *version, int32_t stream_size) { return PREFIX(deflateInit2_)(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, version, stream_size); diff --git a/slide_hash.c b/slide_hash.c new file mode 100644 index 0000000000..d25e710a85 --- /dev/null +++ b/slide_hash.c @@ -0,0 +1,52 @@ +/* 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); +} diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index a272810a87..8a39249dd8 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -64,6 +64,7 @@ OBJS = \ inffast.obj \ insert_string.obj \ insert_string_roll.obj \ + slide_hash.obj \ trees.obj \ uncompr.obj \ zutil.obj \ @@ -179,6 +180,7 @@ infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/ inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h +slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 23ed761a4a..9897ad8e90 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -67,6 +67,7 @@ OBJS = \ inffast.obj \ insert_string.obj \ insert_string_roll.obj \ + slide_hash.obj \ trees.obj \ uncompr.obj \ zutil.obj \ @@ -191,6 +192,7 @@ infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/ inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h +slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 94462f5968..0ff683e2f7 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -75,6 +75,7 @@ OBJS = \ insert_string.obj \ insert_string_roll.obj \ insert_string_sse.obj \ + slide_hash.obj \ slide_avx.obj \ slide_sse.obj \ trees.obj \ @@ -185,6 +186,7 @@ infback.obj: $(SRCDIR)/infback.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/ inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h +slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h slide_sse.obj: $(SRCDIR)/arch/x86/slide_sse.c $(SRCDIR)/deflate.h trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h From 12a975ac9f19b3d2e362d0d783ea20400335d1c6 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Jun 2021 20:07:41 -0700 Subject: [PATCH 117/798] Rename slide source files to slide_hash to match function name. --- CMakeLists.txt | 8 +++--- arch/arm/Makefile.in | 10 +++---- arch/arm/{slide_neon.c => slide_hash_neon.c} | 2 +- arch/power/Makefile.in | 12 ++++---- .../{slide_power8.c => slide_hash_power8.c} | 0 arch/x86/INDEX.md | 2 +- arch/x86/Makefile.in | 20 ++++++------- arch/x86/{slide_avx.c => slide_hash_avx.c} | 0 arch/x86/{slide_sse.c => slide_hash_sse.c} | 0 configure | 28 +++++++++---------- win32/Makefile.a64 | 3 +- win32/Makefile.arm | 2 +- win32/Makefile.msc | 7 +++-- 13 files changed, 48 insertions(+), 46 deletions(-) rename arch/arm/{slide_neon.c => slide_hash_neon.c} (93%) rename arch/power/{slide_power8.c => slide_hash_power8.c} (100%) rename arch/x86/{slide_avx.c => slide_hash_avx.c} (100%) rename arch/x86/{slide_sse.c => slide_hash_sse.c} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4deef8235a..614d7e5934 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -595,7 +595,7 @@ if(WITH_OPTIM) check_neon_intrinsics() if(MFPU_NEON_AVAILABLE) add_definitions(-DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) - set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_neon.c) + set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_hash_neon.c) list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) set_property(SOURCE ${NEON_SRCS} PROPERTY COMPILE_FLAGS "${NEONFLAG} ${NOLTOFLAG}") if(MSVC) @@ -618,7 +618,7 @@ if(WITH_OPTIM) add_definitions(-DPOWER8_VSX_SLIDEHASH) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) - set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/chunkset_power8.c ${ARCHDIR}/slide_power8.c) + set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/chunkset_power8.c ${ARCHDIR}/slide_hash_power8.c) list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") else() @@ -663,7 +663,7 @@ if(WITH_OPTIM) check_avx2_intrinsics() if(HAVE_AVX2_INTRIN) add_definitions(-DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET) - set(AVX2_SRCS ${ARCHDIR}/slide_avx.c) + set(AVX2_SRCS ${ARCHDIR}/slide_hash_avx.c) add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx.c) add_feature_info(AVX_CHUNKSET 1 "Support AVX optimized chunkset, using \"${AVX2FLAG}\"") @@ -704,7 +704,7 @@ if(WITH_OPTIM) check_sse2_intrinsics() if(HAVE_SSE2_INTRIN) add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) - set(SSE2_SRCS ${ARCHDIR}/chunkset_sse.c ${ARCHDIR}/slide_sse.c) + set(SSE2_SRCS ${ARCHDIR}/chunkset_sse.c ${ARCHDIR}/slide_hash_sse.c) list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) if(NOT ${ARCH} MATCHES "x86_64") set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG} ${NOLTOFLAG}") diff --git a/arch/arm/Makefile.in b/arch/arm/Makefile.in index d383ba0853..39c9a6a3bb 100644 --- a/arch/arm/Makefile.in +++ b/arch/arm/Makefile.in @@ -21,7 +21,7 @@ all: \ armfeature.o armfeature.lo \ chunkset_neon.o chunkset_neon.lo \ crc32_acle.o crc32_acle.lo \ - slide_neon.o slide_neon.lo \ + slide_hash_neon.o slide_hash_neon.lo \ insert_string_acle.o insert_string_acle.lo adler32_neon.o: @@ -48,11 +48,11 @@ crc32_acle.o: crc32_acle.lo: $(CC) $(SFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c -slide_neon.o: - $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_neon.c +slide_hash_neon.o: + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_neon.c -slide_neon.lo: - $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_neon.c +slide_hash_neon.lo: + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_neon.c insert_string_acle.o: $(CC) $(CFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_acle.c diff --git a/arch/arm/slide_neon.c b/arch/arm/slide_hash_neon.c similarity index 93% rename from arch/arm/slide_neon.c rename to arch/arm/slide_hash_neon.c index 87b5397647..b90e470219 100644 --- a/arch/arm/slide_neon.c +++ b/arch/arm/slide_hash_neon.c @@ -1,4 +1,4 @@ -/* slide_neon.c -- Optimized hash table shifting for ARM with support for NEON instructions +/* slide_hash_neon.c -- Optimized hash table shifting for ARM with support for NEON instructions * Copyright (C) 2017-2020 Mika T. Lindqvist * * Authors: diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index f58c49e81e..3e4b41fb0c 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -21,8 +21,8 @@ all: power.o \ adler32_power8.lo \ chunkset_power8.o \ chunkset_power8.lo \ - slide_power8.o \ - slide_power8.lo + slide_hash_power8.o \ + slide_hash_power8.lo power.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power.c @@ -42,11 +42,11 @@ chunkset_power8.o: chunkset_power8.lo: $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_power8.c -slide_power8.o: - $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_power8.c +slide_hash_power8.o: + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c -slide_power8.lo: - $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_power8.c +slide_hash_power8.lo: + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c mostlyclean: clean clean: diff --git a/arch/power/slide_power8.c b/arch/power/slide_hash_power8.c similarity index 100% rename from arch/power/slide_power8.c rename to arch/power/slide_hash_power8.c diff --git a/arch/x86/INDEX.md b/arch/x86/INDEX.md index 8bf6d08e5d..d32bfe8b1d 100644 --- a/arch/x86/INDEX.md +++ b/arch/x86/INDEX.md @@ -5,4 +5,4 @@ Contents |:-|:-| |deflate_quick.c|SSE4 optimized deflate strategy for use as level 1| |crc_folding.c|SSE4 + PCLMULQDQ optimized CRC folding implementation| -|slide_sse2.c|SSE2 optimized slide_hash| +|slide_hash_sse2.c|SSE2 optimized slide_hash| diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 13c736c632..fa153592a5 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -29,8 +29,8 @@ all: \ compare258_sse.o compare258_sse.lo \ insert_string_sse.o insert_string_sse.lo \ crc_folding.o crc_folding.lo \ - slide_avx.o slide_avx.lo \ - slide_sse.o slide_sse.lo + slide_hash_avx.o slide_hash_avx.lo \ + slide_hash_sse.o slide_hash_sse.lo x86.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c @@ -74,17 +74,17 @@ crc_folding.o: crc_folding.lo: $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c -slide_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_avx.c +slide_hash_avx.o: + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx.c -slide_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_avx.c +slide_hash_avx.lo: + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx.c -slide_sse.o: - $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_sse.c +slide_hash_sse.o: + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_sse.c -slide_sse.lo: - $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_sse.c +slide_hash_sse.lo: + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_sse.c adler32_avx.o: $(SRCDIR)/adler32_avx.c $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c diff --git a/arch/x86/slide_avx.c b/arch/x86/slide_hash_avx.c similarity index 100% rename from arch/x86/slide_avx.c rename to arch/x86/slide_hash_avx.c diff --git a/arch/x86/slide_sse.c b/arch/x86/slide_hash_sse.c similarity index 100% rename from arch/x86/slide_sse.c rename to arch/x86/slide_hash_sse.c diff --git a/configure b/configure index 3c278cfcdd..badaa0ae80 100755 --- a/configure +++ b/configure @@ -1252,8 +1252,8 @@ case "${ARCH}" in if test ${HAVE_AVX2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" SFLAGS="${SFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_avx.o chunkset_avx.o compare258_avx.o adler32_avx.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_avx.lo chunkset_avx.lo compare258_avx.lo adler32_avx.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_hash_avx.o chunkset_avx.o compare258_avx.o adler32_avx.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx.lo chunkset_avx.lo compare258_avx.lo adler32_avx.lo" fi check_sse4_intrinsics @@ -1286,8 +1286,8 @@ case "${ARCH}" in if test ${HAVE_SSE2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" SFLAGS="${SFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse.o slide_sse.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse.lo slide_sse.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse.o slide_hash_sse.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse.lo slide_hash_sse.lo" if test $forcesse2 -eq 1; then CFLAGS="${CFLAGS} -DX86_NOCHECK_SSE2" @@ -1447,8 +1447,8 @@ EOF CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_neon.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_hash_neon.lo" fi fi ;; @@ -1469,8 +1469,8 @@ EOF CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_neon.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_hash_neon.lo" fi fi ;; @@ -1495,8 +1495,8 @@ EOF CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_neon.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_hash_neon.lo" fi fi ;; @@ -1551,8 +1551,8 @@ EOF fi CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_neon.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_hash_neon.lo" fi fi @@ -1587,8 +1587,8 @@ EOF CFLAGS="${CFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_CHUNKSET -DPOWER8_VSX_SLIDEHASH" SFLAGS="${SFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_CHUNKSET -DPOWER8_VSX_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o adler32_power8.o chunkset_power8.o slide_power8.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo adler32_power8.lo chunkset_power8.lo slide_power8.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o adler32_power8.o chunkset_power8.o slide_hash_power8.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo adler32_power8.lo chunkset_power8.lo slide_hash_power8.lo" fi fi ;; diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 8a39249dd8..8746e5cbfd 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -96,7 +96,7 @@ WFLAGS = $(WFLAGS) \ -DARM_NEON_SLIDEHASH \ -DARM_NOCHECK_NEON \ # -OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj adler32_neon.obj chunkset_neon.obj slide_neon.obj +OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj adler32_neon.obj chunkset_neon.obj slide_hash_neon.obj # targets all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ @@ -181,6 +181,7 @@ inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/ inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h +slide_hash_neon.obj: $(SRCDIR)/arch/arm/slide_hash_neon.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 9897ad8e90..8403043996 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -107,7 +107,7 @@ WFLAGS = $(WFLAGS) \ -DARM_NEON_SLIDEHASH \ -DARM_NOCHECK_NEON \ # -OBJS = $(OBJS) adler32_neon.obj chunkset_neon.obj slide_neon.obj +OBJS = $(OBJS) adler32_neon.obj chunkset_neon.obj slide_hash_neon.obj !endif # targets diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 0ff683e2f7..3110f7fe98 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -76,8 +76,8 @@ OBJS = \ insert_string_roll.obj \ insert_string_sse.obj \ slide_hash.obj \ - slide_avx.obj \ - slide_sse.obj \ + slide_hash_avx.obj \ + slide_hash_sse.obj \ trees.obj \ uncompr.obj \ zutil.obj \ @@ -187,7 +187,8 @@ inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/ inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h -slide_sse.obj: $(SRCDIR)/arch/x86/slide_sse.c $(SRCDIR)/deflate.h +slide_hash_avx.obj: $(SRCDIR)/arch/x86/slide_hash_avx.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h +slide_hash_sse.obj: $(SRCDIR)/arch/x86/slide_hash_sse.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h From 834e8ce342fa9f24c25be3ec8385ea162efc94ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20Rosenkr=C3=A4nzer?= Date: Sun, 27 Jun 2021 14:31:54 +0200 Subject: [PATCH 118/798] Fix Z_SOLO mode Without this patch, #include with Z_SOLO defined (e.g. while building perl 5.34.0) fails because of use of undefined types. --- zlib.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zlib.h b/zlib.h index 6852dc67bc..842559485d 100644 --- a/zlib.h +++ b/zlib.h @@ -1767,6 +1767,7 @@ Z_EXTERN int Z_EXPORT inflateBackInit_(z_stream *strm, int windowBits, unsigned inflateBackInit_((strm), (windowBits), (window), ZLIB_VERSION, (int)sizeof(z_stream)) +#ifndef Z_SOLO /* gzgetc() macro and its supporting function and exposed data structure. Note * that the real internal state is much larger than the exposed structure. * This abbreviated structure exposes just enough for the gzgetc() macro. The @@ -1797,6 +1798,7 @@ Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ Z_EXTERN unsigned long Z_EXPORT crc32_combine64(unsigned long, unsigned long, z_off64_t); Z_EXTERN void Z_EXPORT crc32_combine_gen64(uint32_t *op, z_off64_t); #endif +#endif #if !defined(Z_INTERNAL) && defined(Z_WANT64) # define gzopen gzopen64 @@ -1835,10 +1837,12 @@ Z_EXTERN unsigned long Z_EXPORT inflateCodesUsed (z_stream *); Z_EXTERN int Z_EXPORT inflateResetKeep (z_stream *); Z_EXTERN int Z_EXPORT deflateResetKeep (z_stream *); +#ifndef Z_SOLO #if defined(_WIN32) Z_EXTERN gzFile Z_EXPORT gzopen_w(const wchar_t *path, const char *mode); #endif Z_EXTERN int Z_EXPORTVA gzvprintf(gzFile file, const char *format, va_list va); +#endif #ifdef __cplusplus } From 77d4c8789ed831db309ea4ae1b701d7a6296173d Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 26 Mar 2017 22:54:17 +0300 Subject: [PATCH 119/798] PowerPC: Add initial support for AltiVec. * Add detection of VMX instructions --- CMakeLists.txt | 32 ++++++++- arch/power/Makefile.in | 20 +++++- arch/power/adler32_vmx.c | 118 ++++++++++++++++++++++++++++++++++ arch/power/power.c | 17 ++++- arch/power/power.h | 2 + arch/power/slide_hash_vmx.c | 34 ++++++++++ cmake/detect-intrinsics.cmake | 50 ++++++++++++++ configure | 62 +++++++++++++++++- functable.c | 19 +++++- zutil.h | 2 +- 10 files changed, 345 insertions(+), 11 deletions(-) create mode 100644 arch/power/adler32_vmx.c create mode 100644 arch/power/slide_hash_vmx.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 614d7e5934..8c4523b3de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,6 +94,7 @@ if(BASEARCH_ARM_FOUND) option(WITH_ACLE "Build with ACLE" ON) option(WITH_NEON "Build with NEON intrinsics" ON) elseif(BASEARCH_PPC_FOUND) + option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON) option(WITH_POWER8 "Build with optimisations for POWER8" ON) elseif(BASEARCH_S360_FOUND) option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF) @@ -119,6 +120,7 @@ mark_as_advanced(FORCE WITH_AVX2 WITH_SSE2 WITH_SSSE3 WITH_SSE4 WITH_PCLMULQDQ + WITH_ALTIVEC WITH_POWER8 WITH_INFLATE_STRICT WITH_INFLATE_ALLOW_INVALID_DIST @@ -608,16 +610,41 @@ if(WITH_OPTIM) endif() endif() elseif(BASEARCH_PPC_FOUND) + # Common arch detection code + if(WITH_ALTIVEC) + check_ppc_intrinsics() + endif() if(WITH_POWER8) check_power8_intrinsics() + endif() + if(HAVE_VMX OR HAVE_POWER8_INTRIN) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) + endif() + # VMX specific options and files + if(WITH_ALTIVEC) + if(HAVE_VMX) + add_definitions(-DPPC_FEATURES) + if(HAVE_ALTIVEC) + add_definitions(-DPPC_VMX_ADLER32) + add_definitions(-DPPC_VMX_SLIDEHASH) + set(PPC_SRCS ${ARCHDIR}/adler32_vmx.c ${ARCHDIR}/slide_hash_vmx.c) + list(APPEND ZLIB_ARCH_SRCS ${PPC_SRCS}) + add_feature_info(ALTIVEC 1 "Support the AltiVec instruction set, using \"-maltivec\"") + set_property(SOURCE ${PPC_SRCS} PROPERTY COMPILE_FLAGS "${PPCFLAGS}") + else() + set(WITH_ALTIVEC OFF) + endif() + endif() + endif() + # Power8 specific options and files + if(WITH_POWER8) if(HAVE_POWER8_INTRIN) add_definitions(-DPOWER8) add_definitions(-DPOWER_FEATURES) add_definitions(-DPOWER8_VSX_ADLER32) add_definitions(-DPOWER8_VSX_CHUNKSET) add_definitions(-DPOWER8_VSX_SLIDEHASH) - list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/chunkset_power8.c ${ARCHDIR}/slide_hash_power8.c) list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") @@ -1315,6 +1342,7 @@ if(BASEARCH_ARM_FOUND) add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE") add_feature_info(WITH_NEON WITH_NEON "Build with NEON intrinsics") elseif(BASEARCH_PPC_FOUND) + add_feature_info(WITH_ALTIVEC WITH_ALTIVEC "Build with AltiVec optimisations") add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8") elseif(BASEARCH_S360_FOUND) add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z") diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index 3e4b41fb0c..9b94e0b7c8 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -1,5 +1,6 @@ # Makefile for POWER-specific files # Copyright (C) 2020 Matheus Castanho , IBM +# Copyright (C) 2021 Mika T. Lindqvist # For conditions of distribution and use, see copyright notice in zlib.h CC= @@ -9,6 +10,7 @@ INCLUDES= SUFFIX= P8FLAGS=-mcpu=power8 +PPCFLAGS=-maltivec NOLTOFLAG= SRCDIR=. @@ -19,10 +21,14 @@ all: power.o \ power.lo \ adler32_power8.o \ adler32_power8.lo \ + adler32_vmx.o \ + adler32_vmx.lo \ chunkset_power8.o \ chunkset_power8.lo \ slide_hash_power8.o \ - slide_hash_power8.lo + slide_hash_power8.lo \ + slide_hash_vmx.o \ + slide_hash_vmx.lo power.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power.c @@ -36,6 +42,12 @@ adler32_power8.o: adler32_power8.lo: $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c +adler32_vmx.o: + $(CC) $(CFLAGS) $(PPCFLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_vmx.c + +adler32_vmx.lo: + $(CC) $(SFLAGS) $(PPCFLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_vmx.c + chunkset_power8.o: $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_power8.c @@ -48,6 +60,12 @@ slide_hash_power8.o: slide_hash_power8.lo: $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c +slide_hash_vmx.o: + $(CC) $(CFLAGS) ${PPCFLAGS} $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_vmx.c + +slide_hash_vmx.lo: + $(CC) $(SFLAGS) ${PPCFLAGS} $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_vmx.c + mostlyclean: clean clean: rm -f *.o *.lo *~ diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c new file mode 100644 index 0000000000..5d7dc43e2c --- /dev/null +++ b/arch/power/adler32_vmx.c @@ -0,0 +1,118 @@ +/* adler32_vmx.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 2017-2021 Mika T. Lindqvist + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef PPC_VMX_ADLER32 +#include +#include "zutil.h" +#include "adler32_p.h" + +#define vmx_zero() (vec_splat_u32(0)) + +vector unsigned short vec_hadduh(vector unsigned char a) { + vector unsigned char vmx_one = vec_splat_u8(1); + return vec_add(vec_mulo(a, vmx_one), vec_mule(a, vmx_one)); +} + +vector unsigned int vec_hadduw(vector unsigned short a) { + vector unsigned short vmx_one = vec_splat_u16(1); + return vec_add(vec_mulo(a, vmx_one), vec_mule(a, vmx_one)); +} + +static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char *buf, size_t len) { + unsigned int i; + for (i = 0; i < len; ++i) { + pair[0] += buf[i]; + pair[1] += pair[0]; + } +} + +static void vmx_accum32(uint32_t *s, const unsigned char *buf, size_t len) { + static const uint8_t tc0[16] ALIGNED_(16) = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + + vector unsigned char t0 = vec_ld(0, tc0); + vector unsigned int adacc, s2acc; + adacc = vec_insert(s[0], vmx_zero(), 0); + s2acc = vec_insert(s[1], vmx_zero(), 0); + + while (len > 0) { + vector unsigned char d0 = vec_ld(0, buf); + vector unsigned short sum2; + sum2 = vec_add(vec_mulo(t0, d0), vec_mule(t0, d0)); + s2acc = vec_add(s2acc, vec_sl(adacc, vec_splat_u32(4))); + s2acc = vec_add(s2acc, vec_hadduw(sum2)); + adacc = vec_add(adacc, vec_hadduw(vec_hadduh(d0))); + buf += 16; + len--; + } + + s[0] = vec_extract(adacc, 0) + vec_extract(adacc, 1) + vec_extract(adacc, 2) + vec_extract(adacc, 3); /* Horizontal add */ + s[1] = vec_extract(s2acc, 0) + vec_extract(s2acc, 1) + vec_extract(s2acc, 2) + vec_extract(s2acc, 3); /* Horizontal add */ +} + +uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len) { + uint32_t sum2; + uint32_t pair[2]; + int n = NMAX; + unsigned int done = 0, i; + + /* Split Adler-32 into component sums, it can be supplied by + * the caller sites (e.g. in a PNG file). + */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + pair[0] = adler; + pair[1] = sum2; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) + return adler32_len_1(adler, buf, sum2); + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (UNLIKELY(buf == NULL)) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (UNLIKELY(len < 16)) + return adler32_len_16(adler, buf, len, sum2); + + // Align buffer + unsigned int al = 0; + if ((uintptr_t)buf & 0xf) { + al = 16-((uintptr_t)buf & 0xf); + if (al > len) { + al=len; + } + vmx_handle_head_or_tail(pair, buf, al); + pair[0] %= BASE; + pair[1] %= BASE; + + done += al; + } + for (i = al; i < len; i += n) { + if ((i + n) > len) + n = (int)(len - i); + + if (n < 16) + break; + + vmx_accum32(pair, buf + i, n / 16); + pair[0] %= BASE; + pair[1] %= BASE; + + done += (n / 16) * 16; + } + + /* Handle the tail elements. */ + if (done < len) { + vmx_handle_head_or_tail(pair, (buf + done), len - done); + pair[0] %= BASE; + pair[1] %= BASE; + } + + /* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */ + return (pair[1] << 16) | pair[0]; +} +#endif diff --git a/arch/power/power.c b/arch/power/power.c index f93b586d50..d17fe3f4f3 100644 --- a/arch/power/power.c +++ b/arch/power/power.c @@ -1,19 +1,30 @@ /* POWER feature check * Copyright (C) 2020 Matheus Castanho , IBM + * Copyright (C) 2021 Mika T. Lindqvist * For conditions of distribution and use, see copyright notice in zlib.h */ #include #include "../../zutil.h" +#include "power.h" -Z_INTERNAL int power_cpu_has_arch_2_07; +Z_INTERNAL int power_cpu_has_altivec = 0; +Z_INTERNAL int power_cpu_has_arch_2_07 = 0; void Z_INTERNAL power_check_features(void) { +#ifdef PPC_FEATURES + unsigned long hwcap; + hwcap = getauxval(AT_HWCAP); + + if (hwcap & PPC_FEATURE_HAS_ALTIVEC) + power_cpu_has_altivec = 1; +#endif + +#ifdef POWER_FEATURES unsigned long hwcap2; hwcap2 = getauxval(AT_HWCAP2); -#ifdef POWER8 if (hwcap2 & PPC_FEATURE2_ARCH_2_07) - power_cpu_has_arch_2_07 = 1; + power_cpu_has_arch_2_07 = 1; #endif } diff --git a/arch/power/power.h b/arch/power/power.h index b36c261410..81ce009617 100644 --- a/arch/power/power.h +++ b/arch/power/power.h @@ -1,11 +1,13 @@ /* power.h -- check for POWER CPU features * Copyright (C) 2020 Matheus Castanho , IBM + * Copyright (C) 2021 Mika T. Lindqvist * For conditions of distribution and use, see copyright notice in zlib.h */ #ifndef POWER_H_ #define POWER_H_ +extern int power_cpu_has_altivec; extern int power_cpu_has_arch_2_07; void Z_INTERNAL power_check_features(void); diff --git a/arch/power/slide_hash_vmx.c b/arch/power/slide_hash_vmx.c new file mode 100644 index 0000000000..b16df15384 --- /dev/null +++ b/arch/power/slide_hash_vmx.c @@ -0,0 +1,34 @@ +/* Optimized slide_hash for PowerPC processors with VMX instructions + * Copyright (C) 2017-2021 Mika T. Lindqvist + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#ifdef PPC_VMX_SLIDEHASH + +#include +#include "zbuild.h" +#include "deflate.h" + +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { + const vector unsigned short vmx_wsize = vec_splats(wsize); + Pos *p = table; + + do { + vector unsigned short value, result; + + value = vec_ld(0, p); + result = vec_subs(value, vmx_wsize); + vec_st(result, 0, p); + + p += 8; + entries -= 8; + } while (entries > 0); +} + +void Z_INTERNAL slide_hash_vmx(deflate_state *s) { + uint16_t wsize = s->w_size; + + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); +} + +#endif /* PPC_VMX_SLIDEHASH */ diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 90c5f3bee1..c6085018a6 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -86,6 +86,56 @@ macro(check_pclmulqdq_intrinsics) endif() endmacro() +macro(check_ppc_intrinsics) + # Check if compiler supports AltiVec + set(CMAKE_REQUIRED_FLAGS "-maltivec") + check_c_source_compiles( + "#include + int main(void) + { + vector int a = vec_splats(0); + vector int b = vec_splats(0); + a = vec_add(a, b); + return 0; + }" + HAVE_ALTIVEC + ) + set(CMAKE_REQUIRED_FLAGS) + + if(HAVE_ALTIVEC) + set(PPCFLAGS "-maltivec") + endif() + + set(CMAKE_REQUIRED_FLAGS "-maltivec -mno-vsx") + check_c_source_compiles( + "#include + int main(void) + { + vector int a = vec_splats(0); + vector int b = vec_splats(0); + a = vec_add(a, b); + return 0; + }" + HAVE_NOVSX + ) + set(CMAKE_REQUIRED_FLAGS) + + if(HAVE_NOVSX) + set(PPCFLAGS "${PPCFLAGS} -mno-vsx") + endif() + + # Check if we have what we need for AltiVec optimizations + set(CMAKE_REQUIRED_FLAGS "${PPCFLAGS}") + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); + }" + HAVE_VMX + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + macro(check_power8_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) diff --git a/configure b/configure index badaa0ae80..e48dfdc565 100755 --- a/configure +++ b/configure @@ -91,6 +91,7 @@ cover=0 build32=0 build64=0 buildacle=1 +buildaltivec=1 buildneon=1 builddfltccdeflate=0 builddfltccinflate=0 @@ -110,6 +111,7 @@ acleflag= neonflag= noltoflag="-fno-lto" vgfmaflag="-march=z13" +vmxflag="-maltivec" without_optimizations=0 without_new_strategies=0 reducedmem=0 @@ -155,6 +157,7 @@ case "$1" in echo ' [--without-new-strategies] Compiles without using new additional deflate strategies' | tee -a configure.log echo ' [--without-acle] Compiles without ARM C Language Extensions' | tee -a configure.log echo ' [--without-neon] Compiles without ARM Neon SIMD instruction set' | tee -a configure.log + echo ' [--without-altivec] Compiles without PPC AltiVec support' | tee -a configure.log echo ' [--with-dfltcc-deflate] Use DEFLATE CONVERSION CALL instruction for compression on IBM Z' | tee -a configure.log echo ' [--with-dfltcc-inflate] Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z' | tee -a configure.log echo ' [--without-crc32-vx] Build without vectorized CRC32 on IBM Z' | tee -a configure.log @@ -183,6 +186,7 @@ case "$1" in -6* | --64) build64=1; shift ;; --without-acle) buildacle=0; shift ;; --without-neon) buildneon=0; shift ;; + --without-altivec) buildaltivec=0 ; shift ;; --with-dfltcc-deflate) builddfltccdeflate=1; shift ;; --with-dfltcc-inflate) builddfltccinflate=1; shift ;; --without-crc32-vx) buildcrc32vx=0; shift ;; @@ -1061,6 +1065,43 @@ EOF fi } +check_ppc_intrinsics() { + cat > $test.c << EOF +#include +int main(void) +{ + vector int a = vec_splats(0); + vector int b = vec_splats(0); + a = vec_add(a, b); + return 0; +} +EOF + if test $buildaltivec -eq 1 && try ${CC} ${CFLAGS} -maltivec $test.c; then + echo "Checking for AltiVec intrinsics ... Yes." | tee -a configure.log + HAVE_ALTIVEC_INTRIN=1 + else + echo "Checking for AltiVec intrinsics ... No." | tee -a configure.log + HAVE_ALTIVEC_INTRIN=0 + fi + if test $buildaltivec -eq 1 && try ${CC} ${CFLAGS} -maltivec -mno-vsx $test.c; then + echo "Checking if -mno-vsx is supported ... Yes." | tee -a configure.log + vmxflag="$vmxflag -mno-vsx" + else + echo "Checking if -mno-vsx is supported ... No." | tee -a configure.log + fi + cat > $test.c << EOF +#include +int main() { return (getauxval(AT_HWCAP) & PPC_FEATURE_HAS_ALTIVEC); } +EOF + if try $CC -c $CFLAGS -maltivec $test.c; then + HAVE_VMX=1 + echo "Check whether VMX instructions are available ... Yes." | tee -a configure.log + else + HAVE_VMX=0 + echo "Check whether VMX instructions are available ... No." | tee -a configure.log + fi +} + check_power8_intrinsics() { # Check whether features needed by POWER optimisations are available cat > $test.c << EOF @@ -1581,14 +1622,30 @@ EOF if test $without_optimizations -eq 0; then + check_ppc_intrinsics check_power8_intrinsics + if test $HAVE_VMX -eq 1; then + CFLAGS="${CFLAGS} -DPPC_FEATURES" + SFLAGS="${SFLAGS} -DPPC_FEATURES" + fi + if test $HAVE_VMX -eq 1 -o $HAVE_POWER8_INTRIN -eq 1; then + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo" + fi + if test $HAVE_VMX -eq 1 -a $HAVE_ALTIVEC_INTRIN -eq 1; then + CFLAGS="${CFLAGS} -DPPC_VMX_ADLER32 -DPPC_VMX_SLIDEHASH" + SFLAGS="${SFLAGS} -DPPC_VMX_ADLER32 -DPPC_VMX_SLIDEHASH" + + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_vmx.o slide_hash_vmx.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_vmx.lo slide_hash_vmx.lo" + fi if test $HAVE_POWER8_INTRIN -eq 1; then CFLAGS="${CFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_CHUNKSET -DPOWER8_VSX_SLIDEHASH" SFLAGS="${SFLAGS} -DPOWER8 -DPOWER_FEATURES -DPOWER8_VSX_ADLER32 -DPOWER8_VSX_CHUNKSET -DPOWER8_VSX_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} power.o adler32_power8.o chunkset_power8.o slide_hash_power8.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} power.lo adler32_power8.lo chunkset_power8.lo slide_hash_power8.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_power8.o chunkset_power8.o slide_hash_power8.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_power8.lo chunkset_power8.lo slide_hash_power8.lo" fi fi ;; @@ -1829,6 +1886,7 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^NEONFLAG *=/s#=.*#=$neonflag# /^NOLTOFLAG *=/s#=.*#=$noltoflag# /^VGFMAFLAG *=/s#=.*#=$vgfmaflag# +/^PPCFLAGS *=/s#=.*#=$vmxflag# " > $ARCHDIR/Makefile # Append header files dependences. diff --git a/functable.c b/functable.c index af3aaa2d8b..17544feb9e 100644 --- a/functable.c +++ b/functable.c @@ -44,7 +44,11 @@ extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); void slide_hash_sse2(deflate_state *s); #elif defined(ARM_NEON_SLIDEHASH) void slide_hash_neon(deflate_state *s); -#elif defined(POWER8_VSX_SLIDEHASH) +#endif +#if defined(PPC_VMX_SLIDEHASH) +void slide_hash_vmx(deflate_state *s); +#endif +#if defined(POWER8_VSX_SLIDEHASH) void slide_hash_power8(deflate_state *s); #endif #ifdef X86_AVX2 @@ -56,6 +60,9 @@ extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len); #ifdef ARM_NEON_ADLER32 extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len); #endif +#ifdef PPC_VMX_ADLER32 +extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len); +#endif #ifdef X86_SSSE3_ADLER32 extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); #endif @@ -175,7 +182,7 @@ Z_INTERNAL void cpu_check_features(void) x86_check_features(); #elif defined(ARM_FEATURES) arm_check_features(); -#elif defined(POWER_FEATURES) +#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) power_check_features(); #elif defined(S390_FEATURES) s390_check_features(); @@ -252,6 +259,10 @@ Z_INTERNAL void slide_hash_stub(deflate_state *s) { if (x86_cpu_has_avx2) functable.slide_hash = &slide_hash_avx2; #endif +#ifdef PPC_VMX_SLIDEHASH + if (power_cpu_has_altivec) + functable.slide_hash = &slide_hash_vmx; +#endif #ifdef POWER8_VSX_SLIDEHASH if (power_cpu_has_arch_2_07) functable.slide_hash = &slide_hash_power8; @@ -279,6 +290,10 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ if (x86_cpu_has_avx2) functable.adler32 = &adler32_avx2; #endif +#ifdef PPC_VMX_ADLER32 + if (power_cpu_has_altivec) + functable.adler32 = &adler32_vmx; +#endif #ifdef POWER8_VSX_ADLER32 if (power_cpu_has_arch_2_07) functable.adler32 = &adler32_power8; diff --git a/zutil.h b/zutil.h index 4e89509555..bcb9ed12fc 100644 --- a/zutil.h +++ b/zutil.h @@ -250,7 +250,7 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr); # include "arch/x86/x86.h" #elif defined(ARM_FEATURES) # include "arch/arm/arm.h" -#elif defined(POWER_FEATURES) +#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) # include "arch/power/power.h" #elif defined(S390_FEATURES) # include "arch/s390/s390.h" From 6cca2c5065719e8846877e820145db652fba6138 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 13 Jun 2021 20:24:09 +0300 Subject: [PATCH 120/798] Add PowerPC without Power8 optimizations to GitHub Actions' configure and cmake workflows. --- .github/workflows/cmake.yml | 9 +++++++++ .github/workflows/configure.yml | 8 ++++++++ configure | 5 ++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index a172451bbf..18377740fc 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -170,6 +170,15 @@ jobs: ldflags: -static codecov: ubuntu_gcc_ppc + - name: Ubuntu GCC PPC No Power8 + os: ubuntu-latest + compiler: powerpc-linux-gnu-gcc + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake -DWITH_POWER8=OFF + asan-options: detect_leaks=0 + packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross + qemu-run: qemu-ppc + codecov: ubuntu_gcc_ppc_no_power8 + - name: Ubuntu GCC PPC64 os: ubuntu-latest compiler: powerpc64-linux-gnu-gcc diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 9d9dc35985..3892932b8c 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -120,6 +120,14 @@ jobs: cflags: -static ldflags: -static + - name: Ubuntu GCC PPC No Power8 + os: ubuntu-latest + compiler: powerpc-linux-gnu-gcc + configure-args: --warn --without-power8 + chost: powerpc-linux-gnu + packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross + qemu-run: qemu-ppc + - name: Ubuntu GCC PPC64 os: ubuntu-latest compiler: powerpc64-linux-gnu-gcc diff --git a/configure b/configure index e48dfdc565..26281338ee 100755 --- a/configure +++ b/configure @@ -92,6 +92,7 @@ build32=0 build64=0 buildacle=1 buildaltivec=1 +buildpower8=1 buildneon=1 builddfltccdeflate=0 builddfltccinflate=0 @@ -158,6 +159,7 @@ case "$1" in echo ' [--without-acle] Compiles without ARM C Language Extensions' | tee -a configure.log echo ' [--without-neon] Compiles without ARM Neon SIMD instruction set' | tee -a configure.log echo ' [--without-altivec] Compiles without PPC AltiVec support' | tee -a configure.log + echo ' [--without-power8] Compiles without Power8 instruction set' | tee -a configure.log echo ' [--with-dfltcc-deflate] Use DEFLATE CONVERSION CALL instruction for compression on IBM Z' | tee -a configure.log echo ' [--with-dfltcc-inflate] Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z' | tee -a configure.log echo ' [--without-crc32-vx] Build without vectorized CRC32 on IBM Z' | tee -a configure.log @@ -187,6 +189,7 @@ case "$1" in --without-acle) buildacle=0; shift ;; --without-neon) buildneon=0; shift ;; --without-altivec) buildaltivec=0 ; shift ;; + --without-power8) buildpower8=0 ; shift ;; --with-dfltcc-deflate) builddfltccdeflate=1; shift ;; --with-dfltcc-inflate) builddfltccinflate=1; shift ;; --without-crc32-vx) buildcrc32vx=0; shift ;; @@ -1108,7 +1111,7 @@ check_power8_intrinsics() { #include int main() { return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); } EOF - if try $CC -c $CFLAGS -mcpu=power8 $test.c; then + if test $buildpower8 -eq 1 && try $CC -c $CFLAGS -mcpu=power8 $test.c; then HAVE_POWER8_INTRIN=1 echo "Check whether POWER8 instructions are available ... Yes." | tee -a configure.log else From 8d6816604a23b84ff1fb53f6e5fbdbd64b084ac7 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 13 Jun 2021 20:53:16 +0300 Subject: [PATCH 121/798] Add AltiVec (VMX) to supported intrinsics for adler32 and slide_hash. --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 161a1b6333..d7a6689b61 100644 --- a/README.md +++ b/README.md @@ -21,10 +21,10 @@ Features * Modern C11 syntax and a clean code layout * Deflate medium and quick algorithms based on Intels zlib fork * Support for CPU intrinsics when available - * Adler32 implementation using SSSE3, AVX2, Neon & VSX + * Adler32 implementation using SSSE3, AVX2, Neon, VMX & VSX * CRC32-B implementation using PCLMULQDQ & ACLE * Hash table implementation using CRC32-C intrinsics on x86 and ARM - * Slide hash implementations using SSE2, AVX2, Neon & VSX + * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX * Compare256/258 implementations using SSE4.2 & AVX2 * Inflate chunk copying using SSE2, AVX2, Neon & VSX * CRC32 implementation using IBM Z vector instructions @@ -202,7 +202,8 @@ Advanced Build Options | WITH_PCLMULQDQ | | Build with PCLMULQDQ intrinsics | ON | | WITH_ACLE | --without-acle | Build with ACLE intrinsics | ON | | WITH_NEON | --without-neon | Build with NEON intrinsics | ON | -| WITH_POWER8 | | Build with POWER8 optimisations | ON | +| WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | ON | +| WITH_POWER8 | --without-power8 | Build with POWER8 optimisations | ON | | WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON | | WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF | | WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF | From f456924eaa9f08a3557cced8ed40b7ef6f9d76ea Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 22 Jun 2021 22:19:13 +0300 Subject: [PATCH 122/798] [PowerPC] Use templatized code for slide_hash as code for VMX and VSX is very similar * Any differences can be handled using compiler options or added as macros before including template header --- arch/power/slide_hash_power8.c | 46 ++-------------------------------- arch/power/slide_hash_vmx.c | 28 ++------------------- arch/power/slide_ppc_tpl.h | 31 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 70 deletions(-) create mode 100644 arch/power/slide_ppc_tpl.h diff --git a/arch/power/slide_hash_power8.c b/arch/power/slide_hash_power8.c index f153057274..5b078ec9f9 100644 --- a/arch/power/slide_hash_power8.c +++ b/arch/power/slide_hash_power8.c @@ -6,49 +6,7 @@ #ifdef POWER8_VSX_SLIDEHASH -#include -#include "zbuild.h" -#include "deflate.h" - -static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { - vector unsigned short vw, vm, *vp; - unsigned chunks; - - table += entries; - - /* Each vector register (chunk) corresponds to 128 bits == 8 Posf, - * so instead of processing each of the entries in the hash table - * individually, we can do it in chunks of 8 with vector instructions. - * - * This function is only called from slide_hash_power8(), and both calls - * pass entries as a power of 2 higher than 2^7, as defined by - * deflateInit2_(), so entries will always be a multiple of 8. */ - chunks = entries >> 3; - Assert(entries % 8 == 0, "Weird hash table size!"); - - vw[0] = wsize; - vw = vec_splat(vw,0); - - vp = (vector unsigned short *)table; - - do { - /* Processing 8 elements at a time */ - vp--; - vm = *vp; - - /* This is equivalent to: m >= wsize ? m - wsize : 0 - * Since we are using a saturated unsigned subtraction, any - * values that are <= wsize will be set to 0, while the others - * will be subtracted by wsize. */ - *vp = vec_subs(vm,vw); - } while (--chunks); -} - -void Z_INTERNAL slide_hash_power8(deflate_state *s) { - uint16_t wsize = s->w_size; - - slide_hash_chain(s->head, HASH_SIZE, wsize); - slide_hash_chain(s->prev, wsize, wsize); -} +#define SLIDE_PPC slide_hash_power8 +#include "slide_ppc_tpl.h" #endif /* POWER8_VSX_SLIDEHASH */ diff --git a/arch/power/slide_hash_vmx.c b/arch/power/slide_hash_vmx.c index b16df15384..cf9bd7b797 100644 --- a/arch/power/slide_hash_vmx.c +++ b/arch/power/slide_hash_vmx.c @@ -4,31 +4,7 @@ */ #ifdef PPC_VMX_SLIDEHASH -#include -#include "zbuild.h" -#include "deflate.h" - -static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { - const vector unsigned short vmx_wsize = vec_splats(wsize); - Pos *p = table; - - do { - vector unsigned short value, result; - - value = vec_ld(0, p); - result = vec_subs(value, vmx_wsize); - vec_st(result, 0, p); - - p += 8; - entries -= 8; - } while (entries > 0); -} - -void Z_INTERNAL slide_hash_vmx(deflate_state *s) { - uint16_t wsize = s->w_size; - - slide_hash_chain(s->head, HASH_SIZE, wsize); - slide_hash_chain(s->prev, wsize, wsize); -} +#define SLIDE_PPC slide_hash_vmx +#include "slide_ppc_tpl.h" #endif /* PPC_VMX_SLIDEHASH */ diff --git a/arch/power/slide_ppc_tpl.h b/arch/power/slide_ppc_tpl.h new file mode 100644 index 0000000000..5c17e38fb3 --- /dev/null +++ b/arch/power/slide_ppc_tpl.h @@ -0,0 +1,31 @@ +/* Optimized slide_hash for PowerPC processors + * Copyright (C) 2017-2021 Mika T. Lindqvist + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include "zbuild.h" +#include "deflate.h" + +static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { + const vector unsigned short vmx_wsize = vec_splats(wsize); + Pos *p = table; + + do { + vector unsigned short value, result; + + value = vec_ld(0, p); + result = vec_subs(value, vmx_wsize); + vec_st(result, 0, p); + + p += 8; + entries -= 8; + } while (entries > 0); +} + +void Z_INTERNAL SLIDE_PPC(deflate_state *s) { + uint16_t wsize = s->w_size; + + slide_hash_chain(s->head, HASH_SIZE, wsize); + slide_hash_chain(s->prev, wsize, wsize); +} From 747ffeb043c68349fb8cbb7f04f9b934a8f2e2e7 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 21 Jul 2021 19:26:43 +0300 Subject: [PATCH 123/798] [arm] Disable ACLE, UNALIGNED_OK and UNALIGNED64_OK on armv7 and earlier. * armv7 has partial support for unaligned reads, but compiler might use instructions that do not support unaligned accesses --- CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c4523b3de..b4eeaba81a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,7 +234,7 @@ endif() # Set architecture alignment requirements if(WITH_UNALIGNED) - if(BASEARCH_ARM_FOUND OR (BASEARCH_PPC_FOUND AND "${ARCH}" MATCHES "powerpc64le") OR BASEARCH_X86_FOUND) + if((BASEARCH_ARM_FOUND AND NOT "${ARCH}" MATCHES "armv[2-7]") OR (BASEARCH_PPC_FOUND AND "${ARCH}" MATCHES "powerpc64le") OR BASEARCH_X86_FOUND) if(NOT DEFINED UNALIGNED_OK) set(UNALIGNED_OK TRUE) endif() @@ -245,7 +245,9 @@ if(WITH_UNALIGNED) endif() if(BASEARCH_ARM_FOUND) if(NOT DEFINED UNALIGNED64_OK) - if("${ARCH}" MATCHES "(arm(v[8-9])?|aarch64)") + if("${ARCH}" MATCHES "armv[2-7]") + set(UNALIGNED64_OK FALSE) + elseif("${ARCH}" MATCHES "(arm(v[8-9])?|aarch64)") set(UNALIGNED64_OK TRUE) endif() endif() @@ -579,7 +581,7 @@ if(WITH_OPTIM) endif() list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/armfeature.c) - if(WITH_ACLE AND NOT MSVC) + if(WITH_ACLE AND NOT MSVC AND NOT "${ARCH}" MATCHES "armv[2-7]") check_acle_intrinsics() if(HAVE_ACLE_INTRIN) add_definitions(-DARM_ACLE_CRC_HASH) @@ -1336,7 +1338,8 @@ add_feature_info(WITH_MAINTAINER_WARNINGS WITH_MAINTAINER_WARNINGS "Build with p add_feature_info(WITH_CODE_COVERAGE WITH_CODE_COVERAGE "Enable code coverage reporting") add_feature_info(WITH_INFLATE_STRICT WITH_INFLATE_STRICT "Build with strict inflate distance checking") add_feature_info(WITH_INFLATE_ALLOW_INVALID_DIST WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances") -add_feature_info(WITH_UNALIGNED WITH_UNALIGNED "Support unaligned reads on platforms that support it") +add_feature_info(WITH_UNALIGNED UNALIGNED_OK "Support unaligned reads on platforms that support it") +add_feature_info(WITH_UNALIGNED64 UNALIGNED64_OK "Support unaligned 64-bit reads on platforms that support it") if(BASEARCH_ARM_FOUND) add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE") From 6d4096adf4749870620a95149371645a79948b42 Mon Sep 17 00:00:00 2001 From: Matheus Castanho Date: Wed, 16 Jun 2021 14:36:24 -0300 Subject: [PATCH 124/798] Standardize crc32_stub Reorganize statements inside crc32_stub() to match more closely the format used for other function stubs in functable.c. --- functable.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/functable.c b/functable.c index 17544feb9e..e1c8577f0e 100644 --- a/functable.c +++ b/functable.c @@ -467,6 +467,7 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t "crc32_z takes size_t but internally we have a uint64_t len"); /* return a function pointer for optimized arches here after a capability test */ + functable.crc32 = &crc32_generic; cpu_check_features(); if (use_byfour) { @@ -485,8 +486,6 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t #else # error No endian defined #endif - } else { - functable.crc32 = crc32_generic; } return functable.crc32(crc, buf, len); From 044badc1177e58327718dab483389a14f25b7ff5 Mon Sep 17 00:00:00 2001 From: Matheus Castanho Date: Wed, 16 Jun 2021 14:36:24 -0300 Subject: [PATCH 125/798] Add optimized crc32 for POWER8 and later processors This commit adds an optimized version of the crc32 function based on crc32-vpmsum from https://github.com/antonblanchard/crc32-vpmsum/ . The code has been relicensed to the zlib license. This is the C implementation created by Rogerio Alves It makes use of vector instructions to speed up CRC32 algorithm. Decompression times were improved by +30% on tests. Based on Daniel Black's work for the original zlib (madler/zlib#478). --- CMakeLists.txt | 4 + arch/power/Makefile.in | 8 + arch/power/crc32_constants.h | 1123 ++++++++++++++++++++++++++++++++ arch/power/crc32_power8.c | 589 +++++++++++++++++ arch/power/fallback_builtins.h | 31 + configure | 8 + functable.c | 6 + 7 files changed, 1769 insertions(+) create mode 100644 arch/power/crc32_constants.h create mode 100644 arch/power/crc32_power8.c create mode 100644 arch/power/fallback_builtins.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b4eeaba81a..77a22cc53b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -648,6 +648,10 @@ if(WITH_OPTIM) add_definitions(-DPOWER8_VSX_CHUNKSET) add_definitions(-DPOWER8_VSX_SLIDEHASH) set(POWER8_SRCS ${ARCHDIR}/adler32_power8.c ${ARCHDIR}/chunkset_power8.c ${ARCHDIR}/slide_hash_power8.c) + if("${ARCH}" MATCHES "powerpc64(le)?") + add_definitions(-DPOWER8_VSX_CRC32) + list(APPEND POWER8_SRCS ${ARCHDIR}/crc32_power8.c) + endif() list(APPEND ZLIB_ARCH_SRCS ${POWER8_SRCS}) set_property(SOURCE ${POWER8_SRCS} PROPERTY COMPILE_FLAGS "${POWER8FLAG} ${NOLTOFLAG}") else() diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index 9b94e0b7c8..344b221044 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -25,6 +25,8 @@ all: power.o \ adler32_vmx.lo \ chunkset_power8.o \ chunkset_power8.lo \ + crc32_power8.o \ + crc32_power8.lo \ slide_hash_power8.o \ slide_hash_power8.lo \ slide_hash_vmx.o \ @@ -54,6 +56,12 @@ chunkset_power8.o: chunkset_power8.lo: $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_power8.c +crc32_power8.o: + $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_power8.c + +crc32_power8.lo: + $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_power8.c + slide_hash_power8.o: $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_power8.c diff --git a/arch/power/crc32_constants.h b/arch/power/crc32_constants.h new file mode 100644 index 0000000000..7b0ec93b4a --- /dev/null +++ b/arch/power/crc32_constants.h @@ -0,0 +1,1123 @@ +/* Constants table used by crc32_power8.c + * Copyright (C) 2021 IBM Corporation + * + * This file was automatically generated, DO NOT EDIT IT MANUALLY. + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zendian.h" +#include "zutil.h" + +/* Reduce 262144 kbits to 1024 bits */ +static const __vector unsigned long long vcrc_const[255] ALIGNED_(16) = { +#if BYTE_ORDER == LITTLE_ENDIAN + /* x^261120 mod p(x)` << 1, x^261184 mod p(x)` << 1 */ + { 0x0000000099ea94a8, 0x00000001651797d2 }, + /* x^260096 mod p(x)` << 1, x^260160 mod p(x)` << 1 */ + { 0x00000000945a8420, 0x0000000021e0d56c }, + /* x^259072 mod p(x)` << 1, x^259136 mod p(x)` << 1 */ + { 0x0000000030762706, 0x000000000f95ecaa }, + /* x^258048 mod p(x)` << 1, x^258112 mod p(x)` << 1 */ + { 0x00000001a52fc582, 0x00000001ebd224ac }, + /* x^257024 mod p(x)` << 1, x^257088 mod p(x)` << 1 */ + { 0x00000001a4a7167a, 0x000000000ccb97ca }, + /* x^256000 mod p(x)` << 1, x^256064 mod p(x)` << 1 */ + { 0x000000000c18249a, 0x00000001006ec8a8 }, + /* x^254976 mod p(x)` << 1, x^255040 mod p(x)` << 1 */ + { 0x00000000a924ae7c, 0x000000014f58f196 }, + /* x^253952 mod p(x)` << 1, x^254016 mod p(x)` << 1 */ + { 0x00000001e12ccc12, 0x00000001a7192ca6 }, + /* x^252928 mod p(x)` << 1, x^252992 mod p(x)` << 1 */ + { 0x00000000a0b9d4ac, 0x000000019a64bab2 }, + /* x^251904 mod p(x)` << 1, x^251968 mod p(x)` << 1 */ + { 0x0000000095e8ddfe, 0x0000000014f4ed2e }, + /* x^250880 mod p(x)` << 1, x^250944 mod p(x)` << 1 */ + { 0x00000000233fddc4, 0x000000011092b6a2 }, + /* x^249856 mod p(x)` << 1, x^249920 mod p(x)` << 1 */ + { 0x00000001b4529b62, 0x00000000c8a1629c }, + /* x^248832 mod p(x)` << 1, x^248896 mod p(x)` << 1 */ + { 0x00000001a7fa0e64, 0x000000017bf32e8e }, + /* x^247808 mod p(x)` << 1, x^247872 mod p(x)` << 1 */ + { 0x00000001b5334592, 0x00000001f8cc6582 }, + /* x^246784 mod p(x)` << 1, x^246848 mod p(x)` << 1 */ + { 0x000000011f8ee1b4, 0x000000008631ddf0 }, + /* x^245760 mod p(x)` << 1, x^245824 mod p(x)` << 1 */ + { 0x000000006252e632, 0x000000007e5a76d0 }, + /* x^244736 mod p(x)` << 1, x^244800 mod p(x)` << 1 */ + { 0x00000000ab973e84, 0x000000002b09b31c }, + /* x^243712 mod p(x)` << 1, x^243776 mod p(x)` << 1 */ + { 0x000000007734f5ec, 0x00000001b2df1f84 }, + /* x^242688 mod p(x)` << 1, x^242752 mod p(x)` << 1 */ + { 0x000000007c547798, 0x00000001d6f56afc }, + /* x^241664 mod p(x)` << 1, x^241728 mod p(x)` << 1 */ + { 0x000000007ec40210, 0x00000001b9b5e70c }, + /* x^240640 mod p(x)` << 1, x^240704 mod p(x)` << 1 */ + { 0x00000001ab1695a8, 0x0000000034b626d2 }, + /* x^239616 mod p(x)` << 1, x^239680 mod p(x)` << 1 */ + { 0x0000000090494bba, 0x000000014c53479a }, + /* x^238592 mod p(x)` << 1, x^238656 mod p(x)` << 1 */ + { 0x00000001123fb816, 0x00000001a6d179a4 }, + /* x^237568 mod p(x)` << 1, x^237632 mod p(x)` << 1 */ + { 0x00000001e188c74c, 0x000000015abd16b4 }, + /* x^236544 mod p(x)` << 1, x^236608 mod p(x)` << 1 */ + { 0x00000001c2d3451c, 0x00000000018f9852 }, + /* x^235520 mod p(x)` << 1, x^235584 mod p(x)` << 1 */ + { 0x00000000f55cf1ca, 0x000000001fb3084a }, + /* x^234496 mod p(x)` << 1, x^234560 mod p(x)` << 1 */ + { 0x00000001a0531540, 0x00000000c53dfb04 }, + /* x^233472 mod p(x)` << 1, x^233536 mod p(x)` << 1 */ + { 0x0000000132cd7ebc, 0x00000000e10c9ad6 }, + /* x^232448 mod p(x)` << 1, x^232512 mod p(x)` << 1 */ + { 0x0000000073ab7f36, 0x0000000025aa994a }, + /* x^231424 mod p(x)` << 1, x^231488 mod p(x)` << 1 */ + { 0x0000000041aed1c2, 0x00000000fa3a74c4 }, + /* x^230400 mod p(x)` << 1, x^230464 mod p(x)` << 1 */ + { 0x0000000136c53800, 0x0000000033eb3f40 }, + /* x^229376 mod p(x)` << 1, x^229440 mod p(x)` << 1 */ + { 0x0000000126835a30, 0x000000017193f296 }, + /* x^228352 mod p(x)` << 1, x^228416 mod p(x)` << 1 */ + { 0x000000006241b502, 0x0000000043f6c86a }, + /* x^227328 mod p(x)` << 1, x^227392 mod p(x)` << 1 */ + { 0x00000000d5196ad4, 0x000000016b513ec6 }, + /* x^226304 mod p(x)` << 1, x^226368 mod p(x)` << 1 */ + { 0x000000009cfa769a, 0x00000000c8f25b4e }, + /* x^225280 mod p(x)` << 1, x^225344 mod p(x)` << 1 */ + { 0x00000000920e5df4, 0x00000001a45048ec }, + /* x^224256 mod p(x)` << 1, x^224320 mod p(x)` << 1 */ + { 0x0000000169dc310e, 0x000000000c441004 }, + /* x^223232 mod p(x)` << 1, x^223296 mod p(x)` << 1 */ + { 0x0000000009fc331c, 0x000000000e17cad6 }, + /* x^222208 mod p(x)` << 1, x^222272 mod p(x)` << 1 */ + { 0x000000010d94a81e, 0x00000001253ae964 }, + /* x^221184 mod p(x)` << 1, x^221248 mod p(x)` << 1 */ + { 0x0000000027a20ab2, 0x00000001d7c88ebc }, + /* x^220160 mod p(x)` << 1, x^220224 mod p(x)` << 1 */ + { 0x0000000114f87504, 0x00000001e7ca913a }, + /* x^219136 mod p(x)` << 1, x^219200 mod p(x)` << 1 */ + { 0x000000004b076d96, 0x0000000033ed078a }, + /* x^218112 mod p(x)` << 1, x^218176 mod p(x)` << 1 */ + { 0x00000000da4d1e74, 0x00000000e1839c78 }, + /* x^217088 mod p(x)` << 1, x^217152 mod p(x)` << 1 */ + { 0x000000001b81f672, 0x00000001322b267e }, + /* x^216064 mod p(x)` << 1, x^216128 mod p(x)` << 1 */ + { 0x000000009367c988, 0x00000000638231b6 }, + /* x^215040 mod p(x)` << 1, x^215104 mod p(x)` << 1 */ + { 0x00000001717214ca, 0x00000001ee7f16f4 }, + /* x^214016 mod p(x)` << 1, x^214080 mod p(x)` << 1 */ + { 0x000000009f47d820, 0x0000000117d9924a }, + /* x^212992 mod p(x)` << 1, x^213056 mod p(x)` << 1 */ + { 0x000000010d9a47d2, 0x00000000e1a9e0c4 }, + /* x^211968 mod p(x)` << 1, x^212032 mod p(x)` << 1 */ + { 0x00000000a696c58c, 0x00000001403731dc }, + /* x^210944 mod p(x)` << 1, x^211008 mod p(x)` << 1 */ + { 0x000000002aa28ec6, 0x00000001a5ea9682 }, + /* x^209920 mod p(x)` << 1, x^209984 mod p(x)` << 1 */ + { 0x00000001fe18fd9a, 0x0000000101c5c578 }, + /* x^208896 mod p(x)` << 1, x^208960 mod p(x)` << 1 */ + { 0x000000019d4fc1ae, 0x00000000dddf6494 }, + /* x^207872 mod p(x)` << 1, x^207936 mod p(x)` << 1 */ + { 0x00000001ba0e3dea, 0x00000000f1c3db28 }, + /* x^206848 mod p(x)` << 1, x^206912 mod p(x)` << 1 */ + { 0x0000000074b59a5e, 0x000000013112fb9c }, + /* x^205824 mod p(x)` << 1, x^205888 mod p(x)` << 1 */ + { 0x00000000f2b5ea98, 0x00000000b680b906 }, + /* x^204800 mod p(x)` << 1, x^204864 mod p(x)` << 1 */ + { 0x0000000187132676, 0x000000001a282932 }, + /* x^203776 mod p(x)` << 1, x^203840 mod p(x)` << 1 */ + { 0x000000010a8c6ad4, 0x0000000089406e7e }, + /* x^202752 mod p(x)` << 1, x^202816 mod p(x)` << 1 */ + { 0x00000001e21dfe70, 0x00000001def6be8c }, + /* x^201728 mod p(x)` << 1, x^201792 mod p(x)` << 1 */ + { 0x00000001da0050e4, 0x0000000075258728 }, + /* x^200704 mod p(x)` << 1, x^200768 mod p(x)` << 1 */ + { 0x00000000772172ae, 0x000000019536090a }, + /* x^199680 mod p(x)` << 1, x^199744 mod p(x)` << 1 */ + { 0x00000000e47724aa, 0x00000000f2455bfc }, + /* x^198656 mod p(x)` << 1, x^198720 mod p(x)` << 1 */ + { 0x000000003cd63ac4, 0x000000018c40baf4 }, + /* x^197632 mod p(x)` << 1, x^197696 mod p(x)` << 1 */ + { 0x00000001bf47d352, 0x000000004cd390d4 }, + /* x^196608 mod p(x)` << 1, x^196672 mod p(x)` << 1 */ + { 0x000000018dc1d708, 0x00000001e4ece95a }, + /* x^195584 mod p(x)` << 1, x^195648 mod p(x)` << 1 */ + { 0x000000002d4620a4, 0x000000001a3ee918 }, + /* x^194560 mod p(x)` << 1, x^194624 mod p(x)` << 1 */ + { 0x0000000058fd1740, 0x000000007c652fb8 }, + /* x^193536 mod p(x)` << 1, x^193600 mod p(x)` << 1 */ + { 0x00000000dadd9bfc, 0x000000011c67842c }, + /* x^192512 mod p(x)` << 1, x^192576 mod p(x)` << 1 */ + { 0x00000001ea2140be, 0x00000000254f759c }, + /* x^191488 mod p(x)` << 1, x^191552 mod p(x)` << 1 */ + { 0x000000009de128ba, 0x000000007ece94ca }, + /* x^190464 mod p(x)` << 1, x^190528 mod p(x)` << 1 */ + { 0x000000013ac3aa8e, 0x0000000038f258c2 }, + /* x^189440 mod p(x)` << 1, x^189504 mod p(x)` << 1 */ + { 0x0000000099980562, 0x00000001cdf17b00 }, + /* x^188416 mod p(x)` << 1, x^188480 mod p(x)` << 1 */ + { 0x00000001c1579c86, 0x000000011f882c16 }, + /* x^187392 mod p(x)` << 1, x^187456 mod p(x)` << 1 */ + { 0x0000000068dbbf94, 0x0000000100093fc8 }, + /* x^186368 mod p(x)` << 1, x^186432 mod p(x)` << 1 */ + { 0x000000004509fb04, 0x00000001cd684f16 }, + /* x^185344 mod p(x)` << 1, x^185408 mod p(x)` << 1 */ + { 0x00000001202f6398, 0x000000004bc6a70a }, + /* x^184320 mod p(x)` << 1, x^184384 mod p(x)` << 1 */ + { 0x000000013aea243e, 0x000000004fc7e8e4 }, + /* x^183296 mod p(x)` << 1, x^183360 mod p(x)` << 1 */ + { 0x00000001b4052ae6, 0x0000000130103f1c }, + /* x^182272 mod p(x)` << 1, x^182336 mod p(x)` << 1 */ + { 0x00000001cd2a0ae8, 0x0000000111b0024c }, + /* x^181248 mod p(x)` << 1, x^181312 mod p(x)` << 1 */ + { 0x00000001fe4aa8b4, 0x000000010b3079da }, + /* x^180224 mod p(x)` << 1, x^180288 mod p(x)` << 1 */ + { 0x00000001d1559a42, 0x000000010192bcc2 }, + /* x^179200 mod p(x)` << 1, x^179264 mod p(x)` << 1 */ + { 0x00000001f3e05ecc, 0x0000000074838d50 }, + /* x^178176 mod p(x)` << 1, x^178240 mod p(x)` << 1 */ + { 0x0000000104ddd2cc, 0x000000001b20f520 }, + /* x^177152 mod p(x)` << 1, x^177216 mod p(x)` << 1 */ + { 0x000000015393153c, 0x0000000050c3590a }, + /* x^176128 mod p(x)` << 1, x^176192 mod p(x)` << 1 */ + { 0x0000000057e942c6, 0x00000000b41cac8e }, + /* x^175104 mod p(x)` << 1, x^175168 mod p(x)` << 1 */ + { 0x000000012c633850, 0x000000000c72cc78 }, + /* x^174080 mod p(x)` << 1, x^174144 mod p(x)` << 1 */ + { 0x00000000ebcaae4c, 0x0000000030cdb032 }, + /* x^173056 mod p(x)` << 1, x^173120 mod p(x)` << 1 */ + { 0x000000013ee532a6, 0x000000013e09fc32 }, + /* x^172032 mod p(x)` << 1, x^172096 mod p(x)` << 1 */ + { 0x00000001bf0cbc7e, 0x000000001ed624d2 }, + /* x^171008 mod p(x)` << 1, x^171072 mod p(x)` << 1 */ + { 0x00000000d50b7a5a, 0x00000000781aee1a }, + /* x^169984 mod p(x)` << 1, x^170048 mod p(x)` << 1 */ + { 0x0000000002fca6e8, 0x00000001c4d8348c }, + /* x^168960 mod p(x)` << 1, x^169024 mod p(x)` << 1 */ + { 0x000000007af40044, 0x0000000057a40336 }, + /* x^167936 mod p(x)` << 1, x^168000 mod p(x)` << 1 */ + { 0x0000000016178744, 0x0000000085544940 }, + /* x^166912 mod p(x)` << 1, x^166976 mod p(x)` << 1 */ + { 0x000000014c177458, 0x000000019cd21e80 }, + /* x^165888 mod p(x)` << 1, x^165952 mod p(x)` << 1 */ + { 0x000000011b6ddf04, 0x000000013eb95bc0 }, + /* x^164864 mod p(x)` << 1, x^164928 mod p(x)` << 1 */ + { 0x00000001f3e29ccc, 0x00000001dfc9fdfc }, + /* x^163840 mod p(x)` << 1, x^163904 mod p(x)` << 1 */ + { 0x0000000135ae7562, 0x00000000cd028bc2 }, + /* x^162816 mod p(x)` << 1, x^162880 mod p(x)` << 1 */ + { 0x0000000190ef812c, 0x0000000090db8c44 }, + /* x^161792 mod p(x)` << 1, x^161856 mod p(x)` << 1 */ + { 0x0000000067a2c786, 0x000000010010a4ce }, + /* x^160768 mod p(x)` << 1, x^160832 mod p(x)` << 1 */ + { 0x0000000048b9496c, 0x00000001c8f4c72c }, + /* x^159744 mod p(x)` << 1, x^159808 mod p(x)` << 1 */ + { 0x000000015a422de6, 0x000000001c26170c }, + /* x^158720 mod p(x)` << 1, x^158784 mod p(x)` << 1 */ + { 0x00000001ef0e3640, 0x00000000e3fccf68 }, + /* x^157696 mod p(x)` << 1, x^157760 mod p(x)` << 1 */ + { 0x00000001006d2d26, 0x00000000d513ed24 }, + /* x^156672 mod p(x)` << 1, x^156736 mod p(x)` << 1 */ + { 0x00000001170d56d6, 0x00000000141beada }, + /* x^155648 mod p(x)` << 1, x^155712 mod p(x)` << 1 */ + { 0x00000000a5fb613c, 0x000000011071aea0 }, + /* x^154624 mod p(x)` << 1, x^154688 mod p(x)` << 1 */ + { 0x0000000040bbf7fc, 0x000000012e19080a }, + /* x^153600 mod p(x)` << 1, x^153664 mod p(x)` << 1 */ + { 0x000000016ac3a5b2, 0x0000000100ecf826 }, + /* x^152576 mod p(x)` << 1, x^152640 mod p(x)` << 1 */ + { 0x00000000abf16230, 0x0000000069b09412 }, + /* x^151552 mod p(x)` << 1, x^151616 mod p(x)` << 1 */ + { 0x00000001ebe23fac, 0x0000000122297bac }, + /* x^150528 mod p(x)` << 1, x^150592 mod p(x)` << 1 */ + { 0x000000008b6a0894, 0x00000000e9e4b068 }, + /* x^149504 mod p(x)` << 1, x^149568 mod p(x)` << 1 */ + { 0x00000001288ea478, 0x000000004b38651a }, + /* x^148480 mod p(x)` << 1, x^148544 mod p(x)` << 1 */ + { 0x000000016619c442, 0x00000001468360e2 }, + /* x^147456 mod p(x)` << 1, x^147520 mod p(x)` << 1 */ + { 0x0000000086230038, 0x00000000121c2408 }, + /* x^146432 mod p(x)` << 1, x^146496 mod p(x)` << 1 */ + { 0x000000017746a756, 0x00000000da7e7d08 }, + /* x^145408 mod p(x)` << 1, x^145472 mod p(x)` << 1 */ + { 0x0000000191b8f8f8, 0x00000001058d7652 }, + /* x^144384 mod p(x)` << 1, x^144448 mod p(x)` << 1 */ + { 0x000000008e167708, 0x000000014a098a90 }, + /* x^143360 mod p(x)` << 1, x^143424 mod p(x)` << 1 */ + { 0x0000000148b22d54, 0x0000000020dbe72e }, + /* x^142336 mod p(x)` << 1, x^142400 mod p(x)` << 1 */ + { 0x0000000044ba2c3c, 0x000000011e7323e8 }, + /* x^141312 mod p(x)` << 1, x^141376 mod p(x)` << 1 */ + { 0x00000000b54d2b52, 0x00000000d5d4bf94 }, + /* x^140288 mod p(x)` << 1, x^140352 mod p(x)` << 1 */ + { 0x0000000005a4fd8a, 0x0000000199d8746c }, + /* x^139264 mod p(x)` << 1, x^139328 mod p(x)` << 1 */ + { 0x0000000139f9fc46, 0x00000000ce9ca8a0 }, + /* x^138240 mod p(x)` << 1, x^138304 mod p(x)` << 1 */ + { 0x000000015a1fa824, 0x00000000136edece }, + /* x^137216 mod p(x)` << 1, x^137280 mod p(x)` << 1 */ + { 0x000000000a61ae4c, 0x000000019b92a068 }, + /* x^136192 mod p(x)` << 1, x^136256 mod p(x)` << 1 */ + { 0x0000000145e9113e, 0x0000000071d62206 }, + /* x^135168 mod p(x)` << 1, x^135232 mod p(x)` << 1 */ + { 0x000000006a348448, 0x00000000dfc50158 }, + /* x^134144 mod p(x)` << 1, x^134208 mod p(x)` << 1 */ + { 0x000000004d80a08c, 0x00000001517626bc }, + /* x^133120 mod p(x)` << 1, x^133184 mod p(x)` << 1 */ + { 0x000000014b6837a0, 0x0000000148d1e4fa }, + /* x^132096 mod p(x)` << 1, x^132160 mod p(x)` << 1 */ + { 0x000000016896a7fc, 0x0000000094d8266e }, + /* x^131072 mod p(x)` << 1, x^131136 mod p(x)` << 1 */ + { 0x000000014f187140, 0x00000000606c5e34 }, + /* x^130048 mod p(x)` << 1, x^130112 mod p(x)` << 1 */ + { 0x000000019581b9da, 0x000000019766beaa }, + /* x^129024 mod p(x)` << 1, x^129088 mod p(x)` << 1 */ + { 0x00000001091bc984, 0x00000001d80c506c }, + /* x^128000 mod p(x)` << 1, x^128064 mod p(x)` << 1 */ + { 0x000000001067223c, 0x000000001e73837c }, + /* x^126976 mod p(x)` << 1, x^127040 mod p(x)` << 1 */ + { 0x00000001ab16ea02, 0x0000000064d587de }, + /* x^125952 mod p(x)` << 1, x^126016 mod p(x)` << 1 */ + { 0x000000013c4598a8, 0x00000000f4a507b0 }, + /* x^124928 mod p(x)` << 1, x^124992 mod p(x)` << 1 */ + { 0x00000000b3735430, 0x0000000040e342fc }, + /* x^123904 mod p(x)` << 1, x^123968 mod p(x)` << 1 */ + { 0x00000001bb3fc0c0, 0x00000001d5ad9c3a }, + /* x^122880 mod p(x)` << 1, x^122944 mod p(x)` << 1 */ + { 0x00000001570ae19c, 0x0000000094a691a4 }, + /* x^121856 mod p(x)` << 1, x^121920 mod p(x)` << 1 */ + { 0x00000001ea910712, 0x00000001271ecdfa }, + /* x^120832 mod p(x)` << 1, x^120896 mod p(x)` << 1 */ + { 0x0000000167127128, 0x000000009e54475a }, + /* x^119808 mod p(x)` << 1, x^119872 mod p(x)` << 1 */ + { 0x0000000019e790a2, 0x00000000c9c099ee }, + /* x^118784 mod p(x)` << 1, x^118848 mod p(x)` << 1 */ + { 0x000000003788f710, 0x000000009a2f736c }, + /* x^117760 mod p(x)` << 1, x^117824 mod p(x)` << 1 */ + { 0x00000001682a160e, 0x00000000bb9f4996 }, + /* x^116736 mod p(x)` << 1, x^116800 mod p(x)` << 1 */ + { 0x000000007f0ebd2e, 0x00000001db688050 }, + /* x^115712 mod p(x)` << 1, x^115776 mod p(x)` << 1 */ + { 0x000000002b032080, 0x00000000e9b10af4 }, + /* x^114688 mod p(x)` << 1, x^114752 mod p(x)` << 1 */ + { 0x00000000cfd1664a, 0x000000012d4545e4 }, + /* x^113664 mod p(x)` << 1, x^113728 mod p(x)` << 1 */ + { 0x00000000aa1181c2, 0x000000000361139c }, + /* x^112640 mod p(x)` << 1, x^112704 mod p(x)` << 1 */ + { 0x00000000ddd08002, 0x00000001a5a1a3a8 }, + /* x^111616 mod p(x)` << 1, x^111680 mod p(x)` << 1 */ + { 0x00000000e8dd0446, 0x000000006844e0b0 }, + /* x^110592 mod p(x)` << 1, x^110656 mod p(x)` << 1 */ + { 0x00000001bbd94a00, 0x00000000c3762f28 }, + /* x^109568 mod p(x)` << 1, x^109632 mod p(x)` << 1 */ + { 0x00000000ab6cd180, 0x00000001d26287a2 }, + /* x^108544 mod p(x)` << 1, x^108608 mod p(x)` << 1 */ + { 0x0000000031803ce2, 0x00000001f6f0bba8 }, + /* x^107520 mod p(x)` << 1, x^107584 mod p(x)` << 1 */ + { 0x0000000024f40b0c, 0x000000002ffabd62 }, + /* x^106496 mod p(x)` << 1, x^106560 mod p(x)` << 1 */ + { 0x00000001ba1d9834, 0x00000000fb4516b8 }, + /* x^105472 mod p(x)` << 1, x^105536 mod p(x)` << 1 */ + { 0x0000000104de61aa, 0x000000018cfa961c }, + /* x^104448 mod p(x)` << 1, x^104512 mod p(x)` << 1 */ + { 0x0000000113e40d46, 0x000000019e588d52 }, + /* x^103424 mod p(x)` << 1, x^103488 mod p(x)` << 1 */ + { 0x00000001415598a0, 0x00000001180f0bbc }, + /* x^102400 mod p(x)` << 1, x^102464 mod p(x)` << 1 */ + { 0x00000000bf6c8c90, 0x00000000e1d9177a }, + /* x^101376 mod p(x)` << 1, x^101440 mod p(x)` << 1 */ + { 0x00000001788b0504, 0x0000000105abc27c }, + /* x^100352 mod p(x)` << 1, x^100416 mod p(x)` << 1 */ + { 0x0000000038385d02, 0x00000000972e4a58 }, + /* x^99328 mod p(x)` << 1, x^99392 mod p(x)` << 1 */ + { 0x00000001b6c83844, 0x0000000183499a5e }, + /* x^98304 mod p(x)` << 1, x^98368 mod p(x)` << 1 */ + { 0x0000000051061a8a, 0x00000001c96a8cca }, + /* x^97280 mod p(x)` << 1, x^97344 mod p(x)` << 1 */ + { 0x000000017351388a, 0x00000001a1a5b60c }, + /* x^96256 mod p(x)` << 1, x^96320 mod p(x)` << 1 */ + { 0x0000000132928f92, 0x00000000e4b6ac9c }, + /* x^95232 mod p(x)` << 1, x^95296 mod p(x)` << 1 */ + { 0x00000000e6b4f48a, 0x00000001807e7f5a }, + /* x^94208 mod p(x)` << 1, x^94272 mod p(x)` << 1 */ + { 0x0000000039d15e90, 0x000000017a7e3bc8 }, + /* x^93184 mod p(x)` << 1, x^93248 mod p(x)` << 1 */ + { 0x00000000312d6074, 0x00000000d73975da }, + /* x^92160 mod p(x)` << 1, x^92224 mod p(x)` << 1 */ + { 0x000000017bbb2cc4, 0x000000017375d038 }, + /* x^91136 mod p(x)` << 1, x^91200 mod p(x)` << 1 */ + { 0x000000016ded3e18, 0x00000000193680bc }, + /* x^90112 mod p(x)` << 1, x^90176 mod p(x)` << 1 */ + { 0x00000000f1638b16, 0x00000000999b06f6 }, + /* x^89088 mod p(x)` << 1, x^89152 mod p(x)` << 1 */ + { 0x00000001d38b9ecc, 0x00000001f685d2b8 }, + /* x^88064 mod p(x)` << 1, x^88128 mod p(x)` << 1 */ + { 0x000000018b8d09dc, 0x00000001f4ecbed2 }, + /* x^87040 mod p(x)` << 1, x^87104 mod p(x)` << 1 */ + { 0x00000000e7bc27d2, 0x00000000ba16f1a0 }, + /* x^86016 mod p(x)` << 1, x^86080 mod p(x)` << 1 */ + { 0x00000000275e1e96, 0x0000000115aceac4 }, + /* x^84992 mod p(x)` << 1, x^85056 mod p(x)` << 1 */ + { 0x00000000e2e3031e, 0x00000001aeff6292 }, + /* x^83968 mod p(x)` << 1, x^84032 mod p(x)` << 1 */ + { 0x00000001041c84d8, 0x000000009640124c }, + /* x^82944 mod p(x)` << 1, x^83008 mod p(x)` << 1 */ + { 0x00000000706ce672, 0x0000000114f41f02 }, + /* x^81920 mod p(x)` << 1, x^81984 mod p(x)` << 1 */ + { 0x000000015d5070da, 0x000000009c5f3586 }, + /* x^80896 mod p(x)` << 1, x^80960 mod p(x)` << 1 */ + { 0x0000000038f9493a, 0x00000001878275fa }, + /* x^79872 mod p(x)` << 1, x^79936 mod p(x)` << 1 */ + { 0x00000000a3348a76, 0x00000000ddc42ce8 }, + /* x^78848 mod p(x)` << 1, x^78912 mod p(x)` << 1 */ + { 0x00000001ad0aab92, 0x0000000181d2c73a }, + /* x^77824 mod p(x)` << 1, x^77888 mod p(x)` << 1 */ + { 0x000000019e85f712, 0x0000000141c9320a }, + /* x^76800 mod p(x)` << 1, x^76864 mod p(x)` << 1 */ + { 0x000000005a871e76, 0x000000015235719a }, + /* x^75776 mod p(x)` << 1, x^75840 mod p(x)` << 1 */ + { 0x000000017249c662, 0x00000000be27d804 }, + /* x^74752 mod p(x)` << 1, x^74816 mod p(x)` << 1 */ + { 0x000000003a084712, 0x000000006242d45a }, + /* x^73728 mod p(x)` << 1, x^73792 mod p(x)` << 1 */ + { 0x00000000ed438478, 0x000000009a53638e }, + /* x^72704 mod p(x)` << 1, x^72768 mod p(x)` << 1 */ + { 0x00000000abac34cc, 0x00000001001ecfb6 }, + /* x^71680 mod p(x)` << 1, x^71744 mod p(x)` << 1 */ + { 0x000000005f35ef3e, 0x000000016d7c2d64 }, + /* x^70656 mod p(x)` << 1, x^70720 mod p(x)` << 1 */ + { 0x0000000047d6608c, 0x00000001d0ce46c0 }, + /* x^69632 mod p(x)` << 1, x^69696 mod p(x)` << 1 */ + { 0x000000002d01470e, 0x0000000124c907b4 }, + /* x^68608 mod p(x)` << 1, x^68672 mod p(x)` << 1 */ + { 0x0000000158bbc7b0, 0x0000000018a555ca }, + /* x^67584 mod p(x)` << 1, x^67648 mod p(x)` << 1 */ + { 0x00000000c0a23e8e, 0x000000006b0980bc }, + /* x^66560 mod p(x)` << 1, x^66624 mod p(x)` << 1 */ + { 0x00000001ebd85c88, 0x000000008bbba964 }, + /* x^65536 mod p(x)` << 1, x^65600 mod p(x)` << 1 */ + { 0x000000019ee20bb2, 0x00000001070a5a1e }, + /* x^64512 mod p(x)` << 1, x^64576 mod p(x)` << 1 */ + { 0x00000001acabf2d6, 0x000000002204322a }, + /* x^63488 mod p(x)` << 1, x^63552 mod p(x)` << 1 */ + { 0x00000001b7963d56, 0x00000000a27524d0 }, + /* x^62464 mod p(x)` << 1, x^62528 mod p(x)` << 1 */ + { 0x000000017bffa1fe, 0x0000000020b1e4ba }, + /* x^61440 mod p(x)` << 1, x^61504 mod p(x)` << 1 */ + { 0x000000001f15333e, 0x0000000032cc27fc }, + /* x^60416 mod p(x)` << 1, x^60480 mod p(x)` << 1 */ + { 0x000000018593129e, 0x0000000044dd22b8 }, + /* x^59392 mod p(x)` << 1, x^59456 mod p(x)` << 1 */ + { 0x000000019cb32602, 0x00000000dffc9e0a }, + /* x^58368 mod p(x)` << 1, x^58432 mod p(x)` << 1 */ + { 0x0000000142b05cc8, 0x00000001b7a0ed14 }, + /* x^57344 mod p(x)` << 1, x^57408 mod p(x)` << 1 */ + { 0x00000001be49e7a4, 0x00000000c7842488 }, + /* x^56320 mod p(x)` << 1, x^56384 mod p(x)` << 1 */ + { 0x0000000108f69d6c, 0x00000001c02a4fee }, + /* x^55296 mod p(x)` << 1, x^55360 mod p(x)` << 1 */ + { 0x000000006c0971f0, 0x000000003c273778 }, + /* x^54272 mod p(x)` << 1, x^54336 mod p(x)` << 1 */ + { 0x000000005b16467a, 0x00000001d63f8894 }, + /* x^53248 mod p(x)` << 1, x^53312 mod p(x)` << 1 */ + { 0x00000001551a628e, 0x000000006be557d6 }, + /* x^52224 mod p(x)` << 1, x^52288 mod p(x)` << 1 */ + { 0x000000019e42ea92, 0x000000006a7806ea }, + /* x^51200 mod p(x)` << 1, x^51264 mod p(x)` << 1 */ + { 0x000000012fa83ff2, 0x000000016155aa0c }, + /* x^50176 mod p(x)` << 1, x^50240 mod p(x)` << 1 */ + { 0x000000011ca9cde0, 0x00000000908650ac }, + /* x^49152 mod p(x)` << 1, x^49216 mod p(x)` << 1 */ + { 0x00000000c8e5cd74, 0x00000000aa5a8084 }, + /* x^48128 mod p(x)` << 1, x^48192 mod p(x)` << 1 */ + { 0x0000000096c27f0c, 0x0000000191bb500a }, + /* x^47104 mod p(x)` << 1, x^47168 mod p(x)` << 1 */ + { 0x000000002baed926, 0x0000000064e9bed0 }, + /* x^46080 mod p(x)` << 1, x^46144 mod p(x)` << 1 */ + { 0x000000017c8de8d2, 0x000000009444f302 }, + /* x^45056 mod p(x)` << 1, x^45120 mod p(x)` << 1 */ + { 0x00000000d43d6068, 0x000000019db07d3c }, + /* x^44032 mod p(x)` << 1, x^44096 mod p(x)` << 1 */ + { 0x00000000cb2c4b26, 0x00000001359e3e6e }, + /* x^43008 mod p(x)` << 1, x^43072 mod p(x)` << 1 */ + { 0x0000000145b8da26, 0x00000001e4f10dd2 }, + /* x^41984 mod p(x)` << 1, x^42048 mod p(x)` << 1 */ + { 0x000000018fff4b08, 0x0000000124f5735e }, + /* x^40960 mod p(x)` << 1, x^41024 mod p(x)` << 1 */ + { 0x0000000150b58ed0, 0x0000000124760a4c }, + /* x^39936 mod p(x)` << 1, x^40000 mod p(x)` << 1 */ + { 0x00000001549f39bc, 0x000000000f1fc186 }, + /* x^38912 mod p(x)` << 1, x^38976 mod p(x)` << 1 */ + { 0x00000000ef4d2f42, 0x00000000150e4cc4 }, + /* x^37888 mod p(x)` << 1, x^37952 mod p(x)` << 1 */ + { 0x00000001b1468572, 0x000000002a6204e8 }, + /* x^36864 mod p(x)` << 1, x^36928 mod p(x)` << 1 */ + { 0x000000013d7403b2, 0x00000000beb1d432 }, + /* x^35840 mod p(x)` << 1, x^35904 mod p(x)` << 1 */ + { 0x00000001a4681842, 0x0000000135f3f1f0 }, + /* x^34816 mod p(x)` << 1, x^34880 mod p(x)` << 1 */ + { 0x0000000167714492, 0x0000000074fe2232 }, + /* x^33792 mod p(x)` << 1, x^33856 mod p(x)` << 1 */ + { 0x00000001e599099a, 0x000000001ac6e2ba }, + /* x^32768 mod p(x)` << 1, x^32832 mod p(x)` << 1 */ + { 0x00000000fe128194, 0x0000000013fca91e }, + /* x^31744 mod p(x)` << 1, x^31808 mod p(x)` << 1 */ + { 0x0000000077e8b990, 0x0000000183f4931e }, + /* x^30720 mod p(x)` << 1, x^30784 mod p(x)` << 1 */ + { 0x00000001a267f63a, 0x00000000b6d9b4e4 }, + /* x^29696 mod p(x)` << 1, x^29760 mod p(x)` << 1 */ + { 0x00000001945c245a, 0x00000000b5188656 }, + /* x^28672 mod p(x)` << 1, x^28736 mod p(x)` << 1 */ + { 0x0000000149002e76, 0x0000000027a81a84 }, + /* x^27648 mod p(x)` << 1, x^27712 mod p(x)` << 1 */ + { 0x00000001bb8310a4, 0x0000000125699258 }, + /* x^26624 mod p(x)` << 1, x^26688 mod p(x)` << 1 */ + { 0x000000019ec60bcc, 0x00000001b23de796 }, + /* x^25600 mod p(x)` << 1, x^25664 mod p(x)` << 1 */ + { 0x000000012d8590ae, 0x00000000fe4365dc }, + /* x^24576 mod p(x)` << 1, x^24640 mod p(x)` << 1 */ + { 0x0000000065b00684, 0x00000000c68f497a }, + /* x^23552 mod p(x)` << 1, x^23616 mod p(x)` << 1 */ + { 0x000000015e5aeadc, 0x00000000fbf521ee }, + /* x^22528 mod p(x)` << 1, x^22592 mod p(x)` << 1 */ + { 0x00000000b77ff2b0, 0x000000015eac3378 }, + /* x^21504 mod p(x)` << 1, x^21568 mod p(x)` << 1 */ + { 0x0000000188da2ff6, 0x0000000134914b90 }, + /* x^20480 mod p(x)` << 1, x^20544 mod p(x)` << 1 */ + { 0x0000000063da929a, 0x0000000016335cfe }, + /* x^19456 mod p(x)` << 1, x^19520 mod p(x)` << 1 */ + { 0x00000001389caa80, 0x000000010372d10c }, + /* x^18432 mod p(x)` << 1, x^18496 mod p(x)` << 1 */ + { 0x000000013db599d2, 0x000000015097b908 }, + /* x^17408 mod p(x)` << 1, x^17472 mod p(x)` << 1 */ + { 0x0000000122505a86, 0x00000001227a7572 }, + /* x^16384 mod p(x)` << 1, x^16448 mod p(x)` << 1 */ + { 0x000000016bd72746, 0x000000009a8f75c0 }, + /* x^15360 mod p(x)` << 1, x^15424 mod p(x)` << 1 */ + { 0x00000001c3faf1d4, 0x00000000682c77a2 }, + /* x^14336 mod p(x)` << 1, x^14400 mod p(x)` << 1 */ + { 0x00000001111c826c, 0x00000000231f091c }, + /* x^13312 mod p(x)` << 1, x^13376 mod p(x)` << 1 */ + { 0x00000000153e9fb2, 0x000000007d4439f2 }, + /* x^12288 mod p(x)` << 1, x^12352 mod p(x)` << 1 */ + { 0x000000002b1f7b60, 0x000000017e221efc }, + /* x^11264 mod p(x)` << 1, x^11328 mod p(x)` << 1 */ + { 0x00000000b1dba570, 0x0000000167457c38 }, + /* x^10240 mod p(x)` << 1, x^10304 mod p(x)` << 1 */ + { 0x00000001f6397b76, 0x00000000bdf081c4 }, + /* x^9216 mod p(x)` << 1, x^9280 mod p(x)` << 1 */ + { 0x0000000156335214, 0x000000016286d6b0 }, + /* x^8192 mod p(x)` << 1, x^8256 mod p(x)` << 1 */ + { 0x00000001d70e3986, 0x00000000c84f001c }, + /* x^7168 mod p(x)` << 1, x^7232 mod p(x)` << 1 */ + { 0x000000003701a774, 0x0000000064efe7c0 }, + /* x^6144 mod p(x)` << 1, x^6208 mod p(x)` << 1 */ + { 0x00000000ac81ef72, 0x000000000ac2d904 }, + /* x^5120 mod p(x)` << 1, x^5184 mod p(x)` << 1 */ + { 0x0000000133212464, 0x00000000fd226d14 }, + /* x^4096 mod p(x)` << 1, x^4160 mod p(x)` << 1 */ + { 0x00000000e4e45610, 0x000000011cfd42e0 }, + /* x^3072 mod p(x)` << 1, x^3136 mod p(x)` << 1 */ + { 0x000000000c1bd370, 0x000000016e5a5678 }, + /* x^2048 mod p(x)` << 1, x^2112 mod p(x)` << 1 */ + { 0x00000001a7b9e7a6, 0x00000001d888fe22 }, + /* x^1024 mod p(x)` << 1, x^1088 mod p(x)` << 1 */ + { 0x000000007d657a10, 0x00000001af77fcd4 } +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* x^261120 mod p(x)` << 1, x^261184 mod p(x)` << 1 */ + { 0x00000001651797d2, 0x0000000099ea94a8 }, + /* x^260096 mod p(x)` << 1, x^260160 mod p(x)` << 1 */ + { 0x0000000021e0d56c, 0x00000000945a8420 }, + /* x^259072 mod p(x)` << 1, x^259136 mod p(x)` << 1 */ + { 0x000000000f95ecaa, 0x0000000030762706 }, + /* x^258048 mod p(x)` << 1, x^258112 mod p(x)` << 1 */ + { 0x00000001ebd224ac, 0x00000001a52fc582 }, + /* x^257024 mod p(x)` << 1, x^257088 mod p(x)` << 1 */ + { 0x000000000ccb97ca, 0x00000001a4a7167a }, + /* x^256000 mod p(x)` << 1, x^256064 mod p(x)` << 1 */ + { 0x00000001006ec8a8, 0x000000000c18249a }, + /* x^254976 mod p(x)` << 1, x^255040 mod p(x)` << 1 */ + { 0x000000014f58f196, 0x00000000a924ae7c }, + /* x^253952 mod p(x)` << 1, x^254016 mod p(x)` << 1 */ + { 0x00000001a7192ca6, 0x00000001e12ccc12 }, + /* x^252928 mod p(x)` << 1, x^252992 mod p(x)` << 1 */ + { 0x000000019a64bab2, 0x00000000a0b9d4ac }, + /* x^251904 mod p(x)` << 1, x^251968 mod p(x)` << 1 */ + { 0x0000000014f4ed2e, 0x0000000095e8ddfe }, + /* x^250880 mod p(x)` << 1, x^250944 mod p(x)` << 1 */ + { 0x000000011092b6a2, 0x00000000233fddc4 }, + /* x^249856 mod p(x)` << 1, x^249920 mod p(x)` << 1 */ + { 0x00000000c8a1629c, 0x00000001b4529b62 }, + /* x^248832 mod p(x)` << 1, x^248896 mod p(x)` << 1 */ + { 0x000000017bf32e8e, 0x00000001a7fa0e64 }, + /* x^247808 mod p(x)` << 1, x^247872 mod p(x)` << 1 */ + { 0x00000001f8cc6582, 0x00000001b5334592 }, + /* x^246784 mod p(x)` << 1, x^246848 mod p(x)` << 1 */ + { 0x000000008631ddf0, 0x000000011f8ee1b4 }, + /* x^245760 mod p(x)` << 1, x^245824 mod p(x)` << 1 */ + { 0x000000007e5a76d0, 0x000000006252e632 }, + /* x^244736 mod p(x)` << 1, x^244800 mod p(x)` << 1 */ + { 0x000000002b09b31c, 0x00000000ab973e84 }, + /* x^243712 mod p(x)` << 1, x^243776 mod p(x)` << 1 */ + { 0x00000001b2df1f84, 0x000000007734f5ec }, + /* x^242688 mod p(x)` << 1, x^242752 mod p(x)` << 1 */ + { 0x00000001d6f56afc, 0x000000007c547798 }, + /* x^241664 mod p(x)` << 1, x^241728 mod p(x)` << 1 */ + { 0x00000001b9b5e70c, 0x000000007ec40210 }, + /* x^240640 mod p(x)` << 1, x^240704 mod p(x)` << 1 */ + { 0x0000000034b626d2, 0x00000001ab1695a8 }, + /* x^239616 mod p(x)` << 1, x^239680 mod p(x)` << 1 */ + { 0x000000014c53479a, 0x0000000090494bba }, + /* x^238592 mod p(x)` << 1, x^238656 mod p(x)` << 1 */ + { 0x00000001a6d179a4, 0x00000001123fb816 }, + /* x^237568 mod p(x)` << 1, x^237632 mod p(x)` << 1 */ + { 0x000000015abd16b4, 0x00000001e188c74c }, + /* x^236544 mod p(x)` << 1, x^236608 mod p(x)` << 1 */ + { 0x00000000018f9852, 0x00000001c2d3451c }, + /* x^235520 mod p(x)` << 1, x^235584 mod p(x)` << 1 */ + { 0x000000001fb3084a, 0x00000000f55cf1ca }, + /* x^234496 mod p(x)` << 1, x^234560 mod p(x)` << 1 */ + { 0x00000000c53dfb04, 0x00000001a0531540 }, + /* x^233472 mod p(x)` << 1, x^233536 mod p(x)` << 1 */ + { 0x00000000e10c9ad6, 0x0000000132cd7ebc }, + /* x^232448 mod p(x)` << 1, x^232512 mod p(x)` << 1 */ + { 0x0000000025aa994a, 0x0000000073ab7f36 }, + /* x^231424 mod p(x)` << 1, x^231488 mod p(x)` << 1 */ + { 0x00000000fa3a74c4, 0x0000000041aed1c2 }, + /* x^230400 mod p(x)` << 1, x^230464 mod p(x)` << 1 */ + { 0x0000000033eb3f40, 0x0000000136c53800 }, + /* x^229376 mod p(x)` << 1, x^229440 mod p(x)` << 1 */ + { 0x000000017193f296, 0x0000000126835a30 }, + /* x^228352 mod p(x)` << 1, x^228416 mod p(x)` << 1 */ + { 0x0000000043f6c86a, 0x000000006241b502 }, + /* x^227328 mod p(x)` << 1, x^227392 mod p(x)` << 1 */ + { 0x000000016b513ec6, 0x00000000d5196ad4 }, + /* x^226304 mod p(x)` << 1, x^226368 mod p(x)` << 1 */ + { 0x00000000c8f25b4e, 0x000000009cfa769a }, + /* x^225280 mod p(x)` << 1, x^225344 mod p(x)` << 1 */ + { 0x00000001a45048ec, 0x00000000920e5df4 }, + /* x^224256 mod p(x)` << 1, x^224320 mod p(x)` << 1 */ + { 0x000000000c441004, 0x0000000169dc310e }, + /* x^223232 mod p(x)` << 1, x^223296 mod p(x)` << 1 */ + { 0x000000000e17cad6, 0x0000000009fc331c }, + /* x^222208 mod p(x)` << 1, x^222272 mod p(x)` << 1 */ + { 0x00000001253ae964, 0x000000010d94a81e }, + /* x^221184 mod p(x)` << 1, x^221248 mod p(x)` << 1 */ + { 0x00000001d7c88ebc, 0x0000000027a20ab2 }, + /* x^220160 mod p(x)` << 1, x^220224 mod p(x)` << 1 */ + { 0x00000001e7ca913a, 0x0000000114f87504 }, + /* x^219136 mod p(x)` << 1, x^219200 mod p(x)` << 1 */ + { 0x0000000033ed078a, 0x000000004b076d96 }, + /* x^218112 mod p(x)` << 1, x^218176 mod p(x)` << 1 */ + { 0x00000000e1839c78, 0x00000000da4d1e74 }, + /* x^217088 mod p(x)` << 1, x^217152 mod p(x)` << 1 */ + { 0x00000001322b267e, 0x000000001b81f672 }, + /* x^216064 mod p(x)` << 1, x^216128 mod p(x)` << 1 */ + { 0x00000000638231b6, 0x000000009367c988 }, + /* x^215040 mod p(x)` << 1, x^215104 mod p(x)` << 1 */ + { 0x00000001ee7f16f4, 0x00000001717214ca }, + /* x^214016 mod p(x)` << 1, x^214080 mod p(x)` << 1 */ + { 0x0000000117d9924a, 0x000000009f47d820 }, + /* x^212992 mod p(x)` << 1, x^213056 mod p(x)` << 1 */ + { 0x00000000e1a9e0c4, 0x000000010d9a47d2 }, + /* x^211968 mod p(x)` << 1, x^212032 mod p(x)` << 1 */ + { 0x00000001403731dc, 0x00000000a696c58c }, + /* x^210944 mod p(x)` << 1, x^211008 mod p(x)` << 1 */ + { 0x00000001a5ea9682, 0x000000002aa28ec6 }, + /* x^209920 mod p(x)` << 1, x^209984 mod p(x)` << 1 */ + { 0x0000000101c5c578, 0x00000001fe18fd9a }, + /* x^208896 mod p(x)` << 1, x^208960 mod p(x)` << 1 */ + { 0x00000000dddf6494, 0x000000019d4fc1ae }, + /* x^207872 mod p(x)` << 1, x^207936 mod p(x)` << 1 */ + { 0x00000000f1c3db28, 0x00000001ba0e3dea }, + /* x^206848 mod p(x)` << 1, x^206912 mod p(x)` << 1 */ + { 0x000000013112fb9c, 0x0000000074b59a5e }, + /* x^205824 mod p(x)` << 1, x^205888 mod p(x)` << 1 */ + { 0x00000000b680b906, 0x00000000f2b5ea98 }, + /* x^204800 mod p(x)` << 1, x^204864 mod p(x)` << 1 */ + { 0x000000001a282932, 0x0000000187132676 }, + /* x^203776 mod p(x)` << 1, x^203840 mod p(x)` << 1 */ + { 0x0000000089406e7e, 0x000000010a8c6ad4 }, + /* x^202752 mod p(x)` << 1, x^202816 mod p(x)` << 1 */ + { 0x00000001def6be8c, 0x00000001e21dfe70 }, + /* x^201728 mod p(x)` << 1, x^201792 mod p(x)` << 1 */ + { 0x0000000075258728, 0x00000001da0050e4 }, + /* x^200704 mod p(x)` << 1, x^200768 mod p(x)` << 1 */ + { 0x000000019536090a, 0x00000000772172ae }, + /* x^199680 mod p(x)` << 1, x^199744 mod p(x)` << 1 */ + { 0x00000000f2455bfc, 0x00000000e47724aa }, + /* x^198656 mod p(x)` << 1, x^198720 mod p(x)` << 1 */ + { 0x000000018c40baf4, 0x000000003cd63ac4 }, + /* x^197632 mod p(x)` << 1, x^197696 mod p(x)` << 1 */ + { 0x000000004cd390d4, 0x00000001bf47d352 }, + /* x^196608 mod p(x)` << 1, x^196672 mod p(x)` << 1 */ + { 0x00000001e4ece95a, 0x000000018dc1d708 }, + /* x^195584 mod p(x)` << 1, x^195648 mod p(x)` << 1 */ + { 0x000000001a3ee918, 0x000000002d4620a4 }, + /* x^194560 mod p(x)` << 1, x^194624 mod p(x)` << 1 */ + { 0x000000007c652fb8, 0x0000000058fd1740 }, + /* x^193536 mod p(x)` << 1, x^193600 mod p(x)` << 1 */ + { 0x000000011c67842c, 0x00000000dadd9bfc }, + /* x^192512 mod p(x)` << 1, x^192576 mod p(x)` << 1 */ + { 0x00000000254f759c, 0x00000001ea2140be }, + /* x^191488 mod p(x)` << 1, x^191552 mod p(x)` << 1 */ + { 0x000000007ece94ca, 0x000000009de128ba }, + /* x^190464 mod p(x)` << 1, x^190528 mod p(x)` << 1 */ + { 0x0000000038f258c2, 0x000000013ac3aa8e }, + /* x^189440 mod p(x)` << 1, x^189504 mod p(x)` << 1 */ + { 0x00000001cdf17b00, 0x0000000099980562 }, + /* x^188416 mod p(x)` << 1, x^188480 mod p(x)` << 1 */ + { 0x000000011f882c16, 0x00000001c1579c86 }, + /* x^187392 mod p(x)` << 1, x^187456 mod p(x)` << 1 */ + { 0x0000000100093fc8, 0x0000000068dbbf94 }, + /* x^186368 mod p(x)` << 1, x^186432 mod p(x)` << 1 */ + { 0x00000001cd684f16, 0x000000004509fb04 }, + /* x^185344 mod p(x)` << 1, x^185408 mod p(x)` << 1 */ + { 0x000000004bc6a70a, 0x00000001202f6398 }, + /* x^184320 mod p(x)` << 1, x^184384 mod p(x)` << 1 */ + { 0x000000004fc7e8e4, 0x000000013aea243e }, + /* x^183296 mod p(x)` << 1, x^183360 mod p(x)` << 1 */ + { 0x0000000130103f1c, 0x00000001b4052ae6 }, + /* x^182272 mod p(x)` << 1, x^182336 mod p(x)` << 1 */ + { 0x0000000111b0024c, 0x00000001cd2a0ae8 }, + /* x^181248 mod p(x)` << 1, x^181312 mod p(x)` << 1 */ + { 0x000000010b3079da, 0x00000001fe4aa8b4 }, + /* x^180224 mod p(x)` << 1, x^180288 mod p(x)` << 1 */ + { 0x000000010192bcc2, 0x00000001d1559a42 }, + /* x^179200 mod p(x)` << 1, x^179264 mod p(x)` << 1 */ + { 0x0000000074838d50, 0x00000001f3e05ecc }, + /* x^178176 mod p(x)` << 1, x^178240 mod p(x)` << 1 */ + { 0x000000001b20f520, 0x0000000104ddd2cc }, + /* x^177152 mod p(x)` << 1, x^177216 mod p(x)` << 1 */ + { 0x0000000050c3590a, 0x000000015393153c }, + /* x^176128 mod p(x)` << 1, x^176192 mod p(x)` << 1 */ + { 0x00000000b41cac8e, 0x0000000057e942c6 }, + /* x^175104 mod p(x)` << 1, x^175168 mod p(x)` << 1 */ + { 0x000000000c72cc78, 0x000000012c633850 }, + /* x^174080 mod p(x)` << 1, x^174144 mod p(x)` << 1 */ + { 0x0000000030cdb032, 0x00000000ebcaae4c }, + /* x^173056 mod p(x)` << 1, x^173120 mod p(x)` << 1 */ + { 0x000000013e09fc32, 0x000000013ee532a6 }, + /* x^172032 mod p(x)` << 1, x^172096 mod p(x)` << 1 */ + { 0x000000001ed624d2, 0x00000001bf0cbc7e }, + /* x^171008 mod p(x)` << 1, x^171072 mod p(x)` << 1 */ + { 0x00000000781aee1a, 0x00000000d50b7a5a }, + /* x^169984 mod p(x)` << 1, x^170048 mod p(x)` << 1 */ + { 0x00000001c4d8348c, 0x0000000002fca6e8 }, + /* x^168960 mod p(x)` << 1, x^169024 mod p(x)` << 1 */ + { 0x0000000057a40336, 0x000000007af40044 }, + /* x^167936 mod p(x)` << 1, x^168000 mod p(x)` << 1 */ + { 0x0000000085544940, 0x0000000016178744 }, + /* x^166912 mod p(x)` << 1, x^166976 mod p(x)` << 1 */ + { 0x000000019cd21e80, 0x000000014c177458 }, + /* x^165888 mod p(x)` << 1, x^165952 mod p(x)` << 1 */ + { 0x000000013eb95bc0, 0x000000011b6ddf04 }, + /* x^164864 mod p(x)` << 1, x^164928 mod p(x)` << 1 */ + { 0x00000001dfc9fdfc, 0x00000001f3e29ccc }, + /* x^163840 mod p(x)` << 1, x^163904 mod p(x)` << 1 */ + { 0x00000000cd028bc2, 0x0000000135ae7562 }, + /* x^162816 mod p(x)` << 1, x^162880 mod p(x)` << 1 */ + { 0x0000000090db8c44, 0x0000000190ef812c }, + /* x^161792 mod p(x)` << 1, x^161856 mod p(x)` << 1 */ + { 0x000000010010a4ce, 0x0000000067a2c786 }, + /* x^160768 mod p(x)` << 1, x^160832 mod p(x)` << 1 */ + { 0x00000001c8f4c72c, 0x0000000048b9496c }, + /* x^159744 mod p(x)` << 1, x^159808 mod p(x)` << 1 */ + { 0x000000001c26170c, 0x000000015a422de6 }, + /* x^158720 mod p(x)` << 1, x^158784 mod p(x)` << 1 */ + { 0x00000000e3fccf68, 0x00000001ef0e3640 }, + /* x^157696 mod p(x)` << 1, x^157760 mod p(x)` << 1 */ + { 0x00000000d513ed24, 0x00000001006d2d26 }, + /* x^156672 mod p(x)` << 1, x^156736 mod p(x)` << 1 */ + { 0x00000000141beada, 0x00000001170d56d6 }, + /* x^155648 mod p(x)` << 1, x^155712 mod p(x)` << 1 */ + { 0x000000011071aea0, 0x00000000a5fb613c }, + /* x^154624 mod p(x)` << 1, x^154688 mod p(x)` << 1 */ + { 0x000000012e19080a, 0x0000000040bbf7fc }, + /* x^153600 mod p(x)` << 1, x^153664 mod p(x)` << 1 */ + { 0x0000000100ecf826, 0x000000016ac3a5b2 }, + /* x^152576 mod p(x)` << 1, x^152640 mod p(x)` << 1 */ + { 0x0000000069b09412, 0x00000000abf16230 }, + /* x^151552 mod p(x)` << 1, x^151616 mod p(x)` << 1 */ + { 0x0000000122297bac, 0x00000001ebe23fac }, + /* x^150528 mod p(x)` << 1, x^150592 mod p(x)` << 1 */ + { 0x00000000e9e4b068, 0x000000008b6a0894 }, + /* x^149504 mod p(x)` << 1, x^149568 mod p(x)` << 1 */ + { 0x000000004b38651a, 0x00000001288ea478 }, + /* x^148480 mod p(x)` << 1, x^148544 mod p(x)` << 1 */ + { 0x00000001468360e2, 0x000000016619c442 }, + /* x^147456 mod p(x)` << 1, x^147520 mod p(x)` << 1 */ + { 0x00000000121c2408, 0x0000000086230038 }, + /* x^146432 mod p(x)` << 1, x^146496 mod p(x)` << 1 */ + { 0x00000000da7e7d08, 0x000000017746a756 }, + /* x^145408 mod p(x)` << 1, x^145472 mod p(x)` << 1 */ + { 0x00000001058d7652, 0x0000000191b8f8f8 }, + /* x^144384 mod p(x)` << 1, x^144448 mod p(x)` << 1 */ + { 0x000000014a098a90, 0x000000008e167708 }, + /* x^143360 mod p(x)` << 1, x^143424 mod p(x)` << 1 */ + { 0x0000000020dbe72e, 0x0000000148b22d54 }, + /* x^142336 mod p(x)` << 1, x^142400 mod p(x)` << 1 */ + { 0x000000011e7323e8, 0x0000000044ba2c3c }, + /* x^141312 mod p(x)` << 1, x^141376 mod p(x)` << 1 */ + { 0x00000000d5d4bf94, 0x00000000b54d2b52 }, + /* x^140288 mod p(x)` << 1, x^140352 mod p(x)` << 1 */ + { 0x0000000199d8746c, 0x0000000005a4fd8a }, + /* x^139264 mod p(x)` << 1, x^139328 mod p(x)` << 1 */ + { 0x00000000ce9ca8a0, 0x0000000139f9fc46 }, + /* x^138240 mod p(x)` << 1, x^138304 mod p(x)` << 1 */ + { 0x00000000136edece, 0x000000015a1fa824 }, + /* x^137216 mod p(x)` << 1, x^137280 mod p(x)` << 1 */ + { 0x000000019b92a068, 0x000000000a61ae4c }, + /* x^136192 mod p(x)` << 1, x^136256 mod p(x)` << 1 */ + { 0x0000000071d62206, 0x0000000145e9113e }, + /* x^135168 mod p(x)` << 1, x^135232 mod p(x)` << 1 */ + { 0x00000000dfc50158, 0x000000006a348448 }, + /* x^134144 mod p(x)` << 1, x^134208 mod p(x)` << 1 */ + { 0x00000001517626bc, 0x000000004d80a08c }, + /* x^133120 mod p(x)` << 1, x^133184 mod p(x)` << 1 */ + { 0x0000000148d1e4fa, 0x000000014b6837a0 }, + /* x^132096 mod p(x)` << 1, x^132160 mod p(x)` << 1 */ + { 0x0000000094d8266e, 0x000000016896a7fc }, + /* x^131072 mod p(x)` << 1, x^131136 mod p(x)` << 1 */ + { 0x00000000606c5e34, 0x000000014f187140 }, + /* x^130048 mod p(x)` << 1, x^130112 mod p(x)` << 1 */ + { 0x000000019766beaa, 0x000000019581b9da }, + /* x^129024 mod p(x)` << 1, x^129088 mod p(x)` << 1 */ + { 0x00000001d80c506c, 0x00000001091bc984 }, + /* x^128000 mod p(x)` << 1, x^128064 mod p(x)` << 1 */ + { 0x000000001e73837c, 0x000000001067223c }, + /* x^126976 mod p(x)` << 1, x^127040 mod p(x)` << 1 */ + { 0x0000000064d587de, 0x00000001ab16ea02 }, + /* x^125952 mod p(x)` << 1, x^126016 mod p(x)` << 1 */ + { 0x00000000f4a507b0, 0x000000013c4598a8 }, + /* x^124928 mod p(x)` << 1, x^124992 mod p(x)` << 1 */ + { 0x0000000040e342fc, 0x00000000b3735430 }, + /* x^123904 mod p(x)` << 1, x^123968 mod p(x)` << 1 */ + { 0x00000001d5ad9c3a, 0x00000001bb3fc0c0 }, + /* x^122880 mod p(x)` << 1, x^122944 mod p(x)` << 1 */ + { 0x0000000094a691a4, 0x00000001570ae19c }, + /* x^121856 mod p(x)` << 1, x^121920 mod p(x)` << 1 */ + { 0x00000001271ecdfa, 0x00000001ea910712 }, + /* x^120832 mod p(x)` << 1, x^120896 mod p(x)` << 1 */ + { 0x000000009e54475a, 0x0000000167127128 }, + /* x^119808 mod p(x)` << 1, x^119872 mod p(x)` << 1 */ + { 0x00000000c9c099ee, 0x0000000019e790a2 }, + /* x^118784 mod p(x)` << 1, x^118848 mod p(x)` << 1 */ + { 0x000000009a2f736c, 0x000000003788f710 }, + /* x^117760 mod p(x)` << 1, x^117824 mod p(x)` << 1 */ + { 0x00000000bb9f4996, 0x00000001682a160e }, + /* x^116736 mod p(x)` << 1, x^116800 mod p(x)` << 1 */ + { 0x00000001db688050, 0x000000007f0ebd2e }, + /* x^115712 mod p(x)` << 1, x^115776 mod p(x)` << 1 */ + { 0x00000000e9b10af4, 0x000000002b032080 }, + /* x^114688 mod p(x)` << 1, x^114752 mod p(x)` << 1 */ + { 0x000000012d4545e4, 0x00000000cfd1664a }, + /* x^113664 mod p(x)` << 1, x^113728 mod p(x)` << 1 */ + { 0x000000000361139c, 0x00000000aa1181c2 }, + /* x^112640 mod p(x)` << 1, x^112704 mod p(x)` << 1 */ + { 0x00000001a5a1a3a8, 0x00000000ddd08002 }, + /* x^111616 mod p(x)` << 1, x^111680 mod p(x)` << 1 */ + { 0x000000006844e0b0, 0x00000000e8dd0446 }, + /* x^110592 mod p(x)` << 1, x^110656 mod p(x)` << 1 */ + { 0x00000000c3762f28, 0x00000001bbd94a00 }, + /* x^109568 mod p(x)` << 1, x^109632 mod p(x)` << 1 */ + { 0x00000001d26287a2, 0x00000000ab6cd180 }, + /* x^108544 mod p(x)` << 1, x^108608 mod p(x)` << 1 */ + { 0x00000001f6f0bba8, 0x0000000031803ce2 }, + /* x^107520 mod p(x)` << 1, x^107584 mod p(x)` << 1 */ + { 0x000000002ffabd62, 0x0000000024f40b0c }, + /* x^106496 mod p(x)` << 1, x^106560 mod p(x)` << 1 */ + { 0x00000000fb4516b8, 0x00000001ba1d9834 }, + /* x^105472 mod p(x)` << 1, x^105536 mod p(x)` << 1 */ + { 0x000000018cfa961c, 0x0000000104de61aa }, + /* x^104448 mod p(x)` << 1, x^104512 mod p(x)` << 1 */ + { 0x000000019e588d52, 0x0000000113e40d46 }, + /* x^103424 mod p(x)` << 1, x^103488 mod p(x)` << 1 */ + { 0x00000001180f0bbc, 0x00000001415598a0 }, + /* x^102400 mod p(x)` << 1, x^102464 mod p(x)` << 1 */ + { 0x00000000e1d9177a, 0x00000000bf6c8c90 }, + /* x^101376 mod p(x)` << 1, x^101440 mod p(x)` << 1 */ + { 0x0000000105abc27c, 0x00000001788b0504 }, + /* x^100352 mod p(x)` << 1, x^100416 mod p(x)` << 1 */ + { 0x00000000972e4a58, 0x0000000038385d02 }, + /* x^99328 mod p(x)` << 1, x^99392 mod p(x)` << 1 */ + { 0x0000000183499a5e, 0x00000001b6c83844 }, + /* x^98304 mod p(x)` << 1, x^98368 mod p(x)` << 1 */ + { 0x00000001c96a8cca, 0x0000000051061a8a }, + /* x^97280 mod p(x)` << 1, x^97344 mod p(x)` << 1 */ + { 0x00000001a1a5b60c, 0x000000017351388a }, + /* x^96256 mod p(x)` << 1, x^96320 mod p(x)` << 1 */ + { 0x00000000e4b6ac9c, 0x0000000132928f92 }, + /* x^95232 mod p(x)` << 1, x^95296 mod p(x)` << 1 */ + { 0x00000001807e7f5a, 0x00000000e6b4f48a }, + /* x^94208 mod p(x)` << 1, x^94272 mod p(x)` << 1 */ + { 0x000000017a7e3bc8, 0x0000000039d15e90 }, + /* x^93184 mod p(x)` << 1, x^93248 mod p(x)` << 1 */ + { 0x00000000d73975da, 0x00000000312d6074 }, + /* x^92160 mod p(x)` << 1, x^92224 mod p(x)` << 1 */ + { 0x000000017375d038, 0x000000017bbb2cc4 }, + /* x^91136 mod p(x)` << 1, x^91200 mod p(x)` << 1 */ + { 0x00000000193680bc, 0x000000016ded3e18 }, + /* x^90112 mod p(x)` << 1, x^90176 mod p(x)` << 1 */ + { 0x00000000999b06f6, 0x00000000f1638b16 }, + /* x^89088 mod p(x)` << 1, x^89152 mod p(x)` << 1 */ + { 0x00000001f685d2b8, 0x00000001d38b9ecc }, + /* x^88064 mod p(x)` << 1, x^88128 mod p(x)` << 1 */ + { 0x00000001f4ecbed2, 0x000000018b8d09dc }, + /* x^87040 mod p(x)` << 1, x^87104 mod p(x)` << 1 */ + { 0x00000000ba16f1a0, 0x00000000e7bc27d2 }, + /* x^86016 mod p(x)` << 1, x^86080 mod p(x)` << 1 */ + { 0x0000000115aceac4, 0x00000000275e1e96 }, + /* x^84992 mod p(x)` << 1, x^85056 mod p(x)` << 1 */ + { 0x00000001aeff6292, 0x00000000e2e3031e }, + /* x^83968 mod p(x)` << 1, x^84032 mod p(x)` << 1 */ + { 0x000000009640124c, 0x00000001041c84d8 }, + /* x^82944 mod p(x)` << 1, x^83008 mod p(x)` << 1 */ + { 0x0000000114f41f02, 0x00000000706ce672 }, + /* x^81920 mod p(x)` << 1, x^81984 mod p(x)` << 1 */ + { 0x000000009c5f3586, 0x000000015d5070da }, + /* x^80896 mod p(x)` << 1, x^80960 mod p(x)` << 1 */ + { 0x00000001878275fa, 0x0000000038f9493a }, + /* x^79872 mod p(x)` << 1, x^79936 mod p(x)` << 1 */ + { 0x00000000ddc42ce8, 0x00000000a3348a76 }, + /* x^78848 mod p(x)` << 1, x^78912 mod p(x)` << 1 */ + { 0x0000000181d2c73a, 0x00000001ad0aab92 }, + /* x^77824 mod p(x)` << 1, x^77888 mod p(x)` << 1 */ + { 0x0000000141c9320a, 0x000000019e85f712 }, + /* x^76800 mod p(x)` << 1, x^76864 mod p(x)` << 1 */ + { 0x000000015235719a, 0x000000005a871e76 }, + /* x^75776 mod p(x)` << 1, x^75840 mod p(x)` << 1 */ + { 0x00000000be27d804, 0x000000017249c662 }, + /* x^74752 mod p(x)` << 1, x^74816 mod p(x)` << 1 */ + { 0x000000006242d45a, 0x000000003a084712 }, + /* x^73728 mod p(x)` << 1, x^73792 mod p(x)` << 1 */ + { 0x000000009a53638e, 0x00000000ed438478 }, + /* x^72704 mod p(x)` << 1, x^72768 mod p(x)` << 1 */ + { 0x00000001001ecfb6, 0x00000000abac34cc }, + /* x^71680 mod p(x)` << 1, x^71744 mod p(x)` << 1 */ + { 0x000000016d7c2d64, 0x000000005f35ef3e }, + /* x^70656 mod p(x)` << 1, x^70720 mod p(x)` << 1 */ + { 0x00000001d0ce46c0, 0x0000000047d6608c }, + /* x^69632 mod p(x)` << 1, x^69696 mod p(x)` << 1 */ + { 0x0000000124c907b4, 0x000000002d01470e }, + /* x^68608 mod p(x)` << 1, x^68672 mod p(x)` << 1 */ + { 0x0000000018a555ca, 0x0000000158bbc7b0 }, + /* x^67584 mod p(x)` << 1, x^67648 mod p(x)` << 1 */ + { 0x000000006b0980bc, 0x00000000c0a23e8e }, + /* x^66560 mod p(x)` << 1, x^66624 mod p(x)` << 1 */ + { 0x000000008bbba964, 0x00000001ebd85c88 }, + /* x^65536 mod p(x)` << 1, x^65600 mod p(x)` << 1 */ + { 0x00000001070a5a1e, 0x000000019ee20bb2 }, + /* x^64512 mod p(x)` << 1, x^64576 mod p(x)` << 1 */ + { 0x000000002204322a, 0x00000001acabf2d6 }, + /* x^63488 mod p(x)` << 1, x^63552 mod p(x)` << 1 */ + { 0x00000000a27524d0, 0x00000001b7963d56 }, + /* x^62464 mod p(x)` << 1, x^62528 mod p(x)` << 1 */ + { 0x0000000020b1e4ba, 0x000000017bffa1fe }, + /* x^61440 mod p(x)` << 1, x^61504 mod p(x)` << 1 */ + { 0x0000000032cc27fc, 0x000000001f15333e }, + /* x^60416 mod p(x)` << 1, x^60480 mod p(x)` << 1 */ + { 0x0000000044dd22b8, 0x000000018593129e }, + /* x^59392 mod p(x)` << 1, x^59456 mod p(x)` << 1 */ + { 0x00000000dffc9e0a, 0x000000019cb32602 }, + /* x^58368 mod p(x)` << 1, x^58432 mod p(x)` << 1 */ + { 0x00000001b7a0ed14, 0x0000000142b05cc8 }, + /* x^57344 mod p(x)` << 1, x^57408 mod p(x)` << 1 */ + { 0x00000000c7842488, 0x00000001be49e7a4 }, + /* x^56320 mod p(x)` << 1, x^56384 mod p(x)` << 1 */ + { 0x00000001c02a4fee, 0x0000000108f69d6c }, + /* x^55296 mod p(x)` << 1, x^55360 mod p(x)` << 1 */ + { 0x000000003c273778, 0x000000006c0971f0 }, + /* x^54272 mod p(x)` << 1, x^54336 mod p(x)` << 1 */ + { 0x00000001d63f8894, 0x000000005b16467a }, + /* x^53248 mod p(x)` << 1, x^53312 mod p(x)` << 1 */ + { 0x000000006be557d6, 0x00000001551a628e }, + /* x^52224 mod p(x)` << 1, x^52288 mod p(x)` << 1 */ + { 0x000000006a7806ea, 0x000000019e42ea92 }, + /* x^51200 mod p(x)` << 1, x^51264 mod p(x)` << 1 */ + { 0x000000016155aa0c, 0x000000012fa83ff2 }, + /* x^50176 mod p(x)` << 1, x^50240 mod p(x)` << 1 */ + { 0x00000000908650ac, 0x000000011ca9cde0 }, + /* x^49152 mod p(x)` << 1, x^49216 mod p(x)` << 1 */ + { 0x00000000aa5a8084, 0x00000000c8e5cd74 }, + /* x^48128 mod p(x)` << 1, x^48192 mod p(x)` << 1 */ + { 0x0000000191bb500a, 0x0000000096c27f0c }, + /* x^47104 mod p(x)` << 1, x^47168 mod p(x)` << 1 */ + { 0x0000000064e9bed0, 0x000000002baed926 }, + /* x^46080 mod p(x)` << 1, x^46144 mod p(x)` << 1 */ + { 0x000000009444f302, 0x000000017c8de8d2 }, + /* x^45056 mod p(x)` << 1, x^45120 mod p(x)` << 1 */ + { 0x000000019db07d3c, 0x00000000d43d6068 }, + /* x^44032 mod p(x)` << 1, x^44096 mod p(x)` << 1 */ + { 0x00000001359e3e6e, 0x00000000cb2c4b26 }, + /* x^43008 mod p(x)` << 1, x^43072 mod p(x)` << 1 */ + { 0x00000001e4f10dd2, 0x0000000145b8da26 }, + /* x^41984 mod p(x)` << 1, x^42048 mod p(x)` << 1 */ + { 0x0000000124f5735e, 0x000000018fff4b08 }, + /* x^40960 mod p(x)` << 1, x^41024 mod p(x)` << 1 */ + { 0x0000000124760a4c, 0x0000000150b58ed0 }, + /* x^39936 mod p(x)` << 1, x^40000 mod p(x)` << 1 */ + { 0x000000000f1fc186, 0x00000001549f39bc }, + /* x^38912 mod p(x)` << 1, x^38976 mod p(x)` << 1 */ + { 0x00000000150e4cc4, 0x00000000ef4d2f42 }, + /* x^37888 mod p(x)` << 1, x^37952 mod p(x)` << 1 */ + { 0x000000002a6204e8, 0x00000001b1468572 }, + /* x^36864 mod p(x)` << 1, x^36928 mod p(x)` << 1 */ + { 0x00000000beb1d432, 0x000000013d7403b2 }, + /* x^35840 mod p(x)` << 1, x^35904 mod p(x)` << 1 */ + { 0x0000000135f3f1f0, 0x00000001a4681842 }, + /* x^34816 mod p(x)` << 1, x^34880 mod p(x)` << 1 */ + { 0x0000000074fe2232, 0x0000000167714492 }, + /* x^33792 mod p(x)` << 1, x^33856 mod p(x)` << 1 */ + { 0x000000001ac6e2ba, 0x00000001e599099a }, + /* x^32768 mod p(x)` << 1, x^32832 mod p(x)` << 1 */ + { 0x0000000013fca91e, 0x00000000fe128194 }, + /* x^31744 mod p(x)` << 1, x^31808 mod p(x)` << 1 */ + { 0x0000000183f4931e, 0x0000000077e8b990 }, + /* x^30720 mod p(x)` << 1, x^30784 mod p(x)` << 1 */ + { 0x00000000b6d9b4e4, 0x00000001a267f63a }, + /* x^29696 mod p(x)` << 1, x^29760 mod p(x)` << 1 */ + { 0x00000000b5188656, 0x00000001945c245a }, + /* x^28672 mod p(x)` << 1, x^28736 mod p(x)` << 1 */ + { 0x0000000027a81a84, 0x0000000149002e76 }, + /* x^27648 mod p(x)` << 1, x^27712 mod p(x)` << 1 */ + { 0x0000000125699258, 0x00000001bb8310a4 }, + /* x^26624 mod p(x)` << 1, x^26688 mod p(x)` << 1 */ + { 0x00000001b23de796, 0x000000019ec60bcc }, + /* x^25600 mod p(x)` << 1, x^25664 mod p(x)` << 1 */ + { 0x00000000fe4365dc, 0x000000012d8590ae }, + /* x^24576 mod p(x)` << 1, x^24640 mod p(x)` << 1 */ + { 0x00000000c68f497a, 0x0000000065b00684 }, + /* x^23552 mod p(x)` << 1, x^23616 mod p(x)` << 1 */ + { 0x00000000fbf521ee, 0x000000015e5aeadc }, + /* x^22528 mod p(x)` << 1, x^22592 mod p(x)` << 1 */ + { 0x000000015eac3378, 0x00000000b77ff2b0 }, + /* x^21504 mod p(x)` << 1, x^21568 mod p(x)` << 1 */ + { 0x0000000134914b90, 0x0000000188da2ff6 }, + /* x^20480 mod p(x)` << 1, x^20544 mod p(x)` << 1 */ + { 0x0000000016335cfe, 0x0000000063da929a }, + /* x^19456 mod p(x)` << 1, x^19520 mod p(x)` << 1 */ + { 0x000000010372d10c, 0x00000001389caa80 }, + /* x^18432 mod p(x)` << 1, x^18496 mod p(x)` << 1 */ + { 0x000000015097b908, 0x000000013db599d2 }, + /* x^17408 mod p(x)` << 1, x^17472 mod p(x)` << 1 */ + { 0x00000001227a7572, 0x0000000122505a86 }, + /* x^16384 mod p(x)` << 1, x^16448 mod p(x)` << 1 */ + { 0x000000009a8f75c0, 0x000000016bd72746 }, + /* x^15360 mod p(x)` << 1, x^15424 mod p(x)` << 1 */ + { 0x00000000682c77a2, 0x00000001c3faf1d4 }, + /* x^14336 mod p(x)` << 1, x^14400 mod p(x)` << 1 */ + { 0x00000000231f091c, 0x00000001111c826c }, + /* x^13312 mod p(x)` << 1, x^13376 mod p(x)` << 1 */ + { 0x000000007d4439f2, 0x00000000153e9fb2 }, + /* x^12288 mod p(x)` << 1, x^12352 mod p(x)` << 1 */ + { 0x000000017e221efc, 0x000000002b1f7b60 }, + /* x^11264 mod p(x)` << 1, x^11328 mod p(x)` << 1 */ + { 0x0000000167457c38, 0x00000000b1dba570 }, + /* x^10240 mod p(x)` << 1, x^10304 mod p(x)` << 1 */ + { 0x00000000bdf081c4, 0x00000001f6397b76 }, + /* x^9216 mod p(x)` << 1, x^9280 mod p(x)` << 1 */ + { 0x000000016286d6b0, 0x0000000156335214 }, + /* x^8192 mod p(x)` << 1, x^8256 mod p(x)` << 1 */ + { 0x00000000c84f001c, 0x00000001d70e3986 }, + /* x^7168 mod p(x)` << 1, x^7232 mod p(x)` << 1 */ + { 0x0000000064efe7c0, 0x000000003701a774 }, + /* x^6144 mod p(x)` << 1, x^6208 mod p(x)` << 1 */ + { 0x000000000ac2d904, 0x00000000ac81ef72 }, + /* x^5120 mod p(x)` << 1, x^5184 mod p(x)` << 1 */ + { 0x00000000fd226d14, 0x0000000133212464 }, + /* x^4096 mod p(x)` << 1, x^4160 mod p(x)` << 1 */ + { 0x000000011cfd42e0, 0x00000000e4e45610 }, + /* x^3072 mod p(x)` << 1, x^3136 mod p(x)` << 1 */ + { 0x000000016e5a5678, 0x000000000c1bd370 }, + /* x^2048 mod p(x)` << 1, x^2112 mod p(x)` << 1 */ + { 0x00000001d888fe22, 0x00000001a7b9e7a6 }, + /* x^1024 mod p(x)` << 1, x^1088 mod p(x)` << 1 */ + { 0x00000001af77fcd4, 0x000000007d657a10 } +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ +}; + +/* Reduce final 1024-2048 bits to 64 bits, shifting 32 bits to include the trailing 32 bits of zeros */ + +static const __vector unsigned long long vcrc_short_const[16] ALIGNED_(16) = { +#if BYTE_ORDER == LITTLE_ENDIAN + /* x^1952 mod p(x) , x^1984 mod p(x) , x^2016 mod p(x) , x^2048 mod p(x) */ + { 0x99168a18ec447f11, 0xed837b2613e8221e }, + /* x^1824 mod p(x) , x^1856 mod p(x) , x^1888 mod p(x) , x^1920 mod p(x) */ + { 0xe23e954e8fd2cd3c, 0xc8acdd8147b9ce5a }, + /* x^1696 mod p(x) , x^1728 mod p(x) , x^1760 mod p(x) , x^1792 mod p(x) */ + { 0x92f8befe6b1d2b53, 0xd9ad6d87d4277e25 }, + /* x^1568 mod p(x) , x^1600 mod p(x) , x^1632 mod p(x) , x^1664 mod p(x) */ + { 0xf38a3556291ea462, 0xc10ec5e033fbca3b }, + /* x^1440 mod p(x) , x^1472 mod p(x) , x^1504 mod p(x) , x^1536 mod p(x) */ + { 0x974ac56262b6ca4b, 0xc0b55b0e82e02e2f }, + /* x^1312 mod p(x) , x^1344 mod p(x) , x^1376 mod p(x) , x^1408 mod p(x) */ + { 0x855712b3784d2a56, 0x71aa1df0e172334d }, + /* x^1184 mod p(x) , x^1216 mod p(x) , x^1248 mod p(x) , x^1280 mod p(x) */ + { 0xa5abe9f80eaee722, 0xfee3053e3969324d }, + /* x^1056 mod p(x) , x^1088 mod p(x) , x^1120 mod p(x) , x^1152 mod p(x) */ + { 0x1fa0943ddb54814c, 0xf44779b93eb2bd08 }, + /* x^928 mod p(x) , x^960 mod p(x) , x^992 mod p(x) , x^1024 mod p(x) */ + { 0xa53ff440d7bbfe6a, 0xf5449b3f00cc3374 }, + /* x^800 mod p(x) , x^832 mod p(x) , x^864 mod p(x) , x^896 mod p(x) */ + { 0xebe7e3566325605c, 0x6f8346e1d777606e }, + /* x^672 mod p(x) , x^704 mod p(x) , x^736 mod p(x) , x^768 mod p(x) */ + { 0xc65a272ce5b592b8, 0xe3ab4f2ac0b95347 }, + /* x^544 mod p(x) , x^576 mod p(x) , x^608 mod p(x) , x^640 mod p(x) */ + { 0x5705a9ca4721589f, 0xaa2215ea329ecc11 }, + /* x^416 mod p(x) , x^448 mod p(x) , x^480 mod p(x) , x^512 mod p(x) */ + { 0xe3720acb88d14467, 0x1ed8f66ed95efd26 }, + /* x^288 mod p(x) , x^320 mod p(x) , x^352 mod p(x) , x^384 mod p(x) */ + { 0xba1aca0315141c31, 0x78ed02d5a700e96a }, + /* x^160 mod p(x) , x^192 mod p(x) , x^224 mod p(x) , x^256 mod p(x) */ + { 0xad2a31b3ed627dae, 0xba8ccbe832b39da3 }, + /* x^32 mod p(x) , x^64 mod p(x) , x^96 mod p(x) , x^128 mod p(x) */ + { 0x6655004fa06a2517, 0xedb88320b1e6b092 } +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + /* x^1952 mod p(x) , x^1984 mod p(x) , x^2016 mod p(x) , x^2048 mod p(x) */ + { 0xed837b2613e8221e, 0x99168a18ec447f11 }, + /* x^1824 mod p(x) , x^1856 mod p(x) , x^1888 mod p(x) , x^1920 mod p(x) */ + { 0xc8acdd8147b9ce5a, 0xe23e954e8fd2cd3c }, + /* x^1696 mod p(x) , x^1728 mod p(x) , x^1760 mod p(x) , x^1792 mod p(x) */ + { 0xd9ad6d87d4277e25, 0x92f8befe6b1d2b53 }, + /* x^1568 mod p(x) , x^1600 mod p(x) , x^1632 mod p(x) , x^1664 mod p(x) */ + { 0xc10ec5e033fbca3b, 0xf38a3556291ea462 }, + /* x^1440 mod p(x) , x^1472 mod p(x) , x^1504 mod p(x) , x^1536 mod p(x) */ + { 0xc0b55b0e82e02e2f, 0x974ac56262b6ca4b }, + /* x^1312 mod p(x) , x^1344 mod p(x) , x^1376 mod p(x) , x^1408 mod p(x) */ + { 0x71aa1df0e172334d, 0x855712b3784d2a56 }, + /* x^1184 mod p(x) , x^1216 mod p(x) , x^1248 mod p(x) , x^1280 mod p(x) */ + { 0xfee3053e3969324d, 0xa5abe9f80eaee722 }, + /* x^1056 mod p(x) , x^1088 mod p(x) , x^1120 mod p(x) , x^1152 mod p(x) */ + { 0xf44779b93eb2bd08, 0x1fa0943ddb54814c }, + /* x^928 mod p(x) , x^960 mod p(x) , x^992 mod p(x) , x^1024 mod p(x) */ + { 0xf5449b3f00cc3374, 0xa53ff440d7bbfe6a }, + /* x^800 mod p(x) , x^832 mod p(x) , x^864 mod p(x) , x^896 mod p(x) */ + { 0x6f8346e1d777606e, 0xebe7e3566325605c }, + /* x^672 mod p(x) , x^704 mod p(x) , x^736 mod p(x) , x^768 mod p(x) */ + { 0xe3ab4f2ac0b95347, 0xc65a272ce5b592b8 }, + /* x^544 mod p(x) , x^576 mod p(x) , x^608 mod p(x) , x^640 mod p(x) */ + { 0xaa2215ea329ecc11, 0x5705a9ca4721589f }, + /* x^416 mod p(x) , x^448 mod p(x) , x^480 mod p(x) , x^512 mod p(x) */ + { 0x1ed8f66ed95efd26, 0xe3720acb88d14467 }, + /* x^288 mod p(x) , x^320 mod p(x) , x^352 mod p(x) , x^384 mod p(x) */ + { 0x78ed02d5a700e96a, 0xba1aca0315141c31 }, + /* x^160 mod p(x) , x^192 mod p(x) , x^224 mod p(x) , x^256 mod p(x) */ + { 0xba8ccbe832b39da3, 0xad2a31b3ed627dae }, + /* x^32 mod p(x) , x^64 mod p(x) , x^96 mod p(x) , x^128 mod p(x) */ + { 0xedb88320b1e6b092, 0x6655004fa06a2517 } +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ +}; + +/* Barrett constants */ +/* 33 bit reflected Barrett constant m - (4^32)/n */ + +static const __vector unsigned long long v_Barrett_const[2] ALIGNED_(16) = { + /* x^64 div p(x) */ +#if BYTE_ORDER == LITTLE_ENDIAN + { 0x00000001f7011641, 0x0000000000000000 }, + { 0x00000001db710641, 0x0000000000000000 } +#else /* BYTE_ORDER == LITTLE_ENDIAN */ + { 0x0000000000000000, 0x00000001f7011641 }, + { 0x0000000000000000, 0x00000001db710641 } +#endif /* BYTE_ORDER == LITTLE_ENDIAN */ +}; diff --git a/arch/power/crc32_power8.c b/arch/power/crc32_power8.c new file mode 100644 index 0000000000..17414b394e --- /dev/null +++ b/arch/power/crc32_power8.c @@ -0,0 +1,589 @@ +/* crc32 for POWER8 using VSX instructions + * Copyright (C) 2021 IBM Corporation + * + * Author: Rogerio Alves + * + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Calculate the checksum of data that is 16 byte aligned and a multiple of + * 16 bytes. + * + * The first step is to reduce it to 1024 bits. We do this in 8 parallel + * chunks in order to mask the latency of the vpmsum instructions. If we + * have more than 32 kB of data to checksum we repeat this step multiple + * times, passing in the previous 1024 bits. + * + * The next step is to reduce the 1024 bits to 64 bits. This step adds + * 32 bits of 0s to the end - this matches what a CRC does. We just + * calculate constants that land the data in this 32 bits. + * + * We then use fixed point Barrett reduction to compute a mod n over GF(2) + * for n = CRC using POWER8 instructions. We use x = 32. + * + * http://en.wikipedia.org/wiki/Barrett_reduction + * + * This code uses gcc vector builtins instead using assembly directly. + */ + +#include +#include "zendian.h" +#include "zutil.h" + +#include "crc32_constants.h" +#include "crc32_tbl.h" + +#if defined (__clang__) +#include "fallback_builtins.h" +#endif + +#define MAX_SIZE 32768 +#define VMX_ALIGN 16 +#define VMX_ALIGN_MASK (VMX_ALIGN-1) + +static unsigned int crc32_align(unsigned int crc, const unsigned char *p, unsigned long len) { + while (len--) + crc = crc_table[0][(crc ^ *p++) & 0xff] ^ (crc >> 8); + return crc; +} + +static unsigned int ALIGNED_(32) __crc32_vpmsum(unsigned int crc, const void* p, unsigned long len); + +Z_INTERNAL uint32_t crc32_power8(uint32_t crc, const unsigned char *p, uint64_t _len) { + unsigned int prealign; + unsigned int tail; + + unsigned long len = (unsigned long) _len; + + if (p == (const unsigned char *) 0x0) + return 0; + + crc ^= 0xffffffff; + + if (len < VMX_ALIGN + VMX_ALIGN_MASK) { + crc = crc32_align(crc, p, len); + goto out; + } + + if ((unsigned long)p & VMX_ALIGN_MASK) { + prealign = VMX_ALIGN - ((unsigned long)p & VMX_ALIGN_MASK); + crc = crc32_align(crc, p, prealign); + len -= prealign; + p += prealign; + } + + crc = __crc32_vpmsum(crc, p, len & ~VMX_ALIGN_MASK); + + tail = len & VMX_ALIGN_MASK; + if (tail) { + p += len & ~VMX_ALIGN_MASK; + crc = crc32_align(crc, p, tail); + } + +out: + crc ^= 0xffffffff; + + return crc; +} + +/* When we have a load-store in a single-dispatch group and address overlap + * such that forward is not allowed (load-hit-store) the group must be flushed. + * A group ending NOP prevents the flush. + */ +#define GROUP_ENDING_NOP __asm__("ori 2,2,0" ::: "memory") + +#if BYTE_ORDER == BIG_ENDIAN +#define BYTESWAP_DATA +#endif + +#ifdef BYTESWAP_DATA +#define VEC_PERM(vr, va, vb, vc) vr = vec_perm(va, vb, (__vector unsigned char) vc) +#if BYTE_ORDER == LITTLE_ENDIAN +/* Byte reverse permute constant LE. */ +static const __vector unsigned long long vperm_const ALIGNED_(16) = { 0x08090A0B0C0D0E0FUL, 0x0001020304050607UL }; +#else +static const __vector unsigned long long vperm_const ALIGNED_(16) = { 0x0F0E0D0C0B0A0908UL, 0X0706050403020100UL }; +#endif +#else +#define VEC_PERM(vr, va, vb, vc) +#endif + +static unsigned int ALIGNED_(32) __crc32_vpmsum(unsigned int crc, const void* p, unsigned long len) { + + const __vector unsigned long long vzero = {0,0}; + const __vector unsigned long long vones = {0xffffffffffffffffUL, 0xffffffffffffffffUL}; + + const __vector unsigned long long vmask_32bit = + (__vector unsigned long long)vec_sld((__vector unsigned char)vzero, (__vector unsigned char)vones, 4); + + const __vector unsigned long long vmask_64bit = + (__vector unsigned long long)vec_sld((__vector unsigned char)vzero, (__vector unsigned char)vones, 8); + + __vector unsigned long long vcrc; + + __vector unsigned long long vconst1, vconst2; + + /* vdata0-vdata7 will contain our data (p). */ + __vector unsigned long long vdata0, vdata1, vdata2, vdata3, vdata4, vdata5, vdata6, vdata7; + + /* v0-v7 will contain our checksums */ + __vector unsigned long long v0 = {0,0}; + __vector unsigned long long v1 = {0,0}; + __vector unsigned long long v2 = {0,0}; + __vector unsigned long long v3 = {0,0}; + __vector unsigned long long v4 = {0,0}; + __vector unsigned long long v5 = {0,0}; + __vector unsigned long long v6 = {0,0}; + __vector unsigned long long v7 = {0,0}; + + + /* Vector auxiliary variables. */ + __vector unsigned long long va0, va1, va2, va3, va4, va5, va6, va7; + + unsigned int offset; /* Constant table offset. */ + + unsigned long i; /* Counter. */ + unsigned long chunks; + + unsigned long block_size; + int next_block = 0; + + /* Align by 128 bits. The last 128 bit block will be processed at end. */ + unsigned long length = len & 0xFFFFFFFFFFFFFF80UL; + + vcrc = (__vector unsigned long long)__builtin_pack_vector_int128(0UL, crc); + + /* Short version. */ + if (len < 256) { + /* Calculate where in the constant table we need to start. */ + offset = 256 - len; + + vconst1 = vec_ld(offset, vcrc_short_const); + vdata0 = vec_ld(0, (__vector unsigned long long*) p); + VEC_PERM(vdata0, vdata0, vconst1, vperm_const); + + /* xor initial value */ + vdata0 = vec_xor(vdata0, vcrc); + + vdata0 = (__vector unsigned long long) __builtin_crypto_vpmsumw( + (__vector unsigned int)vdata0, (__vector unsigned int)vconst1); + v0 = vec_xor(v0, vdata0); + + for (i = 16; i < len; i += 16) { + vconst1 = vec_ld(offset + i, vcrc_short_const); + vdata0 = vec_ld(i, (__vector unsigned long long*) p); + VEC_PERM(vdata0, vdata0, vconst1, vperm_const); + vdata0 = (__vector unsigned long long) __builtin_crypto_vpmsumw( + (__vector unsigned int)vdata0, (__vector unsigned int)vconst1); + v0 = vec_xor(v0, vdata0); + } + } else { + + /* Load initial values. */ + vdata0 = vec_ld(0, (__vector unsigned long long*) p); + vdata1 = vec_ld(16, (__vector unsigned long long*) p); + + VEC_PERM(vdata0, vdata0, vdata0, vperm_const); + VEC_PERM(vdata1, vdata1, vdata1, vperm_const); + + vdata2 = vec_ld(32, (__vector unsigned long long*) p); + vdata3 = vec_ld(48, (__vector unsigned long long*) p); + + VEC_PERM(vdata2, vdata2, vdata2, vperm_const); + VEC_PERM(vdata3, vdata3, vdata3, vperm_const); + + vdata4 = vec_ld(64, (__vector unsigned long long*) p); + vdata5 = vec_ld(80, (__vector unsigned long long*) p); + + VEC_PERM(vdata4, vdata4, vdata4, vperm_const); + VEC_PERM(vdata5, vdata5, vdata5, vperm_const); + + vdata6 = vec_ld(96, (__vector unsigned long long*) p); + vdata7 = vec_ld(112, (__vector unsigned long long*) p); + + VEC_PERM(vdata6, vdata6, vdata6, vperm_const); + VEC_PERM(vdata7, vdata7, vdata7, vperm_const); + + /* xor in initial value */ + vdata0 = vec_xor(vdata0, vcrc); + + p = (char *)p + 128; + + do { + /* Checksum in blocks of MAX_SIZE. */ + block_size = length; + if (block_size > MAX_SIZE) { + block_size = MAX_SIZE; + } + + length = length - block_size; + + /* + * Work out the offset into the constants table to start at. Each + * constant is 16 bytes, and it is used against 128 bytes of input + * data - 128 / 16 = 8 + */ + offset = (MAX_SIZE/8) - (block_size/8); + /* We reduce our final 128 bytes in a separate step */ + chunks = (block_size/128)-1; + + vconst1 = vec_ld(offset, vcrc_const); + + va0 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata0, + (__vector unsigned long long)vconst1); + va1 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata1, + (__vector unsigned long long)vconst1); + va2 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata2, + (__vector unsigned long long)vconst1); + va3 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata3, + (__vector unsigned long long)vconst1); + va4 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata4, + (__vector unsigned long long)vconst1); + va5 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata5, + (__vector unsigned long long)vconst1); + va6 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata6, + (__vector unsigned long long)vconst1); + va7 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata7, + (__vector unsigned long long)vconst1); + + if (chunks > 1) { + offset += 16; + vconst2 = vec_ld(offset, vcrc_const); + GROUP_ENDING_NOP; + + vdata0 = vec_ld(0, (__vector unsigned long long*) p); + VEC_PERM(vdata0, vdata0, vdata0, vperm_const); + + vdata1 = vec_ld(16, (__vector unsigned long long*) p); + VEC_PERM(vdata1, vdata1, vdata1, vperm_const); + + vdata2 = vec_ld(32, (__vector unsigned long long*) p); + VEC_PERM(vdata2, vdata2, vdata2, vperm_const); + + vdata3 = vec_ld(48, (__vector unsigned long long*) p); + VEC_PERM(vdata3, vdata3, vdata3, vperm_const); + + vdata4 = vec_ld(64, (__vector unsigned long long*) p); + VEC_PERM(vdata4, vdata4, vdata4, vperm_const); + + vdata5 = vec_ld(80, (__vector unsigned long long*) p); + VEC_PERM(vdata5, vdata5, vdata5, vperm_const); + + vdata6 = vec_ld(96, (__vector unsigned long long*) p); + VEC_PERM(vdata6, vdata6, vdata6, vperm_const); + + vdata7 = vec_ld(112, (__vector unsigned long long*) p); + VEC_PERM(vdata7, vdata7, vdata7, vperm_const); + + p = (char *)p + 128; + + /* + * main loop. Each iteration calculates the CRC for a 128-byte + * block. + */ + for (i = 0; i < chunks-2; i++) { + vconst1 = vec_ld(offset, vcrc_const); + offset += 16; + GROUP_ENDING_NOP; + + v0 = vec_xor(v0, va0); + va0 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata0, + (__vector unsigned long long)vconst2); + vdata0 = vec_ld(0, (__vector unsigned long long*) p); + VEC_PERM(vdata0, vdata0, vdata0, vperm_const); + GROUP_ENDING_NOP; + + v1 = vec_xor(v1, va1); + va1 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata1, + (__vector unsigned long long)vconst2); + vdata1 = vec_ld(16, (__vector unsigned long long*) p); + VEC_PERM(vdata1, vdata1, vdata1, vperm_const); + GROUP_ENDING_NOP; + + v2 = vec_xor(v2, va2); + va2 = __builtin_crypto_vpmsumd((__vector unsigned long long) + vdata2, (__vector unsigned long long)vconst2); + vdata2 = vec_ld(32, (__vector unsigned long long*) p); + VEC_PERM(vdata2, vdata2, vdata2, vperm_const); + GROUP_ENDING_NOP; + + v3 = vec_xor(v3, va3); + va3 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata3, + (__vector unsigned long long)vconst2); + vdata3 = vec_ld(48, (__vector unsigned long long*) p); + VEC_PERM(vdata3, vdata3, vdata3, vperm_const); + + vconst2 = vec_ld(offset, vcrc_const); + GROUP_ENDING_NOP; + + v4 = vec_xor(v4, va4); + va4 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata4, + (__vector unsigned long long)vconst1); + vdata4 = vec_ld(64, (__vector unsigned long long*) p); + VEC_PERM(vdata4, vdata4, vdata4, vperm_const); + GROUP_ENDING_NOP; + + v5 = vec_xor(v5, va5); + va5 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata5, + (__vector unsigned long long)vconst1); + vdata5 = vec_ld(80, (__vector unsigned long long*) p); + VEC_PERM(vdata5, vdata5, vdata5, vperm_const); + GROUP_ENDING_NOP; + + v6 = vec_xor(v6, va6); + va6 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata6, + (__vector unsigned long long)vconst1); + vdata6 = vec_ld(96, (__vector unsigned long long*) p); + VEC_PERM(vdata6, vdata6, vdata6, vperm_const); + GROUP_ENDING_NOP; + + v7 = vec_xor(v7, va7); + va7 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata7, + (__vector unsigned long long)vconst1); + vdata7 = vec_ld(112, (__vector unsigned long long*) p); + VEC_PERM(vdata7, vdata7, vdata7, vperm_const); + + p = (char *)p + 128; + } + + /* First cool down */ + vconst1 = vec_ld(offset, vcrc_const); + offset += 16; + + v0 = vec_xor(v0, va0); + va0 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata0, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v1 = vec_xor(v1, va1); + va1 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata1, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v2 = vec_xor(v2, va2); + va2 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata2, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v3 = vec_xor(v3, va3); + va3 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata3, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v4 = vec_xor(v4, va4); + va4 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata4, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v5 = vec_xor(v5, va5); + va5 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata5, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v6 = vec_xor(v6, va6); + va6 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata6, + (__vector unsigned long long)vconst1); + GROUP_ENDING_NOP; + + v7 = vec_xor(v7, va7); + va7 = __builtin_crypto_vpmsumd((__vector unsigned long long)vdata7, + (__vector unsigned long long)vconst1); + }/* else */ + + /* Second cool down. */ + v0 = vec_xor(v0, va0); + v1 = vec_xor(v1, va1); + v2 = vec_xor(v2, va2); + v3 = vec_xor(v3, va3); + v4 = vec_xor(v4, va4); + v5 = vec_xor(v5, va5); + v6 = vec_xor(v6, va6); + v7 = vec_xor(v7, va7); + + /* + * vpmsumd produces a 96 bit result in the least significant bits + * of the register. Since we are bit reflected we have to shift it + * left 32 bits so it occupies the least significant bits in the + * bit reflected domain. + */ + v0 = (__vector unsigned long long)vec_sld((__vector unsigned char)v0, + (__vector unsigned char)vzero, 4); + v1 = (__vector unsigned long long)vec_sld((__vector unsigned char)v1, + (__vector unsigned char)vzero, 4); + v2 = (__vector unsigned long long)vec_sld((__vector unsigned char)v2, + (__vector unsigned char)vzero, 4); + v3 = (__vector unsigned long long)vec_sld((__vector unsigned char)v3, + (__vector unsigned char)vzero, 4); + v4 = (__vector unsigned long long)vec_sld((__vector unsigned char)v4, + (__vector unsigned char)vzero, 4); + v5 = (__vector unsigned long long)vec_sld((__vector unsigned char)v5, + (__vector unsigned char)vzero, 4); + v6 = (__vector unsigned long long)vec_sld((__vector unsigned char)v6, + (__vector unsigned char)vzero, 4); + v7 = (__vector unsigned long long)vec_sld((__vector unsigned char)v7, + (__vector unsigned char)vzero, 4); + + /* xor with the last 1024 bits. */ + va0 = vec_ld(0, (__vector unsigned long long*) p); + VEC_PERM(va0, va0, va0, vperm_const); + + va1 = vec_ld(16, (__vector unsigned long long*) p); + VEC_PERM(va1, va1, va1, vperm_const); + + va2 = vec_ld(32, (__vector unsigned long long*) p); + VEC_PERM(va2, va2, va2, vperm_const); + + va3 = vec_ld(48, (__vector unsigned long long*) p); + VEC_PERM(va3, va3, va3, vperm_const); + + va4 = vec_ld(64, (__vector unsigned long long*) p); + VEC_PERM(va4, va4, va4, vperm_const); + + va5 = vec_ld(80, (__vector unsigned long long*) p); + VEC_PERM(va5, va5, va5, vperm_const); + + va6 = vec_ld(96, (__vector unsigned long long*) p); + VEC_PERM(va6, va6, va6, vperm_const); + + va7 = vec_ld(112, (__vector unsigned long long*) p); + VEC_PERM(va7, va7, va7, vperm_const); + + p = (char *)p + 128; + + vdata0 = vec_xor(v0, va0); + vdata1 = vec_xor(v1, va1); + vdata2 = vec_xor(v2, va2); + vdata3 = vec_xor(v3, va3); + vdata4 = vec_xor(v4, va4); + vdata5 = vec_xor(v5, va5); + vdata6 = vec_xor(v6, va6); + vdata7 = vec_xor(v7, va7); + + /* Check if we have more blocks to process */ + next_block = 0; + if (length != 0) { + next_block = 1; + + /* zero v0-v7 */ + v0 = vec_xor(v0, v0); + v1 = vec_xor(v1, v1); + v2 = vec_xor(v2, v2); + v3 = vec_xor(v3, v3); + v4 = vec_xor(v4, v4); + v5 = vec_xor(v5, v5); + v6 = vec_xor(v6, v6); + v7 = vec_xor(v7, v7); + } + length = length + 128; + + } while (next_block); + + /* Calculate how many bytes we have left. */ + length = (len & 127); + + /* Calculate where in (short) constant table we need to start. */ + offset = 128 - length; + + v0 = vec_ld(offset, vcrc_short_const); + v1 = vec_ld(offset + 16, vcrc_short_const); + v2 = vec_ld(offset + 32, vcrc_short_const); + v3 = vec_ld(offset + 48, vcrc_short_const); + v4 = vec_ld(offset + 64, vcrc_short_const); + v5 = vec_ld(offset + 80, vcrc_short_const); + v6 = vec_ld(offset + 96, vcrc_short_const); + v7 = vec_ld(offset + 112, vcrc_short_const); + + offset += 128; + + v0 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata0, (__vector unsigned int)v0); + v1 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata1, (__vector unsigned int)v1); + v2 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata2, (__vector unsigned int)v2); + v3 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata3, (__vector unsigned int)v3); + v4 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata4, (__vector unsigned int)v4); + v5 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata5, (__vector unsigned int)v5); + v6 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata6, (__vector unsigned int)v6); + v7 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata7, (__vector unsigned int)v7); + + /* Now reduce the tail (0-112 bytes). */ + for (i = 0; i < length; i+=16) { + vdata0 = vec_ld(i,(__vector unsigned long long*)p); + VEC_PERM(vdata0, vdata0, vdata0, vperm_const); + va0 = vec_ld(offset + i,vcrc_short_const); + va0 = (__vector unsigned long long)__builtin_crypto_vpmsumw( + (__vector unsigned int)vdata0, (__vector unsigned int)va0); + v0 = vec_xor(v0, va0); + } + + /* xor all parallel chunks together. */ + v0 = vec_xor(v0, v1); + v2 = vec_xor(v2, v3); + v4 = vec_xor(v4, v5); + v6 = vec_xor(v6, v7); + + v0 = vec_xor(v0, v2); + v4 = vec_xor(v4, v6); + + v0 = vec_xor(v0, v4); + } + + /* Barrett Reduction */ + vconst1 = vec_ld(0, v_Barrett_const); + vconst2 = vec_ld(16, v_Barrett_const); + + v1 = (__vector unsigned long long)vec_sld((__vector unsigned char)v0, + (__vector unsigned char)v0, 8); + v0 = vec_xor(v1,v0); + + /* shift left one bit */ + __vector unsigned char vsht_splat = vec_splat_u8 (1); + v0 = (__vector unsigned long long)vec_sll((__vector unsigned char)v0, vsht_splat); + + v0 = vec_and(v0, vmask_64bit); + + /* + * The reflected version of Barrett reduction. Instead of bit + * reflecting our data (which is expensive to do), we bit reflect our + * constants and our algorithm, which means the intermediate data in + * our vector registers goes from 0-63 instead of 63-0. We can reflect + * the algorithm because we don't carry in mod 2 arithmetic. + */ + + /* bottom 32 bits of a */ + v1 = vec_and(v0, vmask_32bit); + + /* ma */ + v1 = __builtin_crypto_vpmsumd((__vector unsigned long long)v1, + (__vector unsigned long long)vconst1); + + /* bottom 32bits of ma */ + v1 = vec_and(v1, vmask_32bit); + /* qn */ + v1 = __builtin_crypto_vpmsumd((__vector unsigned long long)v1, + (__vector unsigned long long)vconst2); + /* a - qn, subtraction is xor in GF(2) */ + v0 = vec_xor (v0, v1); + + /* + * Since we are bit reflected, the result (ie the low 32 bits) is in + * the high 32 bits. We just need to shift it left 4 bytes + * V0 [ 0 1 X 3 ] + * V0 [ 0 X 2 3 ] + */ + + /* shift result into top 64 bits of */ + v0 = (__vector unsigned long long)vec_sld((__vector unsigned char)v0, + (__vector unsigned char)vzero, 4); + +#if BYTE_ORDER == BIG_ENDIAN + return v0[0]; +#else + return v0[1]; +#endif +} diff --git a/arch/power/fallback_builtins.h b/arch/power/fallback_builtins.h new file mode 100644 index 0000000000..ed9584617b --- /dev/null +++ b/arch/power/fallback_builtins.h @@ -0,0 +1,31 @@ +/* Helper functions to work around issues with clang builtins + * Copyright (C) 2021 IBM Corporation + * + * Authors: + * Daniel Black + * Rogerio Alves + * Tulio Magno Quites Machado Filho + * + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef POWER_BUILTINS_H +#define POWER_BUILTINS_H + +/* + * These stubs fix clang incompatibilities with GCC builtins. + */ + +#ifndef __builtin_crypto_vpmsumw +#define __builtin_crypto_vpmsumw __builtin_crypto_vpmsumb +#endif +#ifndef __builtin_crypto_vpmsumd +#define __builtin_crypto_vpmsumd __builtin_crypto_vpmsumb +#endif + +static inline __vector unsigned long long __attribute__((overloadable)) +vec_ld(int __a, const __vector unsigned long long* __b) { + return (__vector unsigned long long)__builtin_altivec_lvx(__a, __b); +} + +#endif diff --git a/configure b/configure index 26281338ee..596ce6046a 100755 --- a/configure +++ b/configure @@ -1649,6 +1649,14 @@ EOF ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_power8.o chunkset_power8.o slide_hash_power8.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_power8.lo chunkset_power8.lo slide_hash_power8.lo" + case "${ARCH}" in + powerpc64*) + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_power8.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_power8.lo" + CFLAGS="${CFLAGS} -DPOWER8_VSX_CRC32" + SFLAGS="${SFLAGS} -DPOWER8_VSX_CRC32" + ;; + esac fi fi ;; diff --git a/functable.c b/functable.c index e1c8577f0e..36eec10231 100644 --- a/functable.c +++ b/functable.c @@ -118,6 +118,8 @@ Z_INTERNAL uint32_t crc32_generic(uint32_t, const unsigned char *, uint64_t); #ifdef ARM_ACLE_CRC_HASH extern uint32_t crc32_acle(uint32_t, const unsigned char *, uint64_t); +#elif defined(POWER8_VSX_CRC32) +extern uint32_t crc32_power8(uint32_t, const unsigned char *, uint64_t); #endif #ifdef S390_CRC32_VX extern uint32_t s390_crc32_vx(uint32_t, const unsigned char *, uint64_t); @@ -487,6 +489,10 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t # error No endian defined #endif } +#if defined(POWER8_VSX_CRC32) + if (power_cpu_has_arch_2_07) + functable.crc32 = crc32_power8; +#endif return functable.crc32(crc, buf, len); } From 0064010024ca2d0b00b3f075607f12b05b57a5c9 Mon Sep 17 00:00:00 2001 From: Matheus Castanho Date: Wed, 16 Jun 2021 14:36:24 -0300 Subject: [PATCH 126/798] Add new crc32 unit test --- .gitignore | 2 + CMakeLists.txt | 1 + Makefile.in | 23 +++++- test/Makefile.in | 4 +- test/crc32_test.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 223 insertions(+), 6 deletions(-) create mode 100644 test/crc32_test.c diff --git a/.gitignore b/.gitignore index 23f9fd1590..bf420e572c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,8 @@ /adler32_test /adler32_testsh +/crc32_test +/crc32_testsh /example /example64 /examplesh diff --git a/CMakeLists.txt b/CMakeLists.txt index 77a22cc53b..6c148222d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1084,6 +1084,7 @@ if(ZLIB_ENABLE_TESTS) endmacro() add_simple_test_executable(adler32_test) + add_simple_test_executable(crc32_test) add_simple_test_executable(example) set(MINIGZIP_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) diff --git a/Makefile.in b/Makefile.in index de37b19067..19901ef479 100644 --- a/Makefile.in +++ b/Makefile.in @@ -147,9 +147,9 @@ PIC_OBJS = $(PIC_OBJC) all: static shared -static: adler32_test$(EXE) example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) +static: adler32_test$(EXE) crc32_test$(EXE) example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) -shared: adler32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) +shared: adler32_testsh$(EXE) crc32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) check: test @@ -244,6 +244,9 @@ $(STATICLIB): $(OBJS) adler32_test.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/adler32_test.c +crc32_test.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/crc32_test.c + example.o: $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $(SRCDIR)/test/example.c @@ -292,6 +295,12 @@ ifneq ($(STRIP),) $(STRIP) $@ endif +crc32_test$(EXE): crc32_test.o $(STATICLIB) + $(CC) $(LDFLAGS) -o $@ crc32_test.o $(TEST_LIBS) $(LDSHAREDLIBC) +ifneq ($(STRIP),) + $(STRIP) $@ +endif + example$(EXE): example.o $(OBJG) $(STATICLIB) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) @@ -310,6 +319,12 @@ ifneq ($(STRIP),) $(STRIP) $@ endif +crc32_testsh$(EXE): crc32_test.o $(SHAREDTARGET) + $(CC) $(LDFLAGS) -o $@ crc32_test.o $(SHAREDTARGET) $(LDSHAREDLIBC) +ifneq ($(STRIP),) + $(STRIP) $@ +endif + examplesh$(EXE): example.o $(OBJG) $(SHAREDTARGET) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) ifneq ($(STRIP),) @@ -401,8 +416,8 @@ clean: @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) clean; fi @if [ -f test/Makefile ]; then $(MAKE) -C test clean; fi rm -f *.o *.lo *~ \ - adler32_test$(EXE) example$(EXE) minigzip$(EXE) \ - adler32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ + adler32_test$(EXE) crc32_test$(EXE) example$(EXE) minigzip$(EXE) \ + adler32_testsh$(EXE) crc32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) \ example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE) \ infcover makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) \ diff --git a/test/Makefile.in b/test/Makefile.in index 97b8be7538..6a075d362e 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -48,7 +48,7 @@ endif teststatic: check_cross_dep @TMPST=tmpst_$$$$; \ HELLOST=tmphellost_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${QEMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${QEMU_RUN} ../example$(EXE) $$TMPST && ${QEMU_RUN} ../adler32_test$(EXE); then \ + if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${QEMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${QEMU_RUN} ../example$(EXE) $$TMPST && ${QEMU_RUN} ../adler32_test$(EXE) && ${QEMU_RUN} ../crc32_test$(EXE); then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; exit 1; \ @@ -62,7 +62,7 @@ testshared: check_cross_dep SHLIB_PATH=`pwd`/..:$(SHLIB_PATH) ; export SHLIB_PATH; \ TMPSH=tmpsh_$$$$; \ HELLOSH=tmphellosh_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${QEMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH && ${QEMU_RUN} ../adler32_testsh$(EXE); then \ + if echo hello world | ${QEMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${QEMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH && ${QEMU_RUN} ../adler32_testsh$(EXE) && ${QEMU_RUN} ../crc32_testsh$(EXE); then \ echo ' *** zlib shared test OK ***'; \ else \ echo ' *** zlib shared test FAILED ***'; exit 1; \ diff --git a/test/crc32_test.c b/test/crc32_test.c new file mode 100644 index 0000000000..c625b501a1 --- /dev/null +++ b/test/crc32_test.c @@ -0,0 +1,199 @@ +/* crc32_test.c -- crc32 unit test + * Copyright (C) 2019-2021 IBM Corporation + * Authors: Rogerio Alves + * Matheus Castanho + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +typedef struct { + uint32_t line; + unsigned long crc; + const unsigned char *buf; + size_t len; + unsigned long expect; +} crc32_test; + +void test_crc32(unsigned long crc, const unsigned char *buf, size_t len, uint32_t chk, uint32_t line) { + uint32_t res = PREFIX(crc32_z)((uint32_t)crc, buf, len); + if (res != chk) { + fprintf(stderr, "FAIL [%d]: crc32 returned 0x%08X expected 0x%08X\n", + line, res, chk); + exit(1); + } +} + +static const crc32_test tests[] = { + {__LINE__, 0x0, (const unsigned char *)0x0, 0, 0x0}, + {__LINE__, 0xffffffff, (const unsigned char *)0x0, 0, 0x0}, + {__LINE__, 0x0, (const unsigned char *)0x0, 255, 0x0}, /* BZ 174799. */ + {__LINE__, 0x0, (const unsigned char *)0x0, 256, 0x0}, + {__LINE__, 0x0, (const unsigned char *)0x0, 257, 0x0}, + {__LINE__, 0x0, (const unsigned char *)0x0, 32767, 0x0}, + {__LINE__, 0x0, (const unsigned char *)0x0, 32768, 0x0}, + {__LINE__, 0x0, (const unsigned char *)0x0, 32769, 0x0}, + {__LINE__, 0x0, (const unsigned char *)"", 0, 0x0}, + {__LINE__, 0xffffffff, (const unsigned char *)"", 0, 0xffffffff}, + {__LINE__, 0x0, (const unsigned char *)"abacus", 6, 0xc3d7115b}, + {__LINE__, 0x0, (const unsigned char *)"backlog", 7, 0x269205}, + {__LINE__, 0x0, (const unsigned char *)"campfire", 8, 0x22a515f8}, + {__LINE__, 0x0, (const unsigned char *)"delta", 5, 0x9643fed9}, + {__LINE__, 0x0, (const unsigned char *)"executable", 10, 0xd68eda01}, + {__LINE__, 0x0, (const unsigned char *)"file", 4, 0x8c9f3610}, + {__LINE__, 0x0, (const unsigned char *)"greatest", 8, 0xc1abd6cd}, + {__LINE__, 0x0, (const unsigned char *)"hello", 5, 0x3610a686}, + {__LINE__, 0x0, (const unsigned char *)"inverter", 8, 0xc9e962c9}, + {__LINE__, 0x0, (const unsigned char *)"jigsaw", 6, 0xce4e3f69}, + {__LINE__, 0x0, (const unsigned char *)"karate", 6, 0x890be0e2}, + {__LINE__, 0x0, (const unsigned char *)"landscape", 9, 0xc4e0330b}, + {__LINE__, 0x0, (const unsigned char *)"machine", 7, 0x1505df84}, + {__LINE__, 0x0, (const unsigned char *)"nanometer", 9, 0xd4e19f39}, + {__LINE__, 0x0, (const unsigned char *)"oblivion", 8, 0xdae9de77}, + {__LINE__, 0x0, (const unsigned char *)"panama", 6, 0x66b8979c}, + {__LINE__, 0x0, (const unsigned char *)"quest", 5, 0x4317f817}, + {__LINE__, 0x0, (const unsigned char *)"resource", 8, 0xbc91f416}, + {__LINE__, 0x0, (const unsigned char *)"secret", 6, 0x5ca2e8e5}, + {__LINE__, 0x0, (const unsigned char *)"test", 4, 0xd87f7e0c}, + {__LINE__, 0x0, (const unsigned char *)"ultimate", 8, 0x3fc79b0b}, + {__LINE__, 0x0, (const unsigned char *)"vector", 6, 0x1b6e485b}, + {__LINE__, 0x0, (const unsigned char *)"walrus", 6, 0xbe769b97}, + {__LINE__, 0x0, (const unsigned char *)"xeno", 4, 0xe7a06444}, + {__LINE__, 0x0, (const unsigned char *)"yelling", 7, 0xfe3944e5}, + {__LINE__, 0x0, (const unsigned char *)"zlib", 4, 0x73887d3a}, + {__LINE__, 0x0, (const unsigned char *)"4BJD7PocN1VqX0jXVpWB", 20, 0xd487a5a1}, + {__LINE__, 0x0, (const unsigned char *)"F1rPWI7XvDs6nAIRx41l", 20, 0x61a0132e}, + {__LINE__, 0x0, (const unsigned char *)"ldhKlsVkPFOveXgkGtC2", 20, 0xdf02f76}, + {__LINE__, 0x0, (const unsigned char *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x579b2b0a}, + {__LINE__, 0x0, (const unsigned char *)"0l1tw7GOcem06Ddu7yn4", 20, 0xf7d16e2d}, + {__LINE__, 0x0, (const unsigned char *)"MCr47CjPIn9R1IvE1Tm5", 20, 0x731788f5}, + {__LINE__, 0x0, (const unsigned char *)"UcixbzPKTIv0SvILHVdO", 20, 0x7112bb11}, + {__LINE__, 0x0, (const unsigned char *)"dGnAyAhRQDsWw0ESou24", 20, 0xf32a0dac}, + {__LINE__, 0x0, (const unsigned char *)"di0nvmY9UYMYDh0r45XT", 20, 0x625437bb}, + {__LINE__, 0x0, (const unsigned char *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x896930f9}, + {__LINE__, 0x0, (const unsigned char *)"ZhrANFIiIvRnqClIVyeD", 20, 0x8579a37}, + {__LINE__, 0x0, (const unsigned char *)"v7Q9ehzioTOVeDIZioT1", 20, 0x632aa8e0}, + {__LINE__, 0x0, (const unsigned char *)"Yod5hEeKcYqyhfXbhxj2", 20, 0xc829af29}, + {__LINE__, 0x0, (const unsigned char *)"GehSWY2ay4uUKhehXYb0", 20, 0x1b08b7e8}, + {__LINE__, 0x0, (const unsigned char *)"kwytJmq6UqpflV8Y8GoE", 20, 0x4e33b192}, + {__LINE__, 0x0, (const unsigned char *)"70684206568419061514", 20, 0x59a179f0}, + {__LINE__, 0x0, (const unsigned char *)"42015093765128581010", 20, 0xcd1013d7}, + {__LINE__, 0x0, (const unsigned char *)"88214814356148806939", 20, 0xab927546}, + {__LINE__, 0x0, (const unsigned char *)"43472694284527343838", 20, 0x11f3b20c}, + {__LINE__, 0x0, (const unsigned char *)"49769333513942933689", 20, 0xd562d4ca}, + {__LINE__, 0x0, (const unsigned char *)"54979784887993251199", 20, 0x233395f7}, + {__LINE__, 0x0, (const unsigned char *)"58360544869206793220", 20, 0x2d167fd5}, + {__LINE__, 0x0, (const unsigned char *)"27347953487840714234", 20, 0x8b5108ba}, + {__LINE__, 0x0, (const unsigned char *)"07650690295365319082", 20, 0xc46b3cd8}, + {__LINE__, 0x0, (const unsigned char *)"42655507906821911703", 20, 0xc10b2662}, + {__LINE__, 0x0, (const unsigned char *)"29977409200786225655", 20, 0xc9a0f9d2}, + {__LINE__, 0x0, (const unsigned char *)"85181542907229116674", 20, 0x9341357b}, + {__LINE__, 0x0, (const unsigned char *)"87963594337989416799", 20, 0xf0424937}, + {__LINE__, 0x0, (const unsigned char *)"21395988329504168551", 20, 0xd7c4c31f}, + {__LINE__, 0x0, (const unsigned char *)"51991013580943379423", 20, 0xf11edcc4}, + {__LINE__, 0x0, (const unsigned char *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x40795df4}, + {__LINE__, 0x0, (const unsigned char *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0xdd61a631}, + {__LINE__, 0x0, (const unsigned char *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0xca907a99}, + {__LINE__, 0x0, (const unsigned char *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0xf652deac}, + {__LINE__, 0x0, (const unsigned char *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0xaf39a5a9}, + {__LINE__, 0x0, (const unsigned char *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x6bebb4cf}, + {__LINE__, 0x0, (const unsigned char *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x76430bac}, + {__LINE__, 0x0, (const unsigned char *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x6c80c388}, + {__LINE__, 0x0, (const unsigned char *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xd54d977d}, + {__LINE__, 0x0, (const unsigned char *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0xe3966ad5}, + {__LINE__, 0x0, (const unsigned char *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0xe7c71db9}, + {__LINE__, 0x0, (const unsigned char *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xeaa52777}, + {__LINE__, 0x0, (const unsigned char *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xcd472048}, + {__LINE__, 0x7a30360d, (const unsigned char *)"abacus", 6, 0xf8655a84}, + {__LINE__, 0x6fd767ee, (const unsigned char *)"backlog", 7, 0x1ed834b1}, + {__LINE__, 0xefeb7589, (const unsigned char *)"campfire", 8, 0x686cfca}, + {__LINE__, 0x61cf7e6b, (const unsigned char *)"delta", 5, 0x1554e4b1}, + {__LINE__, 0xdc712e2, (const unsigned char *)"executable", 10, 0x761b4254}, + {__LINE__, 0xad23c7fd, (const unsigned char *)"file", 4, 0x7abdd09b}, + {__LINE__, 0x85cb2317, (const unsigned char *)"greatest", 8, 0x4ba91c6b}, + {__LINE__, 0x9eed31b0, (const unsigned char *)"inverter", 8, 0xd5e78ba5}, + {__LINE__, 0xb94f34ca, (const unsigned char *)"jigsaw", 6, 0x23649109}, + {__LINE__, 0xab058a2, (const unsigned char *)"karate", 6, 0xc5591f41}, + {__LINE__, 0x5bff2b7a, (const unsigned char *)"landscape", 9, 0xf10eb644}, + {__LINE__, 0x605c9a5f, (const unsigned char *)"machine", 7, 0xbaa0a636}, + {__LINE__, 0x51bdeea5, (const unsigned char *)"nanometer", 9, 0x6af89afb}, + {__LINE__, 0x85c21c79, (const unsigned char *)"oblivion", 8, 0xecae222b}, + {__LINE__, 0x97216f56, (const unsigned char *)"panama", 6, 0x47dffac4}, + {__LINE__, 0x18444af2, (const unsigned char *)"quest", 5, 0x70c2fe36}, + {__LINE__, 0xbe6ce359, (const unsigned char *)"resource", 8, 0x1471d925}, + {__LINE__, 0x843071f1, (const unsigned char *)"secret", 6, 0x50c9a0db}, + {__LINE__, 0xf2480c60, (const unsigned char *)"ultimate", 8, 0xf973daf8}, + {__LINE__, 0x2d2feb3d, (const unsigned char *)"vector", 6, 0x344ac03d}, + {__LINE__, 0x7490310a, (const unsigned char *)"walrus", 6, 0x6d1408ef}, + {__LINE__, 0x97d247d4, (const unsigned char *)"xeno", 4, 0xe62670b5}, + {__LINE__, 0x93cf7599, (const unsigned char *)"yelling", 7, 0x1b36da38}, + {__LINE__, 0x73c84278, (const unsigned char *)"zlib", 4, 0x6432d127}, + {__LINE__, 0x228a87d1, (const unsigned char *)"4BJD7PocN1VqX0jXVpWB", 20, 0x997107d0}, + {__LINE__, 0xa7a048d0, (const unsigned char *)"F1rPWI7XvDs6nAIRx41l", 20, 0xdc567274}, + {__LINE__, 0x1f0ded40, (const unsigned char *)"ldhKlsVkPFOveXgkGtC2", 20, 0xdcc63870}, + {__LINE__, 0xa804a62f, (const unsigned char *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x6926cffd}, + {__LINE__, 0x508fae6a, (const unsigned char *)"0l1tw7GOcem06Ddu7yn4", 20, 0xb52b38bc}, + {__LINE__, 0xe5adaf4f, (const unsigned char *)"MCr47CjPIn9R1IvE1Tm5", 20, 0xf83b8178}, + {__LINE__, 0x67136a40, (const unsigned char *)"UcixbzPKTIv0SvILHVdO", 20, 0xc5213070}, + {__LINE__, 0xb00c4a10, (const unsigned char *)"dGnAyAhRQDsWw0ESou24", 20, 0xbc7648b0}, + {__LINE__, 0x2e0c84b5, (const unsigned char *)"di0nvmY9UYMYDh0r45XT", 20, 0xd8123a72}, + {__LINE__, 0x81238d44, (const unsigned char *)"2XKDwHfAhFsV0RhbqtvH", 20, 0xd5ac5620}, + {__LINE__, 0xf853aa92, (const unsigned char *)"ZhrANFIiIvRnqClIVyeD", 20, 0xceae099d}, + {__LINE__, 0x5a692325, (const unsigned char *)"v7Q9ehzioTOVeDIZioT1", 20, 0xb07d2b24}, + {__LINE__, 0x3275b9f, (const unsigned char *)"Yod5hEeKcYqyhfXbhxj2", 20, 0x24ce91df}, + {__LINE__, 0x38371feb, (const unsigned char *)"GehSWY2ay4uUKhehXYb0", 20, 0x707b3b30}, + {__LINE__, 0xafc8bf62, (const unsigned char *)"kwytJmq6UqpflV8Y8GoE", 20, 0x16abc6a9}, + {__LINE__, 0x9b07db73, (const unsigned char *)"70684206568419061514", 20, 0xae1fb7b7}, + {__LINE__, 0xe75b214, (const unsigned char *)"42015093765128581010", 20, 0xd4eecd2d}, + {__LINE__, 0x72d0fe6f, (const unsigned char *)"88214814356148806939", 20, 0x4660ec7}, + {__LINE__, 0xf857a4b1, (const unsigned char *)"43472694284527343838", 20, 0xfd8afdf7}, + {__LINE__, 0x54b8e14, (const unsigned char *)"49769333513942933689", 20, 0xc6d1b5f2}, + {__LINE__, 0xd6aa5616, (const unsigned char *)"54979784887993251199", 20, 0x32476461}, + {__LINE__, 0x11e63098, (const unsigned char *)"58360544869206793220", 20, 0xd917cf1a}, + {__LINE__, 0xbe92385, (const unsigned char *)"27347953487840714234", 20, 0x4ad14a12}, + {__LINE__, 0x49511de0, (const unsigned char *)"07650690295365319082", 20, 0xe37b5c6c}, + {__LINE__, 0x3db13bc1, (const unsigned char *)"42655507906821911703", 20, 0x7cc497f1}, + {__LINE__, 0xbb899bea, (const unsigned char *)"29977409200786225655", 20, 0x99781bb2}, + {__LINE__, 0xf6cd9436, (const unsigned char *)"85181542907229116674", 20, 0x132256a1}, + {__LINE__, 0x9109e6c3, (const unsigned char *)"87963594337989416799", 20, 0xbfdb2c83}, + {__LINE__, 0x75770fc, (const unsigned char *)"21395988329504168551", 20, 0x8d9d1e81}, + {__LINE__, 0x69b1d19b, (const unsigned char *)"51991013580943379423", 20, 0x7b6d4404}, + {__LINE__, 0xc6132975, (const unsigned char *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x8619f010}, + {__LINE__, 0xd58cb00c, (const unsigned char *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0x15746ac3}, + {__LINE__, 0xb63b8caa, (const unsigned char *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0xaccf812f}, + {__LINE__, 0x8a45a2b8, (const unsigned char *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x78af45de}, + {__LINE__, 0xcbe95b78, (const unsigned char *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x25b06b59}, + {__LINE__, 0x4ef8a54b, (const unsigned char *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x4ba0d08f}, + {__LINE__, 0x76ad267a, (const unsigned char *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0xe26b6aac}, + {__LINE__, 0x569e613c, (const unsigned char *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x7e2b0a66}, + {__LINE__, 0x36aa61da, (const unsigned char *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xb3430dc7}, + {__LINE__, 0xf67222df, (const unsigned char *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x626c17a}, + {__LINE__, 0x74b34fd3, (const unsigned char *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0xccf98060}, + {__LINE__, 0x351fd770, (const unsigned char *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xd8b95312}, + {__LINE__, 0xc45aef77, (const unsigned char *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xbb1c9912}, + {__LINE__, 0xc45aef77, (const unsigned char *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 600, 0x888AFA5B} +}; + +static const int test_size = sizeof(tests) / sizeof(tests[0]); + +int main(void) { + int i; + for (i = 0; i < test_size; i++) { + test_crc32(tests[i].crc, tests[i].buf, tests[i].len, tests[i].expect, tests[i].line); + } + return 0; +} From db59b636765af09b78a7f1d6d3333aa5270be5f0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 2 Jul 2021 16:56:20 -0700 Subject: [PATCH 127/798] Added CRC32_INITIAL_VALUE to prevent initial call to crc32 function. --- arch/x86/crc_folding.c | 4 +--- arch/x86/crc_folding.h | 2 +- crc32.c | 5 ++--- inflate.c | 4 ++-- zutil.h | 1 + 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/x86/crc_folding.c b/arch/x86/crc_folding.c index 2f38f6332e..de087e3440 100644 --- a/arch/x86/crc_folding.c +++ b/arch/x86/crc_folding.c @@ -24,14 +24,12 @@ #include "crc_folding.h" -Z_INTERNAL uint32_t crc_fold_init(unsigned int crc0[4 * 5]) { +Z_INTERNAL void crc_fold_init(unsigned int crc0[4 * 5]) { /* CRC_SAVE */ _mm_storeu_si128((__m128i *)crc0 + 0, _mm_cvtsi32_si128(0x9db42487)); _mm_storeu_si128((__m128i *)crc0 + 1, _mm_setzero_si128()); _mm_storeu_si128((__m128i *)crc0 + 2, _mm_setzero_si128()); _mm_storeu_si128((__m128i *)crc0 + 3, _mm_setzero_si128()); - - return 0; } static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { diff --git a/arch/x86/crc_folding.h b/arch/x86/crc_folding.h index a9ed41f3c0..3af7f079a1 100644 --- a/arch/x86/crc_folding.h +++ b/arch/x86/crc_folding.h @@ -12,7 +12,7 @@ #include "../../zutil.h" -Z_INTERNAL uint32_t crc_fold_init(unsigned int crc0[4 * 5]); +Z_INTERNAL void crc_fold_init(unsigned int crc0[4 * 5]); Z_INTERNAL uint32_t crc_fold_512to32(unsigned int crc0[4 * 5]); Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *, const unsigned char *, long); diff --git a/crc32.c b/crc32.c index 74d9c414c2..3cb066ce5e 100644 --- a/crc32.c +++ b/crc32.c @@ -183,11 +183,10 @@ Z_INTERNAL void crc_reset(deflate_state *const s) { #ifdef X86_PCLMULQDQ_CRC x86_check_features(); if (x86_cpu_has_pclmulqdq) { - s->strm->adler = crc_fold_init(s->crc0); - return; + crc_fold_init(s->crc0); } #endif - s->strm->adler = PREFIX(crc32)(0L, NULL, 0); + s->strm->adler = CRC32_INITIAL_VALUE; } Z_INTERNAL void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size) { diff --git a/inflate.c b/inflate.c index 6ba6e83dea..45c90232ad 100644 --- a/inflate.c +++ b/inflate.c @@ -410,7 +410,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ if (state->wbits == 0) state->wbits = 15; - state->check = PREFIX(crc32)(0L, NULL, 0); + state->check = CRC32_INITIAL_VALUE; CRC2(state->check, hold); INITBITS(); state->mode = FLAGS; @@ -578,7 +578,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } - strm->adler = state->check = PREFIX(crc32)(0L, NULL, 0); + strm->adler = state->check = CRC32_INITIAL_VALUE; state->mode = TYPE; break; #endif diff --git a/zutil.h b/zutil.h index bcb9ed12fc..30bd6394ea 100644 --- a/zutil.h +++ b/zutil.h @@ -76,6 +76,7 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ #define ADLER32_INITIAL_VALUE 1 /* initial adler-32 hash value */ +#define CRC32_INITIAL_VALUE 0 /* initial crc-32 hash value */ /* target dependencies */ From d802e8900f2a09b5a2d0710bfee3e7b3adc87567 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 2 Jul 2021 17:44:08 -0700 Subject: [PATCH 128/798] Move crc32 folding functions into functable. --- CMakeLists.txt | 4 +- Makefile.in | 2 + arch/x86/INDEX.md | 2 +- arch/x86/Makefile.in | 10 +-- .../{crc_folding.c => crc32_fold_pclmulqdq.c} | 71 +++++++++---------- arch/x86/crc_folding.h | 19 ----- configure | 4 +- crc32.c | 31 -------- crc32_fold.c | 23 ++++++ crc32_fold.h | 17 +++++ deflate.c | 19 ++--- deflate.h | 6 +- functable.c | 44 ++++++++++++ functable.h | 4 ++ win32/Makefile.a64 | 2 + win32/Makefile.arm | 2 + win32/Makefile.msc | 5 +- zutil.h | 2 +- 18 files changed, 153 insertions(+), 114 deletions(-) rename arch/x86/{crc_folding.c => crc32_fold_pclmulqdq.c} (89%) delete mode 100644 arch/x86/crc_folding.h create mode 100644 crc32_fold.c create mode 100644 crc32_fold.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c148222d0..dcd07ad602 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -766,7 +766,7 @@ if(WITH_OPTIM) check_pclmulqdq_intrinsics() if(HAVE_PCLMULQDQ_INTRIN AND HAVE_SSSE3_INTRIN) add_definitions(-DX86_PCLMULQDQ_CRC) - set(PCLMULQDQ_SRCS ${ARCHDIR}/crc_folding.c) + set(PCLMULQDQ_SRCS ${ARCHDIR}/crc32_fold_pclmulqdq.c) add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") @@ -849,6 +849,7 @@ set(ZLIB_PRIVATE_HDRS crc32_p.h crc32_tbl.h crc32_comb_tbl.h + crc32_fold.h deflate.h deflate_p.h functable.h @@ -873,6 +874,7 @@ set(ZLIB_SRCS compress.c crc32.c crc32_comb.c + crc32_fold.c deflate.c deflate_fast.c deflate_huff.c diff --git a/Makefile.in b/Makefile.in index 19901ef479..fb6a30c247 100644 --- a/Makefile.in +++ b/Makefile.in @@ -78,6 +78,7 @@ OBJZ = \ compress.o \ crc32.o \ crc32_comb.o \ + crc32_fold.o \ deflate.o \ deflate_fast.o \ deflate_huff.o \ @@ -113,6 +114,7 @@ PIC_OBJZ = \ compress.lo \ crc32.lo \ crc32_comb.lo \ + crc32_fold.lo \ deflate.lo \ deflate_fast.lo \ deflate_huff.lo \ diff --git a/arch/x86/INDEX.md b/arch/x86/INDEX.md index d32bfe8b1d..e20245a5e1 100644 --- a/arch/x86/INDEX.md +++ b/arch/x86/INDEX.md @@ -4,5 +4,5 @@ Contents |Name|Description| |:-|:-| |deflate_quick.c|SSE4 optimized deflate strategy for use as level 1| -|crc_folding.c|SSE4 + PCLMULQDQ optimized CRC folding implementation| +|crc32_fold_pclmulqdq.c|SSE4 + PCLMULQDQ optimized CRC folding implementation| |slide_hash_sse2.c|SSE2 optimized slide_hash| diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index fa153592a5..c5e588e70d 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -28,7 +28,7 @@ all: \ compare258_avx.o compare258_avx.lo \ compare258_sse.o compare258_sse.lo \ insert_string_sse.o insert_string_sse.lo \ - crc_folding.o crc_folding.lo \ + crc32_fold_pclmulqdq.o crc32_fold_pclmulqdq.lo \ slide_hash_avx.o slide_hash_avx.lo \ slide_hash_sse.o slide_hash_sse.lo @@ -68,11 +68,11 @@ insert_string_sse.o: insert_string_sse.lo: $(CC) $(SFLAGS) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c -crc_folding.o: - $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c +crc32_fold_pclmulqdq.o: + $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c -crc_folding.lo: - $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc_folding.c +crc32_fold_pclmulqdq.lo: + $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c slide_hash_avx.o: $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx.c diff --git a/arch/x86/crc_folding.c b/arch/x86/crc32_fold_pclmulqdq.c similarity index 89% rename from arch/x86/crc_folding.c rename to arch/x86/crc32_fold_pclmulqdq.c index de087e3440..30a24ea869 100644 --- a/arch/x86/crc_folding.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -17,19 +17,22 @@ */ #ifdef X86_PCLMULQDQ_CRC +#include "../../zutil.h" #include #include #include -#include "crc_folding.h" +#include "../../crc32_fold.h" -Z_INTERNAL void crc_fold_init(unsigned int crc0[4 * 5]) { +Z_INTERNAL uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc) { /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)crc0 + 0, _mm_cvtsi32_si128(0x9db42487)); - _mm_storeu_si128((__m128i *)crc0 + 1, _mm_setzero_si128()); - _mm_storeu_si128((__m128i *)crc0 + 2, _mm_setzero_si128()); - _mm_storeu_si128((__m128i *)crc0 + 3, _mm_setzero_si128()); + _mm_storeu_si128((__m128i *)crc->fold + 0, _mm_cvtsi32_si128(0x9db42487)); + _mm_storeu_si128((__m128i *)crc->fold + 1, _mm_setzero_si128()); + _mm_storeu_si128((__m128i *)crc->fold + 2, _mm_setzero_si128()); + _mm_storeu_si128((__m128i *)crc->fold + 3, _mm_setzero_si128()); + + return 0; } static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { @@ -224,16 +227,16 @@ static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, *xmm_crc3 = _mm_castps_si128(ps_res); } -Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *dst, const unsigned char *src, long len) { +Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { unsigned long algn_diff; __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; char ALIGNED_(16) partial_buf[16] = { 0 }; /* CRC_LOAD */ - __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)crc0 + 0); - __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)crc0 + 1); - __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)crc0 + 2); - __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)crc0 + 3); + __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)crc->fold + 0); + __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)crc->fold + 1); + __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)crc->fold + 2); + __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)crc->fold + 3); __m128i xmm_crc_part; if (len < 16) { @@ -260,7 +263,7 @@ Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *dst, cons xmm_crc_part = _mm_setzero_si128(); } - while ((len -= 64) >= 0) { + while (len >= 64) { /* CRC_LOAD */ xmm_t0 = _mm_load_si128((__m128i *)src); xmm_t1 = _mm_load_si128((__m128i *)src + 1); @@ -282,14 +285,13 @@ Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *dst, cons src += 64; dst += 64; + len -= 64; } /* * len = num bytes left - 64 */ - if (len + 16 >= 0) { - len += 16; - + if (len >= 48) { xmm_t0 = _mm_load_si128((__m128i *)src); xmm_t1 = _mm_load_si128((__m128i *)src + 1); xmm_t2 = _mm_load_si128((__m128i *)src + 2); @@ -303,15 +305,13 @@ Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *dst, cons xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); - + len -= 48; if (len == 0) goto done; dst += 48; memcpy(&xmm_crc_part, (__m128i *)src + 3, len); - } else if (len + 32 >= 0) { - len += 32; - + } else if (len >= 32) { xmm_t0 = _mm_load_si128((__m128i *)src); xmm_t1 = _mm_load_si128((__m128i *)src + 1); @@ -323,14 +323,13 @@ Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *dst, cons xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); + len -= 32; if (len == 0) goto done; dst += 32; memcpy(&xmm_crc_part, (__m128i *)src + 2, len); - } else if (len + 48 >= 0) { - len += 48; - + } else if (len >= 16) { xmm_t0 = _mm_load_si128((__m128i *)src); fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); @@ -339,13 +338,13 @@ Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *dst, cons xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + len -= 16; if (len == 0) goto done; dst += 16; memcpy(&xmm_crc_part, (__m128i *)src + 1, len); } else { - len += 64; if (len == 0) goto done; memcpy(&xmm_crc_part, src, len); @@ -358,11 +357,11 @@ Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *dst, cons partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); done: /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)crc0 + 0, xmm_crc0); - _mm_storeu_si128((__m128i *)crc0 + 1, xmm_crc1); - _mm_storeu_si128((__m128i *)crc0 + 2, xmm_crc2); - _mm_storeu_si128((__m128i *)crc0 + 3, xmm_crc3); - _mm_storeu_si128((__m128i *)crc0 + 4, xmm_crc_part); + _mm_storeu_si128((__m128i *)crc->fold + 0, xmm_crc0); + _mm_storeu_si128((__m128i *)crc->fold + 1, xmm_crc1); + _mm_storeu_si128((__m128i *)crc->fold + 2, xmm_crc2); + _mm_storeu_si128((__m128i *)crc->fold + 3, xmm_crc3); + _mm_storeu_si128((__m128i *)crc->fold + 4, xmm_crc_part); } static const unsigned ALIGNED_(16) crc_k[] = { @@ -382,18 +381,17 @@ static const unsigned ALIGNED_(16) crc_mask2[4] = { 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; -uint32_t Z_INTERNAL crc_fold_512to32(unsigned int crc0[4 * 5]) { +Z_INTERNAL uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc) { const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); - uint32_t crc; __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; /* CRC_LOAD */ - __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)crc0 + 0); - __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)crc0 + 1); - __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)crc0 + 2); - __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)crc0 + 3); + __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)crc->fold + 0); + __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)crc->fold + 1); + __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)crc->fold + 2); + __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)crc->fold + 3); /* * k1 @@ -447,8 +445,9 @@ uint32_t Z_INTERNAL crc_fold_512to32(unsigned int crc0[4 * 5]) { xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc2); xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_crc1); - crc = (uint32_t)_mm_extract_epi32(xmm_crc3, 2); - return ~crc; + crc->value = ~((uint32_t)_mm_extract_epi32(xmm_crc3, 2)); + + return crc->value; } #endif diff --git a/arch/x86/crc_folding.h b/arch/x86/crc_folding.h deleted file mode 100644 index 3af7f079a1..0000000000 --- a/arch/x86/crc_folding.h +++ /dev/null @@ -1,19 +0,0 @@ -/* crc_folding.h - * - * Compute the CRC32 using a parallelized folding approach with the PCLMULQDQ - * instruction. - * - * Copyright (C) 2013 Intel Corporation Jim Kukunas - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef CRC_FOLDING_H_ -#define CRC_FOLDING_H_ - -#include "../../zutil.h" - -Z_INTERNAL void crc_fold_init(unsigned int crc0[4 * 5]); -Z_INTERNAL uint32_t crc_fold_512to32(unsigned int crc0[4 * 5]); -Z_INTERNAL void crc_fold_copy(unsigned int crc0[4 * 5], unsigned char *, const unsigned char *, long); - -#endif diff --git a/configure b/configure index 596ce6046a..765ea44359 100755 --- a/configure +++ b/configure @@ -1353,8 +1353,8 @@ case "${ARCH}" in if test ${HAVE_PCLMULQDQ_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_PCLMULQDQ_CRC" SFLAGS="${SFLAGS} -DX86_PCLMULQDQ_CRC" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc_folding.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc_folding.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_fold_pclmulqdq.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_fold_pclmulqdq.lo" fi fi ;; diff --git a/crc32.c b/crc32.c index 3cb066ce5e..c519d874aa 100644 --- a/crc32.c +++ b/crc32.c @@ -168,34 +168,3 @@ Z_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_t l return ZSWAP32(c); } #endif /* BYTE_ORDER == BIG_ENDIAN */ - -#ifdef X86_PCLMULQDQ_CRC -#include "arch/x86/x86.h" -#include "arch/x86/crc_folding.h" - -Z_INTERNAL void crc_finalize(deflate_state *const s) { - if (x86_cpu_has_pclmulqdq) - s->strm->adler = crc_fold_512to32(s->crc0); -} -#endif - -Z_INTERNAL void crc_reset(deflate_state *const s) { -#ifdef X86_PCLMULQDQ_CRC - x86_check_features(); - if (x86_cpu_has_pclmulqdq) { - crc_fold_init(s->crc0); - } -#endif - s->strm->adler = CRC32_INITIAL_VALUE; -} - -Z_INTERNAL void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size) { -#ifdef X86_PCLMULQDQ_CRC - if (x86_cpu_has_pclmulqdq) { - crc_fold_copy(strm->state->crc0, dst, strm->next_in, size); - return; - } -#endif - memcpy(dst, strm->next_in, size); - strm->adler = PREFIX(crc32)(strm->adler, dst, size); -} diff --git a/crc32_fold.c b/crc32_fold.c new file mode 100644 index 0000000000..7771c369ce --- /dev/null +++ b/crc32_fold.c @@ -0,0 +1,23 @@ +/* crc32_fold.c -- crc32 folding interface + * Copyright (C) 2021 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#include "zbuild.h" +#include "zutil.h" +#include "functable.h" + +#include "crc32_fold.h" + +Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc) { + crc->value = CRC32_INITIAL_VALUE; + return crc->value; +} + +Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { + crc->value = functable.crc32(crc->value, src, len); + memcpy(dst, src, len); +} + +Z_INTERNAL uint32_t crc32_fold_final_c(crc32_fold *crc) { + return crc->value; +} diff --git a/crc32_fold.h b/crc32_fold.h new file mode 100644 index 0000000000..ec6d13d157 --- /dev/null +++ b/crc32_fold.h @@ -0,0 +1,17 @@ +/* crc32_fold.h -- crc32 folding interface + * Copyright (C) 2021 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ +#ifndef CRC32_FOLD_H_ +#define CRC32_FOLD_H_ + +typedef struct crc32_fold_s { + uint32_t ALIGNED_(16) fold[4 * 5]; + uint32_t value; +} crc32_fold; + +Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc); +Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +Z_INTERNAL uint32_t crc32_fold_final_c(crc32_fold *crc); + +#endif diff --git a/deflate.c b/deflate.c index c1ee6d4104..79fa85dbc4 100644 --- a/deflate.c +++ b/deflate.c @@ -114,12 +114,6 @@ static void lm_set_level (deflate_state *s, int level); static void lm_init (deflate_state *s); Z_INTERNAL unsigned read_buf (PREFIX3(stream) *strm, unsigned char *buf, unsigned size); -extern void crc_reset(deflate_state *const s); -#ifdef X86_PCLMULQDQ_CRC -extern void crc_finalize(deflate_state *const s); -#endif -extern void copy_with_crc(PREFIX3(stream) *strm, unsigned char *dst, unsigned long size); - extern uint32_t update_hash_roll (deflate_state *const s, uint32_t h, uint32_t val); extern void insert_string_roll (deflate_state *const s, uint32_t str, uint32_t count); extern Pos quick_insert_string_roll(deflate_state *const s, uint32_t str); @@ -454,7 +448,7 @@ int32_t Z_EXPORT PREFIX(deflateResetKeep)(PREFIX3(stream) *strm) { #ifdef GZIP if (s->wrap == 2) - crc_reset(s); + strm->adler = functable.crc32_fold_reset(&s->crc_fold); else #endif strm->adler = ADLER32_INITIAL_VALUE; @@ -780,7 +774,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { #ifdef GZIP if (s->status == GZIP_STATE) { /* gzip header */ - crc_reset(s); + functable.crc32_fold_reset(&s->crc_fold); put_byte(s, 31); put_byte(s, 139); put_byte(s, 8); @@ -897,7 +891,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { } } put_short(s, (uint16_t)strm->adler); - crc_reset(s); + functable.crc32_fold_reset(&s->crc_fold); } s->status = BUSY_STATE; @@ -968,9 +962,8 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { /* Write the trailer */ #ifdef GZIP if (s->wrap == 2) { -# ifdef X86_PCLMULQDQ_CRC - crc_finalize(s); -# endif + strm->adler = functable.crc32_fold_final(&s->crc_fold); + put_uint32(s, strm->adler); put_uint32(s, (uint32_t)strm->total_in); } else @@ -1082,7 +1075,7 @@ Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned memcpy(buf, strm->next_in, len); #ifdef GZIP } else if (strm->state->wrap == 2) { - copy_with_crc(strm, buf, len); + functable.crc32_fold_copy(&strm->state->crc_fold, buf, strm->next_in, len); #endif } else { memcpy(buf, strm->next_in, len); diff --git a/deflate.h b/deflate.h index 8c443d0c1d..94ff239ce4 100644 --- a/deflate.h +++ b/deflate.h @@ -12,6 +12,7 @@ #include "zutil.h" #include "zendian.h" +#include "crc32_fold.h" /* define NO_GZIP when compiling if you want to disable gzip header and trailer creation by deflate(). NO_GZIP would be used to avoid linking in @@ -210,10 +211,7 @@ struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ -#if defined(__x86_64__) || defined(_M_X64) || defined(__i386) || defined(_M_IX86) - /* Only used if X86_PCLMULQDQ_CRC is defined */ - unsigned crc0[4 * 5]; -#endif + crc32_fold ALIGNED_(16) crc_fold; /* used by trees.c: */ /* Didn't use ct_data typedef below to suppress compiler warning */ diff --git a/functable.c b/functable.c index 36eec10231..d8b561b5a9 100644 --- a/functable.c +++ b/functable.c @@ -73,6 +73,17 @@ extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t le extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len); #endif +/* CRC32 folding */ +extern uint32_t crc32_fold_reset_c(crc32_fold *crc); +extern void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t crc32_fold_final_c(crc32_fold *crc); + +#ifdef X86_PCLMULQDQ_CRC +extern uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc); +extern void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc); +#endif + /* memory chunking */ extern uint32_t chunksize_c(void); extern uint8_t* chunkcopy_c(uint8_t *out, uint8_t const *from, unsigned len); @@ -304,6 +315,36 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ return functable.adler32(adler, buf, len); } +Z_INTERNAL uint32_t crc32_fold_reset_stub(crc32_fold *crc) { + functable.crc32_fold_reset = crc32_fold_reset_c; + cpu_check_features(); +#ifdef X86_PCLMULQDQ_CRC + if (x86_cpu_has_pclmulqdq) + functable.crc32_fold_reset = crc32_fold_reset_pclmulqdq; +#endif + return functable.crc32_fold_reset(crc); +} + +Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { + functable.crc32_fold_copy = crc32_fold_copy_c; + cpu_check_features(); +#ifdef X86_PCLMULQDQ_CRC + if (x86_cpu_has_pclmulqdq) + functable.crc32_fold_copy = crc32_fold_copy_pclmulqdq; +#endif + functable.crc32_fold_copy(crc, dst, src, len); +} + +Z_INTERNAL uint32_t crc32_fold_final_stub(crc32_fold *crc) { + functable.crc32_fold_final = crc32_fold_final_c; + cpu_check_features(); +#ifdef X86_PCLMULQDQ_CRC + if (x86_cpu_has_pclmulqdq) + functable.crc32_fold_final = crc32_fold_final_pclmulqdq; +#endif + return functable.crc32_fold_final(crc); +} + Z_INTERNAL uint32_t chunksize_stub(void) { // Initialize default functable.chunksize = &chunksize_c; @@ -579,6 +620,9 @@ Z_INTERNAL Z_TLS struct functable_s functable = { quick_insert_string_stub, adler32_stub, crc32_stub, + crc32_fold_reset_stub, + crc32_fold_copy_stub, + crc32_fold_final_stub, slide_hash_stub, compare258_stub, longest_match_stub, diff --git a/functable.h b/functable.h index f4b17569ac..36039fcb27 100644 --- a/functable.h +++ b/functable.h @@ -7,6 +7,7 @@ #define FUNCTABLE_H_ #include "deflate.h" +#include "crc32_fold.h" struct functable_s { uint32_t (* update_hash) (deflate_state *const s, uint32_t h, uint32_t val); @@ -14,6 +15,9 @@ struct functable_s { Pos (* quick_insert_string)(deflate_state *const s, uint32_t str); uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, size_t len); uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); + uint32_t (* crc32_fold_reset) (crc32_fold *crc); + void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); + uint32_t (* crc32_fold_final) (crc32_fold *crc); void (* slide_hash) (deflate_state *s); uint32_t (* compare258) (const unsigned char *src0, const unsigned char *src1); uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 8746e5cbfd..418558b137 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -49,6 +49,7 @@ OBJS = \ compress.obj \ crc32.obj \ crc32_comb.obj \ + crc32_fold.obj \ deflate.obj \ deflate_fast.obj \ deflate_huff.obj \ @@ -168,6 +169,7 @@ compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h +crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_huff.obj: $(SRCDIR)/deflate_huff.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 8403043996..c44c4d8c86 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -52,6 +52,7 @@ OBJS = \ compress.obj \ crc32.obj \ crc32_comb.obj \ + crc32_fold.obj \ deflate.obj \ deflate_fast.obj \ deflate_huff.obj \ @@ -180,6 +181,7 @@ uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h +crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_huff.obj: $(SRCDIR)/deflate_huff.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 3110f7fe98..eec878f249 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -58,7 +58,8 @@ OBJS = \ compress.obj \ crc32.obj \ crc32_comb.obj \ - crc_folding.obj \ + crc32_fold.obj \ + crc32_fold_pclmulqdq.obj \ deflate.obj \ deflate_fast.obj \ deflate_huff.obj \ @@ -174,6 +175,8 @@ chunkset_avx.obj: $(SRCDIR)/arch/x86/chunkset_avx.c $(SRCDIR)/zbuild.h $(SRCDIR) chunkset_sse.obj: $(SRCDIR)/arch/x86/chunkset_sse.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h +crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h +crc32_fold_pclmulqdq.obj: $(SRCDIR)/arch/x86/crc32_fold_pclmulqdq.c $(SRCDIR)/crc32_fold.h $(SRCDIR)/zbuild.h deflate.obj: $(SRCDIR)/deflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_fast.obj: $(SRCDIR)/deflate_fast.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h deflate_huff.obj: $(SRCDIR)/deflate_huff.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/functable.h diff --git a/zutil.h b/zutil.h index 30bd6394ea..0a44f775c3 100644 --- a/zutil.h +++ b/zutil.h @@ -76,7 +76,7 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ #define ADLER32_INITIAL_VALUE 1 /* initial adler-32 hash value */ -#define CRC32_INITIAL_VALUE 0 /* initial crc-32 hash value */ +#define CRC32_INITIAL_VALUE 0 /* initial crc-32 hash value */ /* target dependencies */ From e128537d4db2a4bec431d75b92b7b8e01fbf8bd7 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 3 Jul 2021 12:40:55 -0700 Subject: [PATCH 129/798] Use static inline functions for crc32 folding load/save. --- arch/x86/crc32_fold_pclmulqdq.c | 73 +++++++++++++++------------------ 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 30a24ea869..9065298f50 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -25,16 +25,6 @@ #include "../../crc32_fold.h" -Z_INTERNAL uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc) { - /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)crc->fold + 0, _mm_cvtsi32_si128(0x9db42487)); - _mm_storeu_si128((__m128i *)crc->fold + 1, _mm_setzero_si128()); - _mm_storeu_si128((__m128i *)crc->fold + 2, _mm_setzero_si128()); - _mm_storeu_si128((__m128i *)crc->fold + 3, _mm_setzero_si128()); - - return 0; -} - static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); @@ -227,24 +217,45 @@ static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, *xmm_crc3 = _mm_castps_si128(ps_res); } +static inline void crc32_fold_load(__m128i *fold, __m128i *fold0, __m128i *fold1, __m128i *fold2, __m128i *fold3) { + *fold0 = _mm_load_si128(fold + 0); + *fold1 = _mm_load_si128(fold + 1); + *fold2 = _mm_load_si128(fold + 2); + *fold3 = _mm_load_si128(fold + 3); +} + +static inline void crc32_fold_save(__m128i *fold, __m128i fold0, __m128i fold1, __m128i fold2, __m128i fold3) { + _mm_storeu_si128(fold + 0, fold0); + _mm_storeu_si128(fold + 1, fold1); + _mm_storeu_si128(fold + 2, fold2); + _mm_storeu_si128(fold + 3, fold3); +} + +static inline void crc32_fold_save_partial(__m128i *fold, __m128i foldp) { + _mm_store_si128(fold + 4, foldp); +} + +Z_INTERNAL uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc) { + __m128i xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); + __m128i xmm_zero = _mm_setzero_si128(); + crc32_fold_save((__m128i *)&crc->fold, xmm_crc0, xmm_zero, xmm_zero, xmm_zero); + return 0; +} + Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { unsigned long algn_diff; __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; + __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3, xmm_crc_part; char ALIGNED_(16) partial_buf[16] = { 0 }; - /* CRC_LOAD */ - __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)crc->fold + 0); - __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)crc->fold + 1); - __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)crc->fold + 2); - __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)crc->fold + 3); - __m128i xmm_crc_part; + crc32_fold_load((__m128i *)&crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); if (len < 16) { if (len == 0) return; memcpy(partial_buf, src, len); - xmm_crc_part = _mm_loadu_si128((const __m128i *)partial_buf); + xmm_crc_part = _mm_load_si128((const __m128i *)partial_buf); memcpy(dst, partial_buf, len); goto partial; } @@ -264,19 +275,11 @@ Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const u } while (len >= 64) { - /* CRC_LOAD */ - xmm_t0 = _mm_load_si128((__m128i *)src); - xmm_t1 = _mm_load_si128((__m128i *)src + 1); - xmm_t2 = _mm_load_si128((__m128i *)src + 2); - xmm_t3 = _mm_load_si128((__m128i *)src + 3); + crc32_fold_load((__m128i *)src, &xmm_t0, &xmm_t1, &xmm_t2, &xmm_t3); fold_4(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); - /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)dst, xmm_t0); - _mm_storeu_si128((__m128i *)dst + 1, xmm_t1); - _mm_storeu_si128((__m128i *)dst + 2, xmm_t2); - _mm_storeu_si128((__m128i *)dst + 3, xmm_t3); + crc32_fold_save((__m128i *)dst, xmm_t0, xmm_t1, xmm_t2, xmm_t3); xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); @@ -356,12 +359,8 @@ Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const u partial: partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); done: - /* CRC_SAVE */ - _mm_storeu_si128((__m128i *)crc->fold + 0, xmm_crc0); - _mm_storeu_si128((__m128i *)crc->fold + 1, xmm_crc1); - _mm_storeu_si128((__m128i *)crc->fold + 2, xmm_crc2); - _mm_storeu_si128((__m128i *)crc->fold + 3, xmm_crc3); - _mm_storeu_si128((__m128i *)crc->fold + 4, xmm_crc_part); + crc32_fold_save((__m128i *)&crc->fold, xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3); + crc32_fold_save_partial((__m128i *)&crc->fold, xmm_crc_part); } static const unsigned ALIGNED_(16) crc_k[] = { @@ -384,14 +383,10 @@ static const unsigned ALIGNED_(16) crc_mask2[4] = { Z_INTERNAL uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc) { const __m128i xmm_mask = _mm_load_si128((__m128i *)crc_mask); const __m128i xmm_mask2 = _mm_load_si128((__m128i *)crc_mask2); - + __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3; __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; - /* CRC_LOAD */ - __m128i xmm_crc0 = _mm_loadu_si128((__m128i *)crc->fold + 0); - __m128i xmm_crc1 = _mm_loadu_si128((__m128i *)crc->fold + 1); - __m128i xmm_crc2 = _mm_loadu_si128((__m128i *)crc->fold + 2); - __m128i xmm_crc3 = _mm_loadu_si128((__m128i *)crc->fold + 3); + crc32_fold_load((__m128i *)&crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); /* * k1 From 0af8678307ef2ab976454a50ae299281185ba2f5 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 17 Aug 2021 10:12:37 -0700 Subject: [PATCH 130/798] Fixed undefined behavior of isgraph when character is not in the range 0 through 0xFF inclusive. --- trees.c | 2 +- trees_emit.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/trees.c b/trees.c index 2a5e2de946..5ff07636f4 100644 --- a/trees.c +++ b/trees.c @@ -308,7 +308,7 @@ Z_INTERNAL void gen_codes(ct_data *tree, int max_code, uint16_t *bl_count) { tree[n].Code = bi_reverse(next_code[len]++, len); Tracecv(tree != static_ltree, (stderr, "\nn %3d %c l %2d c %4x (%x) ", - n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + n, (isgraph(n & 0xff) ? n : ' '), len, tree[n].Code, next_code[len]-1)); } } diff --git a/trees_emit.h b/trees_emit.h index 52af7a409d..c957770878 100644 --- a/trees_emit.h +++ b/trees_emit.h @@ -109,7 +109,7 @@ static inline uint32_t zng_emit_lit(deflate_state *s, const ct_data *ltree, unsi s->bi_valid = bi_valid; s->bi_buf = bi_buf; - Tracecv(isgraph(c), (stderr, " '%c' ", c)); + Tracecv(isgraph(c & 0xff), (stderr, " '%c' ", c)); return ltree[c].Len; } From 96290ad9177865558e47d00576aed82df5197522 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 1 Jul 2021 14:06:06 -0700 Subject: [PATCH 131/798] Include win directory in pigz even if not using threads. --- test/pigz/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/pigz/CMakeLists.txt b/test/pigz/CMakeLists.txt index 6038e6cb53..43082cf263 100644 --- a/test/pigz/CMakeLists.txt +++ b/test/pigz/CMakeLists.txt @@ -6,6 +6,9 @@ # By default pigz will be linked against the system zlib and # pthread libraries if installed. +# For compilation on Windows download and use shim: +# https://github.com/zlib-ng/pigzbench/tree/master/pigz/win + # Optional Variables # WITH_CODE_COVERAGE - Enable code coverage reporting # WITH_THREADS - Enable threading support @@ -69,6 +72,9 @@ set(PIGZ_HDRS add_executable(${PROJECT_NAME} ${PIGZ_SRCS} ${PIGZ_HDRS}) add_definitions(-DNOZOPFLI) +if(WIN32) + target_include_directories(${PROJECT_NAME} PRIVATE win) +endif() # Find and link against pthreads or pthreads4w if(WITH_THREADS) @@ -79,7 +85,7 @@ if(WITH_THREADS) add_subdirectory(${PTHREADS4W_ROOT} ${PTHREADS4W_ROOT} EXCLUDE_FROM_ALL) target_link_libraries(${PROJECT_NAME} pthreadVC3) - target_include_directories(${PROJECT_NAME} PRIVATE win ${PTHREADS4W_ROOT}) + target_include_directories(${PROJECT_NAME} PRIVATE ${PTHREADS4W_ROOT}) else() message(WARNING "Missing pthreads4w root directory") set(WITH_THREADS OFF) From e9d0177feafa3adad6ca90cadd44b50389ac4094 Mon Sep 17 00:00:00 2001 From: Sergey Markelov Date: Thu, 22 Jul 2021 10:23:26 -0700 Subject: [PATCH 132/798] Fix hangs on macOS due to loading of misaligned addresses in chunkmemset_8. --- chunkset_tpl.h | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 1018aac3a3..c451c0d16c 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -114,10 +114,10 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { chunk_t chunk; unsigned sz = sizeof(chunk); if (len < sz) { - do { + while (len != 0) { *out++ = *from++; --len; - } while (len != 0); + } return out; } @@ -176,9 +176,24 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { } Z_INTERNAL uint8_t* CHUNKMEMSET_SAFE(uint8_t *out, unsigned dist, unsigned len, unsigned left) { +#if !defined(UNALIGNED64_OK) +# if !defined(UNALIGNED_OK) + static const uint32_t align_mask = 7; +# else + static const uint32_t align_mask = 3; +# endif +#endif + len = MIN(len, left); + uint8_t *from = out - dist; +#if !defined(UNALIGNED64_OK) + while (((uintptr_t)out & align_mask) && (len > 0)) { + *out++ = *from++; + --len; + --left; + } +#endif if (left < (unsigned)(3 * sizeof(chunk_t))) { - uint8_t *from = out - dist; while (len > 0) { *out++ = *from++; --len; From f77af71e77cdb9d41d5e3a606e2a8dd67034e387 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 4 Sep 2021 12:16:16 -0700 Subject: [PATCH 133/798] Fixed trailing whitespaces and missing new lines. --- cmake/detect-arch.c | 4 ++-- cmake/run-and-compare.cmake | 2 +- cmake/test-compress.cmake | 2 +- cmake/test-tools.cmake | 1 - deflate_fast.c | 1 - inffast.c | 4 ++-- insert_string_tpl.h | 2 +- 7 files changed, 7 insertions(+), 9 deletions(-) diff --git a/cmake/detect-arch.c b/cmake/detect-arch.c index 8cae4eb668..84e6a84100 100644 --- a/cmake/detect-arch.c +++ b/cmake/detect-arch.c @@ -36,7 +36,7 @@ #if defined(__64BIT__) || defined(__powerpc64__) || defined(__ppc64__) #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #error archfound powerpc64le - #else + #else #error archfound powerpc64 #endif #else @@ -94,7 +94,7 @@ #error archfound rs6000 // RISC-V -#elif defined(__riscv) +#elif defined(__riscv) #if __riscv_xlen == 64 #error archfound riscv64 #elif __riscv_xlen == 32 diff --git a/cmake/run-and-compare.cmake b/cmake/run-and-compare.cmake index af54abc264..209d31e9e6 100644 --- a/cmake/run-and-compare.cmake +++ b/cmake/run-and-compare.cmake @@ -59,4 +59,4 @@ endif() if(CMD_RESULT) message(FATAL_ERROR "Run compare failed: ${CMD_RESULT}") -endif() \ No newline at end of file +endif() diff --git a/cmake/test-compress.cmake b/cmake/test-compress.cmake index 321fa54301..cfc7613ab2 100644 --- a/cmake/test-compress.cmake +++ b/cmake/test-compress.cmake @@ -261,4 +261,4 @@ if(GZIP_VERIFY AND NOT "${COMPRESS_ARGS}" MATCHES "-T") endif() endif() -cleanup_always() \ No newline at end of file +cleanup_always() diff --git a/cmake/test-tools.cmake b/cmake/test-tools.cmake index 3275935547..4afe07c2c1 100644 --- a/cmake/test-tools.cmake +++ b/cmake/test-tools.cmake @@ -32,4 +32,3 @@ add_test(NAME switchlevels-help COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${TEST_COMMAND}" -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake) - diff --git a/deflate_fast.c b/deflate_fast.c index 4142a7aa4c..c6e24e48a2 100644 --- a/deflate_fast.c +++ b/deflate_fast.c @@ -47,7 +47,6 @@ Z_INTERNAL block_state deflate_fast(deflate_state *s, int flush) { /* Find the longest match, discarding those <= prev_length. * At this point we have always match length < WANT_MIN_MATCH */ - if (dist <= MAX_DIST(s) && dist > 0 && hash_head != 0) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match diff --git a/inffast.c b/inffast.c index 136b98d5a6..de71271b2c 100644 --- a/inffast.c +++ b/inffast.c @@ -152,8 +152,8 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; - /* Detect if out and window point to the same memory allocation. In this instance it is - necessary to use safe chunk copy functions to prevent overwriting the window. If the + /* Detect if out and window point to the same memory allocation. In this instance it is + necessary to use safe chunk copy functions to prevent overwriting the window. If the window is overwritten then future matches with far distances will fail to copy correctly. */ extra_safe = (out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); diff --git a/insert_string_tpl.h b/insert_string_tpl.h index c116544f9d..ad88275bfc 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -23,7 +23,7 @@ */ #ifndef HASH_CALC_OFFSET -# define HASH_CALC_OFFSET 0 +# define HASH_CALC_OFFSET 0 #endif #ifndef HASH_CALC_MASK # define HASH_CALC_MASK HASH_MASK From 0c7524acd3b83f5bdded9d1adf775cb228c32077 Mon Sep 17 00:00:00 2001 From: Ori Livneh Date: Mon, 23 Aug 2021 12:40:19 -0400 Subject: [PATCH 134/798] Fix UB in inffast.c when not using window When not using window, `window + wsize` applies a zero offset to a null pointer, which is undefined behavior. --- inffast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inffast.c b/inffast.c index de71271b2c..2c3add3a84 100644 --- a/inffast.c +++ b/inffast.c @@ -155,7 +155,7 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { /* Detect if out and window point to the same memory allocation. In this instance it is necessary to use safe chunk copy functions to prevent overwriting the window. If the window is overwritten then future matches with far distances will fail to copy correctly. */ - extra_safe = (out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); + extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); /* decode literals and length/distances until end-of-block or not enough input data or output space */ From ce3cf80314a470f6a9780d2bf977ec28e342e970 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 10 Jul 2021 10:08:53 -0700 Subject: [PATCH 135/798] Added CI instances for CTZLL and CTZ builtin existence to improve code coverage. --- .github/workflows/cmake.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 18377740fc..aac24c7b2b 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -34,6 +34,18 @@ jobs: codecov: ubuntu_gcc_o3 cflags: -O3 + - name: Ubuntu GCC No CTZLL + os: ubuntu-latest + compiler: gcc + cmake-args: -DWITH_OPTIM=OFF -DHAVE_BUILTIN_CTZLL=OFF + codecov: ubuntu_gcc_no_ctzll + + - name: Ubuntu GCC No CTZ + os: ubuntu-latest + compiler: gcc + cmake-args: -DWITH_OPTIM=OFF -DHAVE_BUILTIN_CTZLL=OFF -DHAVE_BUILTIN_CTZ=OFF + codecov: ubuntu_gcc_no_ctz + - name: Ubuntu GCC Link Zlib os: ubuntu-latest compiler: gcc From 454bbf3e88fc3d5902ab298fc788258838dbe62d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 11 Jul 2021 16:59:21 -0700 Subject: [PATCH 136/798] Fill out gzheader before calling deflateSetHeader for better code coverage in example. --- test/example.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/example.c b/test/example.c index 339ea8cd6f..151e814b7e 100644 --- a/test/example.c +++ b/test/example.c @@ -923,6 +923,12 @@ void test_deflate_set_header(unsigned char *compr, size_t comprLen) { CHECK_ERR(err, "deflateInit2"); head->text = 1; + head->comment = (uint8_t *)"comment"; + head->name = (uint8_t *)"name"; + head->hcrc = 1; + head->extra = (uint8_t *)"extra"; + head->extra_len = (uint32_t)strlen((const char *)head->extra); + err = PREFIX(deflateSetHeader)(&c_stream, head); CHECK_ERR(err, "deflateSetHeader"); if (err == Z_OK) { From 983df0adec3fb04bc47f051e479fb6490f5da3d9 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 11 Jul 2021 16:58:48 -0700 Subject: [PATCH 137/798] Call deflateBound to calculate length with custom gzip header in example. --- test/example.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/example.c b/test/example.c index 151e814b7e..9f1f52a940 100644 --- a/test/example.c +++ b/test/example.c @@ -934,6 +934,7 @@ void test_deflate_set_header(unsigned char *compr, size_t comprLen) { if (err == Z_OK) { printf("deflateSetHeader(): OK\n"); } + PREFIX(deflateBound)(&c_stream, (unsigned long)comprLen); c_stream.next_in = (unsigned char *)hello; c_stream.next_out = compr; From 4deaf27124912152a51649160501e22e6ae7d621 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 11 Jul 2021 16:17:30 -0700 Subject: [PATCH 138/798] Added code coverage for inflateGetDictionary in example. --- test/example.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/example.c b/test/example.c index 9f1f52a940..4f81962f7a 100644 --- a/test/example.c +++ b/test/example.c @@ -575,6 +575,8 @@ void test_dict_deflate(unsigned char *compr, size_t comprLen) { */ void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { int err; + uint8_t check_dictionary[10]; + uint32_t check_dictionary_len = 0; PREFIX3(stream) d_stream; /* decompression stream */ strcpy((char*)uncompr, "garbage garbage garbage"); @@ -605,6 +607,20 @@ void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *unc } CHECK_ERR(err, "inflate with dict"); } + + err = PREFIX(inflateGetDictionary)(&d_stream, NULL, &check_dictionary_len); + CHECK_ERR(err, "inflateGetDictionary"); + if (check_dictionary_len != sizeof(dictionary)) { + fprintf(stderr, "bad dictionary length\n"); + exit(1); + } + + err = PREFIX(inflateGetDictionary)(&d_stream, check_dictionary, &check_dictionary_len); + CHECK_ERR(err, "inflateGetDictionary"); + if (memcmp(dictionary, check_dictionary, sizeof(dictionary)) != 0) { + fprintf(stderr, "bad dictionary\n"); + exit(1); + } err = PREFIX(inflateEnd)(&d_stream); CHECK_ERR(err, "inflateEnd"); From 92107a92d3cfb11cc464c24ef2a73c2d7d05d2ba Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 11 Jul 2021 20:31:08 -0700 Subject: [PATCH 139/798] Use helper function for printing error and exiting in example. --- test/example.c | 311 ++++++++++++++++++------------------------------- 1 file changed, 116 insertions(+), 195 deletions(-) diff --git a/test/example.c b/test/example.c index 4f81962f7a..53abb5ee93 100644 --- a/test/example.c +++ b/test/example.c @@ -17,16 +17,10 @@ #include #include #include +#include #define TESTFILE "foo.gz" -#define CHECK_ERR(err, msg) { \ - if (err != Z_OK) { \ - fprintf(stderr, "%s error: %d\n", msg, err); \ - exit(1); \ - } \ -} - static const char hello[] = "hello, hello!"; /* "hello world" would be more standard, but the repeated "hello" * stresses the compression code better, sorry... @@ -52,6 +46,24 @@ int main (int argc, char *argv[]); static alloc_func zalloc = NULL; static free_func zfree = NULL; +/* =========================================================================== + * Display error message and exit + */ +void error(const char *format, ...) { + va_list va; + + va_start(va, format); + vfprintf(stderr, format, va); + va_end(va); + + exit(1); +} + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) \ + error("%s error: %d\n", msg, err); \ +} + /* =========================================================================== * Test compress() and uncompress() */ @@ -67,12 +79,10 @@ void test_compress(unsigned char *compr, z_size_t comprLen, unsigned char *uncom err = PREFIX(uncompress)(uncompr, &uncomprLen, compr, comprLen); CHECK_ERR(err, "uncompress"); - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad uncompress\n"); - exit(1); - } else { + if (strcmp((char*)uncompr, hello)) + error("bad uncompress\n"); + else printf("uncompress(): %s\n", (char *)uncompr); - } } /* =========================================================================== @@ -91,144 +101,95 @@ void test_gzio(const char *fname, unsigned char *uncompr, z_size_t uncomprLen) { /* Write gz file with test data */ file = PREFIX(gzopen)(fname, "wb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } + if (file == NULL) + error("gzopen error\n"); /* Write hello, hello! using gzputs and gzprintf */ PREFIX(gzputc)(file, 'h'); - if (PREFIX(gzputs)(file, "ello") != 4) { - fprintf(stderr, "gzputs err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - if (PREFIX(gzprintf)(file, ", %s!", "hello") != 8) { - fprintf(stderr, "gzprintf err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } + if (PREFIX(gzputs)(file, "ello") != 4) + error("gzputs err: %s\n", PREFIX(gzerror)(file, &err)); + if (PREFIX(gzprintf)(file, ", %s!", "hello") != 8) + error("gzprintf err: %s\n", PREFIX(gzerror)(file, &err)); /* Write string null-teriminator using gzseek */ if (PREFIX(gzseek)(file, 1L, SEEK_CUR) < 0) - { - fprintf(stderr, "gzseek error, gztell=%ld\n", (long)PREFIX(gztell)(file)); - exit(1); - } + error("gzseek error, gztell=%ld\n", (long)PREFIX(gztell)(file)); /* Write hello, hello! using gzfwrite using best compression level */ - if (PREFIX(gzsetparams)(file, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK) { - fprintf(stderr, "gzsetparams err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - if (PREFIX(gzfwrite)(hello, len, 1, file) == 0) { - fprintf(stderr, "gzfwrite err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } + if (PREFIX(gzsetparams)(file, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK) + error("gzsetparams err: %s\n", PREFIX(gzerror)(file, &err)); + if (PREFIX(gzfwrite)(hello, len, 1, file) == 0) + error("gzfwrite err: %s\n", PREFIX(gzerror)(file, &err)); /* Flush compressed bytes to file */ - if (PREFIX(gzflush)(file, Z_SYNC_FLUSH) != Z_OK) { - fprintf(stderr, "gzflush err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } + if (PREFIX(gzflush)(file, Z_SYNC_FLUSH) != Z_OK) + error("gzflush err: %s\n", PREFIX(gzerror)(file, &err)); comprLen = PREFIX(gzoffset)(file); - if (comprLen <= 0) { - fprintf(stderr, "gzoffset err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } + if (comprLen <= 0) + error("gzoffset err: %s\n", PREFIX(gzerror)(file, &err)); PREFIX(gzclose)(file); /* Open gz file we previously wrote */ file = PREFIX(gzopen)(fname, "rb"); - if (file == NULL) { - fprintf(stderr, "gzopen error\n"); - exit(1); - } + if (file == NULL) + error("gzopen error\n"); + /* Read uncompressed data - hello, hello! string twice */ strcpy((char*)uncompr, "garbages"); - if (PREFIX(gzread)(file, uncompr, (unsigned)uncomprLen) != (int)(len + len)) { - fprintf(stderr, "gzread err: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); - exit(1); - } else { + if (PREFIX(gzread)(file, uncompr, (unsigned)uncomprLen) != (int)(len + len)) + error("gzread err: %s\n", PREFIX(gzerror)(file, &err)); + if (strcmp((char*)uncompr, hello)) + error("bad gzread: %s\n", (char*)uncompr); + else printf("gzread(): %s\n", (char*)uncompr); - } /* Check position at the end of the gz file */ - if (PREFIX(gzeof)(file) != 1) { - fprintf(stderr, "gzeof err: not reporting end of stream\n"); - exit(1); - } + if (PREFIX(gzeof)(file) != 1) + error("gzeof err: not reporting end of stream\n"); + /* Seek backwards mid-string and check char reading with gzgetc and gzungetc */ pos = PREFIX(gzseek)(file, -22L, SEEK_CUR); - if (pos != 6 || PREFIX(gztell)(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)PREFIX(gztell)(file)); - exit(1); - } - if (PREFIX(gzgetc)(file) != ' ') { - fprintf(stderr, "gzgetc error\n"); - exit(1); - } - if (PREFIX(gzungetc)(' ', file) != ' ') { - fprintf(stderr, "gzungetc error\n"); - exit(1); - } + if (pos != 6 || PREFIX(gztell)(file) != pos) + error("gzseek error, pos=%ld, gztell=%ld\n", (long)pos, (long)PREFIX(gztell)(file)); + if (PREFIX(gzgetc)(file) != ' ') + error("gzgetc error\n"); + if (PREFIX(gzungetc)(' ', file) != ' ') + error("gzungetc error\n"); /* Read first hello, hello! string with gzgets */ strcpy((char*)uncompr, "garbages"); PREFIX(gzgets)(file, (char*)uncompr, (int)uncomprLen); - if (strlen((char*)uncompr) != 7) { /* " hello!" */ - fprintf(stderr, "gzgets err after gzseek: %s\n", PREFIX(gzerror)(file, &err)); - exit(1); - } - if (strcmp((char*)uncompr, hello + 6)) { - fprintf(stderr, "bad gzgets after gzseek\n"); - exit(1); - } else { + if (strlen((char*)uncompr) != 7) /* " hello!" */ + error("gzgets err after gzseek: %s\n", PREFIX(gzerror)(file, &err)); + if (strcmp((char*)uncompr, hello + 6)) + error("bad gzgets after gzseek\n"); + else printf("gzgets() after gzseek: %s\n", (char*)uncompr); - } /* Seek to second hello, hello! string */ pos = PREFIX(gzseek)(file, 14L, SEEK_SET); - if (pos != 14 || PREFIX(gztell)(file) != pos) { - fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", - (long)pos, (long)PREFIX(gztell)(file)); - exit(1); - } + if (pos != 14 || PREFIX(gztell)(file) != pos) + error("gzseek error, pos=%ld, gztell=%ld\n", (long)pos, (long)PREFIX(gztell)(file)); /* Check position not at end of file */ - if (PREFIX(gzeof)(file) != 0) { - fprintf(stderr, "gzeof err: reporting end of stream\n"); - exit(1); - } + if (PREFIX(gzeof)(file) != 0) + error("gzeof err: reporting end of stream\n"); /* Read first hello, hello! string with gzfread */ strcpy((char*)uncompr, "garbages"); read = PREFIX(gzfread)(uncompr, uncomprLen, 1, file); - if (strcmp((const char *)uncompr, hello) != 0) { - fprintf(stderr, "bad gzgets\n"); - exit(1); - } else { + if (strcmp((const char *)uncompr, hello) != 0) + error("bad gzgets\n"); + else printf("gzgets(): %s\n", (char*)uncompr); - } pos = PREFIX(gzoffset)(file); - if (pos < 0 || pos != (comprLen + 10)) { - fprintf(stderr, "gzoffset err: wrong offset at end\n"); - exit(1); - } + if (pos < 0 || pos != (comprLen + 10)) + error("gzoffset err: wrong offset at end\n"); /* Trigger an error and clear it with gzclearerr */ PREFIX(gzfread)(uncompr, (size_t)-1, (size_t)-1, file); PREFIX(gzerror)(file, &err); - if (err == 0) { - fprintf(stderr, "gzerror err: no error returned\n"); - exit(1); - } + if (err == 0) + error("gzerror err: no error returned\n"); PREFIX(gzclearerr)(file); PREFIX(gzerror)(file, &err); - if (err != 0) { - fprintf(stderr, "gzclearerr err: not zero %d\n", err); - exit(1); - } + if (err != 0) + error("gzclearerr err: not zero %d\n", err); PREFIX(gzclose)(file); - if (PREFIX(gzclose)(NULL) != Z_STREAM_ERROR) { - fprintf(stderr, "gzclose unexpected return when handle null\n"); - exit(1); - } + if (PREFIX(gzclose)(NULL) != Z_STREAM_ERROR) + error("gzclose unexpected return when handle null\n"); Z_UNUSED(read); #endif } @@ -302,12 +263,10 @@ void test_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, err = PREFIX(inflateEnd)(&d_stream); CHECK_ERR(err, "inflateEnd"); - if (strcmp((char*)uncompr, hello)) { - fprintf(stderr, "bad inflate\n"); - exit(1); - } else { + if (strcmp((char*)uncompr, hello)) + error("bad inflate\n"); + else printf("inflate(): %s\n", (char *)uncompr); - } } static unsigned int diff; @@ -349,29 +308,22 @@ void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *un c_stream.avail_in = (unsigned int)uncomprLen; err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); CHECK_ERR(err, "deflate"); - if (c_stream.avail_in != 0) { - fprintf(stderr, "deflate not greedy\n"); - exit(1); - } + if (c_stream.avail_in != 0) + error("deflate not greedy\n"); /* Feed in already compressed data and switch to no compression: */ if (zng_params) { #ifndef ZLIB_COMPAT zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); - if (level != Z_BEST_SPEED) { - fprintf(stderr, "Expected compression level Z_BEST_SPEED, got %d\n", level); - exit(1); - } - if (strategy != Z_DEFAULT_STRATEGY) { - fprintf(stderr, "Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy); - exit(1); - } + if (level != Z_BEST_SPEED) + error("Expected compression level Z_BEST_SPEED, got %d\n", level); + if (strategy != Z_DEFAULT_STRATEGY) + error("Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy); level = Z_NO_COMPRESSION; strategy = Z_DEFAULT_STRATEGY; zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); #else - fprintf(stderr, "test_large_deflate() called with zng_params=1 in compat mode\n"); - exit(1); + error("test_large_deflate() called with zng_params=1 in compat mode\n"); #endif } else { PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); @@ -388,20 +340,15 @@ void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *un level = -1; strategy = -1; zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); - if (level != Z_NO_COMPRESSION) { - fprintf(stderr, "Expected compression level Z_NO_COMPRESSION, got %d\n", level); - exit(1); - } - if (strategy != Z_DEFAULT_STRATEGY) { - fprintf(stderr, "Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy); - exit(1); - } + if (level != Z_NO_COMPRESSION) + error("Expected compression level Z_NO_COMPRESSION, got %d\n", level); + if (strategy != Z_DEFAULT_STRATEGY) + error("Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy); level = Z_BEST_COMPRESSION; strategy = Z_FILTERED; zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); #else - fprintf(stderr, "test_large_deflate() called with zng_params=1 in compat mode\n"); - exit(1); + error("test_large_deflate() called with zng_params=1 in compat mode\n"); #endif } else { PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); @@ -412,10 +359,8 @@ void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *un CHECK_ERR(err, "deflate"); err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } + if (err != Z_STREAM_END) + error("deflate should report Z_STREAM_END\n"); err = PREFIX(deflateEnd)(&c_stream); CHECK_ERR(err, "deflateEnd"); } @@ -452,12 +397,10 @@ void test_large_inflate(unsigned char *compr, size_t comprLen, unsigned char *un err = PREFIX(inflateEnd)(&d_stream); CHECK_ERR(err, "inflateEnd"); - if (d_stream.total_out != 2*uncomprLen + diff) { - fprintf(stderr, "bad large inflate: %" PRIu64 "\n", (uint64_t)d_stream.total_out); - exit(1); - } else { + if (d_stream.total_out != 2*uncomprLen + diff) + error("bad large inflate: %" PRIu64 "\n", (uint64_t)d_stream.total_out); + else printf("large_inflate(): OK\n"); - } } /* =========================================================================== @@ -525,10 +468,8 @@ void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr, si CHECK_ERR(err, "inflateSync"); err = PREFIX(inflate)(&d_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "inflate should report Z_STREAM_END\n"); - exit(1); - } + if (err != Z_STREAM_END) + error("inflate should report Z_STREAM_END\n"); err = PREFIX(inflateEnd)(&d_stream); CHECK_ERR(err, "inflateEnd"); @@ -562,10 +503,8 @@ void test_dict_deflate(unsigned char *compr, size_t comprLen) { c_stream.avail_in = (unsigned int)strlen(hello)+1; err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } + if (err != Z_STREAM_END) + error("deflate should report Z_STREAM_END\n"); err = PREFIX(deflateEnd)(&c_stream); CHECK_ERR(err, "deflateEnd"); } @@ -598,10 +537,8 @@ void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *unc err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); if (err == Z_STREAM_END) break; if (err == Z_NEED_DICT) { - if (d_stream.adler != dictId) { - fprintf(stderr, "unexpected dictionary"); - exit(1); - } + if (d_stream.adler != dictId) + error("unexpected dictionary"); err = PREFIX(inflateSetDictionary)(&d_stream, (const unsigned char*)dictionary, (int)sizeof(dictionary)); } @@ -610,27 +547,21 @@ void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *unc err = PREFIX(inflateGetDictionary)(&d_stream, NULL, &check_dictionary_len); CHECK_ERR(err, "inflateGetDictionary"); - if (check_dictionary_len != sizeof(dictionary)) { - fprintf(stderr, "bad dictionary length\n"); - exit(1); - } + if (check_dictionary_len != sizeof(dictionary)) + error("bad dictionary length\n"); err = PREFIX(inflateGetDictionary)(&d_stream, check_dictionary, &check_dictionary_len); CHECK_ERR(err, "inflateGetDictionary"); - if (memcmp(dictionary, check_dictionary, sizeof(dictionary)) != 0) { - fprintf(stderr, "bad dictionary\n"); - exit(1); - } + if (memcmp(dictionary, check_dictionary, sizeof(dictionary)) != 0) + error("bad dictionary\n"); err = PREFIX(inflateEnd)(&d_stream); CHECK_ERR(err, "inflateEnd"); - if (strncmp((char*)uncompr, hello, sizeof(hello))) { - fprintf(stderr, "bad inflate with dict\n"); - exit(1); - } else { + if (strncmp((char*)uncompr, hello, sizeof(hello))) + error("bad inflate with dict\n"); + else printf("inflate with dictionary: %s\n", (char *)uncompr); - } } /* =========================================================================== @@ -750,10 +681,8 @@ void test_deflate_get_dict(unsigned char *compr, size_t comprLen) { err = PREFIX(deflate)(&c_stream, Z_FINISH); - if (err != Z_STREAM_END) { - fprintf(stderr, "deflate should report Z_STREAM_END\n"); - exit(1); - } + if (err != Z_STREAM_END) + error("deflate should report Z_STREAM_END\n"); dictNew = calloc(256, 1); dictLen = (unsigned int *)calloc(4, 1); @@ -905,14 +834,10 @@ void test_deflate_prime(unsigned char *compr, size_t comprLen, unsigned char *un err = PREFIX(inflateEnd)(&d_stream); CHECK_ERR(err, "inflateEnd"); - if (strcmp((const char *)uncompr, hello) != 0) { - fprintf(stderr, "bad deflatePrime\n"); - exit(1); - } - - if (err == Z_OK) { + if (strcmp((const char *)uncompr, hello) != 0) + error("bad deflatePrime\n"); + if (err == Z_OK) printf("deflatePrime(): OK\n"); - } } /* =========================================================================== @@ -925,10 +850,8 @@ void test_deflate_set_header(unsigned char *compr, size_t comprLen) { size_t len = strlen(hello)+1; - if (head == NULL) { - printf("out of memory\n"); - exit(1); - } + if (head == NULL) + error("out of memory\n"); c_stream.zalloc = zalloc; c_stream.zfree = zfree; @@ -1047,10 +970,8 @@ int main(int argc, char *argv[]) { /* compr and uncompr are cleared to avoid reading uninitialized * data and to ensure that uncompr compresses well. */ - if (compr == NULL || uncompr == NULL) { - printf("out of memory\n"); - exit(1); - } + if (compr == NULL || uncompr == NULL) + error("out of memory\n"); test_compress(compr, comprLen, uncompr, uncomprLen); From 714f624d797e346b770ced4ed7282dd357f67e44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Mon, 6 Sep 2021 16:39:28 -0400 Subject: [PATCH 140/798] Add support for name mangling This is useful when zlib-ng is embedded into another library, such as ITK: https://itk.org/ Closes #1025. Co-authored-by: Mika Lindqvist --- .gitattributes | 2 + CMakeLists.txt | 33 ++++++- Makefile.in | 32 +++++-- configure | 39 ++++++--- gzread.c => gzread.c.in | 4 +- win32/Makefile.a64 | 28 +++++- win32/Makefile.arm | 28 +++++- win32/Makefile.msc | 28 +++++- win32/replace.vbs | 15 ++++ win32/zlib-ng.def | 60 ------------- win32/zlib-ng.def.in | 60 +++++++++++++ win32/zlib-ng1.rc | 2 +- win32/zlib.def | 61 ------------- win32/zlib.def.in | 61 +++++++++++++ win32/zlib1.rc | 2 +- win32/zlibcompat.def | 94 -------------------- win32/zlibcompat.def.in | 94 ++++++++++++++++++++ zconf-ng.h.in | 2 + zconf.h.in | 2 + zlib-ng.h => zlib-ng.h.in | 12 +-- zlib.h => zlib.h.in | 40 ++++----- zlib.pc.cmakein | 1 + zlib.pc.in | 1 + zlib_name_mangling-ng.h.in | 173 +++++++++++++++++++++++++++++++++++++ zlib_name_mangling.h.empty | 8 ++ zlib_name_mangling.h.in | 157 +++++++++++++++++++++++++++++++++ 26 files changed, 767 insertions(+), 272 deletions(-) rename gzread.c => gzread.c.in (99%) create mode 100644 win32/replace.vbs delete mode 100644 win32/zlib-ng.def create mode 100644 win32/zlib-ng.def.in delete mode 100644 win32/zlib.def create mode 100644 win32/zlib.def.in delete mode 100644 win32/zlibcompat.def create mode 100644 win32/zlibcompat.def.in rename zlib-ng.h => zlib-ng.h.in (99%) rename zlib.h => zlib.h.in (98%) create mode 100644 zlib_name_mangling-ng.h.in create mode 100644 zlib_name_mangling.h.empty create mode 100644 zlib_name_mangling.h.in diff --git a/.gitattributes b/.gitattributes index 68ec3a174e..0414401042 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,5 @@ *.c text *.h text Makefile text +configure text eol=lf +testCVEinputs.sh text eol=lf \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index dcd07ad602..342a9b8c91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ if(NOT CMAKE_C_STANDARD IN_LIST VALID_C_STANDARDS) endif() # Parse the full version number from zlib.h and include in ZLIB_FULL_VERSION -file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h _zlib_h_contents) +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h.in _zlib_h_contents) string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9]+.[0-9]+.[0-9]+).*\".*" "\\1" ZLIB_HEADER_VERSION ${_zlib_h_contents}) string(REGEX REPLACE ".*#define[ \t]+ZLIBNG_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" @@ -86,6 +86,10 @@ option(WITH_INFLATE_STRICT "Build with strict inflate distance checking" OFF) option(WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances" OFF) option(WITH_UNALIGNED "Support unaligned reads on platforms that support it" ON) +set(ZLIB_SYMBOL_PREFIX "" CACHE STRING "Give this prefix to all publicly exported symbols. +Useful when embedding into a larger library. +Default is no prefix (empty prefix).") + # Add multi-choice option set(WITH_SANITIZER AUTO CACHE STRING "Enable sanitizer support") set_property(CACHE WITH_SANITIZER PROPERTY STRINGS "Memory" "Address" "Undefined" "Thread") @@ -111,6 +115,7 @@ endif() option(INSTALL_UTILS "Copy minigzip and minideflate during install" OFF) mark_as_advanced(FORCE + ZLIB_SYMBOL_PREFIX ZLIB_DUAL_LINK WITH_REDUCED_MEM WITH_ACLE WITH_NEON @@ -841,7 +846,8 @@ endif() set(ZLIB_PUBLIC_HDRS ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h - zlib${SUFFIX}.h + ${CMAKE_CURRENT_BINARY_DIR}/zlib_name_mangling${SUFFIX}.h + ${CMAKE_CURRENT_BINARY_DIR}/zlib${SUFFIX}.h ) set(ZLIB_PRIVATE_HDRS adler32_p.h @@ -901,7 +907,7 @@ set(ZLIB_GZFILE_PRIVATE_HDRS ) set(ZLIB_GZFILE_SRCS gzlib.c - gzread.c + ${CMAKE_CURRENT_BINARY_DIR}/gzread.c gzwrite.c ) @@ -1040,6 +1046,23 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein ${ZLIB_PC} @ONLY) configure_file(${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h.in + ${CMAKE_CURRENT_BINARY_DIR}/zlib${SUFFIX}.h @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/gzread.c.in + ${CMAKE_CURRENT_BINARY_DIR}/gzread.c @ONLY) + + +if (NOT ZLIB_SYMBOL_PREFIX STREQUAL "") + add_feature_info(ZLIB_SYMBOL_PREFIX ON "Publicly exported symbols have a custom prefix") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib_name_mangling${SUFFIX}.h.in + ${CMAKE_CURRENT_BINARY_DIR}/zlib_name_mangling${SUFFIX}.h @ONLY) +else() + add_feature_info(ZLIB_SYMBOL_PREFIX OFF "Publicly exported symbols DO NOT have a custom prefix") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zlib_name_mangling.h.empty + ${CMAKE_CURRENT_BINARY_DIR}/zlib_name_mangling${SUFFIX}.h COPYONLY) +endif() +# add_definitions(-DZLIB_SYMBOL_PREFIX=${ZLIB_SYMBOL_PREFIX}) # not needed + if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) install(TARGETS ${ZLIB_INSTALL_LIBRARIES} @@ -1048,8 +1071,10 @@ if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) LIBRARY DESTINATION "${LIB_INSTALL_DIR}") endif() if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) - install(FILES zlib${SUFFIX}.h + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zlib${SUFFIX}.h DESTINATION "${INC_INSTALL_DIR}" RENAME zlib${SUFFIX}.h) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zlib_name_mangling${SUFFIX}.h + DESTINATION "${INC_INSTALL_DIR}" RENAME zlib_name_mangling${SUFFIX}.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h DESTINATION "${INC_INSTALL_DIR}" RENAME zconf${SUFFIX}.h) endif() diff --git a/Makefile.in b/Makefile.in index fb6a30c247..8e855e456d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -57,6 +57,8 @@ EXE= SRCDIR=. INCLUDES=-I$(SRCDIR) +BUILDDIR=. + ARCHDIR=arch/generic ARCH_STATIC_OBJS= ARCH_SHARED_OBJS= @@ -225,7 +227,7 @@ example_dict_fuzzer$(EXE): example_dict_fuzzer.o standalone_fuzz_target_runner.o minigzip_fuzzer$(EXE): minigzip_fuzzer.o standalone_fuzz_target_runner.o $(OBJG) $(STATICLIB) $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) minigzip_fuzzer.o $(OBJG) $(STATICLIB) -lpthread -infcover.o: $(SRCDIR)/test/infcover.c $(SRCDIR)/zlib$(SUFFIX).h zconf$(SUFFIX).h +infcover.o: $(SRCDIR)/test/infcover.c zlib$(SUFFIX).h zconf$(SUFFIX).h zlib_name_mangling$(SUFFIX).h $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c infcover$(EXE): infcover.o $(STATICLIB) @@ -275,9 +277,24 @@ zlibrc.o: win32/zlib$(SUFFIX)1.rc %.lo: $(SRCDIR)/%.c $(CC) $(SFLAGS) -DPIC $(INCLUDES) -c -o $@ $< -$(OBJG): %.o: $(SRCDIR)/%.c +gzlib.o: $(SRCDIR)/gzlib.c + $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< + +gzlib.lo: $(SRCDIR)/gzlib.c + $(CC) $(SFLAGS) -DPIC -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< + +gzread.o: gzread.c $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< +gzread.lo: gzread.c + $(CC) $(SFLAGS) -DPIC -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< + +gzwrite.o: $(SRCDIR)/gzwrite.c + $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< + +gzwrite.lo: $(SRCDIR)/gzwrite.c + $(CC) $(SFLAGS) -DPIC -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< + $(SHAREDTARGET): $(PIC_OBJS) $(DEFFILE) $(RCOBJS) ifneq ($(SHAREDTARGET),) $(LDSHARED) $(CFLAGS) $(LDSHAREDFLAGS) $(LDFLAGS) -o $@ $(DEFFILE) $(PIC_OBJS) $(RCOBJS) $(LDSHAREDLIBC) @@ -393,10 +410,11 @@ install-libs: install-shared install-static install: install-libs -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi - rm -f $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h - cp $(SRCDIR)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zlib$(SUFFIX).h + rm -f $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h $(DESTDIR)$(includedir)/zlib_name_mangling$(SUFFIX).h + cp zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zlib$(SUFFIX).h cp zconf$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h - chmod 644 $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h + cp zlib_name_mangling$(SUFFIX).h $(DESTDIR)$(includedir)/zlib_name_mangling$(SUFFIX).h + chmod 644 $(DESTDIR)$(includedir)/zlib$(SUFFIX).h $(DESTDIR)$(includedir)/zconf$(SUFFIX).h $(DESTDIR)$(includedir)/zlib_name_mangling$(SUFFIX).h uninstall-static: cd $(DESTDIR)$(libdir) && rm -f $(STATICLIB) @@ -410,7 +428,7 @@ ifneq ($(IMPORTLIB),) endif uninstall: uninstall-static uninstall-shared - cd $(DESTDIR)$(includedir) && rm -f zlib$(SUFFIX).h zconf$(SUFFIX).h + cd $(DESTDIR)$(includedir) && rm -f zlib$(SUFFIX).h zconf$(SUFFIX).h zlib_name_mangling$(SUFFIX).h cd $(DESTDIR)$(pkgconfigdir) && rm -f $(PKGFILE) mostlyclean: clean @@ -437,7 +455,7 @@ maintainer-clean: distclean distclean: clean @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) distclean; fi @if [ -f test/Makefile ]; then $(MAKE) -C test distclean; fi - rm -f $(PKGFILE) configure.log zconf.h zconf.h.cmakein + rm -f $(PKGFILE) configure.log zconf.h zconf.h.cmakein zlib$(SUFFIX).h zlib_name_mangling$(SUFFIX)}.h -@rm -f .DS_Store # Reset Makefile if building inside source tree @if [ -f Makefile.in ]; then \ diff --git a/configure b/configure index 765ea44359..af1c7c431d 100755 --- a/configure +++ b/configure @@ -113,6 +113,7 @@ neonflag= noltoflag="-fno-lto" vgfmaflag="-march=z13" vmxflag="-maltivec" +symbol_prefix="" without_optimizations=0 without_new_strategies=0 reducedmem=0 @@ -150,6 +151,7 @@ case "$1" in echo ' configure [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log echo ' [--static] [--32] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log + echo ' [--sprefix=SYMBOL_PREFIX] Adds a prefix to all exported symbols' | tee -a configure.log echo ' [--warn] Enables extra compiler warnings' | tee -a configure.log echo ' [--debug] Enables extra debug prints during operation' | tee -a configure.log echo ' [--zlib-compat] Compiles for zlib-compatible API instead of zlib-ng API' | tee -a configure.log @@ -171,12 +173,14 @@ case "$1" in exit 0 ;; -p*=* | --prefix=*) prefix=$(echo $1 | sed 's/.*=//'); shift ;; -e*=* | --eprefix=*) exec_prefix=$(echo $1 | sed 's/.*=//'); shift ;; + -m*=* | --sprefix=*) symbol_prefix=$(echo $1 | sed 's/.*=//'); shift ;; -l*=* | --libdir=*) libdir=$(echo $1 | sed 's/.*=//'); shift ;; --sharedlibdir=*) sharedlibdir=$(echo $1 | sed 's/.*=//'); shift ;; -i*=* | --includedir=*) includedir=$(echo $1 | sed 's/.*=//');shift ;; -u*=* | --uname=*) uname=$(echo $1 | sed 's/.*=//');shift ;; -p* | --prefix) prefix="$2"; shift; shift ;; -e* | --eprefix) exec_prefix="$2"; shift; shift ;; + -m* | --sprefix) symbol_prefix="$2"; shift; shift ;; -l* | --libdir) libdir="$2"; shift; shift ;; -i* | --includedir) includedir="$2"; shift; shift ;; -s* | --shared | --enable-shared) shared=1; shift ;; @@ -282,15 +286,15 @@ MAPNAME=${LIBNAME2}.map # extract zlib version numbers from zlib.h if test $compat -eq 0; then - VER=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib-ng.h) - VER3=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib-ng.h) - VER2=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\.[0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib-ng.h) - VER1=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib-ng.h) + VER=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib-ng.h.in) + VER3=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib-ng.h.in) + VER2=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\.[0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib-ng.h.in) + VER1=$(sed -n -e '/ZLIBNG_VERSION "/s/.*"\([0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib-ng.h.in) else - VER=$(sed -n -e '/ZLIB_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib.h) - VER3=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib.h) - VER2=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\.[0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib.h) - VER1=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib.h) + VER=$(sed -n -e '/ZLIB_VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}/zlib.h.in) + VER3=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' < ${SRCDIR}/zlib.h.in) + VER2=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\.[0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib.h.in) + VER1=$(sed -n -e '/ZLIB_VERSION "/s/.*"\([0-9]*\)\..*/\1/p' < ${SRCDIR}/zlib.h.in) fi show $cc -c $test.c @@ -790,9 +794,21 @@ else echo "Checking for strerror... No." | tee -a configure.log fi -# We need to remove zconf.h from source directory if building outside of it +# We need to remove consigured files (zconf.h etc) from source directory if building outside of it if [ "$SRCDIR" != "$BUILDDIR" ]; then rm -f $SRCDIR/zconf${SUFFIX}.h + rm -f $SRCDIR/zlib${SUFFIX}.h + rm -f $SRCDIR/zlib_name_mangling${SUFFIX}.h +fi + +# Rename @ZLIB_SYMBOL_PREFIX@ to $symbol_prefix in gzread.c, zlib.h and zlib_name_mangling.h +sed < $SRCDIR/gzread.c.in "s/@ZLIB_SYMBOL_PREFIX@/$symbol_prefix/g" > gzread.c +sed < $SRCDIR/zlib${SUFFIX}.h.in "s/@ZLIB_SYMBOL_PREFIX@/$symbol_prefix/g" > zlib${SUFFIX}.h +if [[ ! -z $symbol_prefix ]]; then + sed < $SRCDIR/zlib_name_mangling${SUFFIX}.h.in "s/@ZLIB_SYMBOL_PREFIX@/$symbol_prefix/g" > zlib_name_mangling${SUFFIX}.h +else + # symbol_prefix is not set, copy the empty mangling header + cp -p $SRCDIR/zlib_name_mangling.h.empty zlib_name_mangling${SUFFIX}.h fi # copy clean zconf.h for subsequent edits @@ -1755,6 +1771,7 @@ echo bindir = $bindir >> configure.log echo libdir = $libdir >> configure.log echo mandir = $mandir >> configure.log echo prefix = $prefix >> configure.log +echo symbol_prefix = $symbol_prefix >> configure.log echo sharedlibdir = $sharedlibdir >> configure.log echo uname = $uname >> configure.log echo sse2flag = $sse2flag >> configure.log @@ -1814,6 +1831,7 @@ sed < $SRCDIR/Makefile.in " /^prefix *=/s#=.*#= $prefix# /^exec_prefix *=/s#=.*#= $exec_prefix# /^bindir *=/s#=.*#= $bindir# +/^symbol_prefix *=/s#=.*#= $symbol_prefix# /^libdir *=/s#=.*#= $libdir# /^sharedlibdir *=/s#=.*#= $sharedlibdir# /^includedir *=/s#=.*#= $includedir# @@ -1887,7 +1905,7 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^SUFFIX *=/s#=.*#=$SUFFIX# /^SRCDIR *=/s#=.*#=$SRCDIR/$ARCHDIR# /^SRCTOP *=/s#=.*#=$SRCDIR# -/^TOPDIR *=/s#=.*#=$BUILDDIR# +/^BUILDDIR *=/s#=.*#=$BUILDDIR# /^AVX2FLAG *=/s#=.*#=$avx2flag# /^SSE2FLAG *=/s#=.*#=$sse2flag# /^SSSE3FLAG *=/s#=.*#=$ssse3flag# @@ -1971,6 +1989,7 @@ sed < $SRCDIR/zlib.pc.in " /^prefix *=/s#=.*#=$prefix# /^exec_prefix *=/s#=.*#=$exec_prefix# /^bindir *=/s#=.*#=$bindir# +/^symbol_prefix *=/s#=.*#=$symbol_prefix# /^libdir *=/s#=.*#=$libdir# /^sharedlibdir *=/s#=.*#=$sharedlibdir# /^includedir *=/s#=.*#=$includedir# diff --git a/gzread.c b/gzread.c.in similarity index 99% rename from gzread.c rename to gzread.c.in index c3b3a035fc..3e1dc1d132 100644 --- a/gzread.c +++ b/gzread.c.in @@ -406,8 +406,8 @@ size_t Z_EXPORT PREFIX(gzfread)(void *buf, size_t size, size_t nitems, gzFile fi } /* -- see zlib.h -- */ -#undef gzgetc -#undef zng_gzgetc +#undef @ZLIB_SYMBOL_PREFIX@gzgetc +#undef @ZLIB_SYMBOL_PREFIX@zng_gzgetc int Z_EXPORT PREFIX(gzgetc)(gzFile file) { unsigned char buf[1]; gz_state *state; diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 418558b137..580b5bfb1d 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -16,6 +16,7 @@ LOC = STATICLIB = zlib.lib SHAREDLIB = zlib1.dll IMPLIB = zdll.lib +SYMBOL_PREFIX = CC = cl LD = link @@ -103,8 +104,25 @@ OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj adler32_neon.obj chunkset_n all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ example.exe minigzip.exe example_d.exe minigzip_d.exe -zconf: $(TOP)/zconf$(SUFFIX).h.in - $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h +!if "$(SYMBOL_PREFIX)" != "" +zlib_name_mangling$(SUFFIX).h: zlib_name_mangling$(SUFFIX).h.in + cscript $(TOP)\win32\replace.vbs $(TOP)\zlib_name_mangling$(SUFFIX).h.in zlib_name_mangling$(SUFFIX).h "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" +!else +zlib_name_mangling$(SUFFIX).h: zlib_name_mangling.h.empty + $(CP) $(TOP)\zlib_name_mangling.h.empty zlib_name_mangling$(SUFFIX).h +!endif + +zlib$(SUFFIX).h: zlib$(SUFFIX).h.in + cscript $(TOP)\win32\replace.vbs $(TOP)\zlib$(SUFFIX).h.in zlib$(SUFFIX).h "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" + +gzread.c: gzread.c.in + cscript $(TOP)\win32\replace.vbs $(TOP)\gzread.c.in gzread.c "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" + +zconf: $(TOP)/zconf$(SUFFIX).h.in $(TOP)/zlib$(SUFFIX).h $(TOP)/zlib_name_mangling$(SUFFIX).h + $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h + +$(TOP)/win32/$(DEFFILE): $(TOP)/win32/$(DEFFILE).in + cscript $(TOP)\win32\replace.vbs $(TOP)/win32/$(DEFFILE).in $(TOP)/win32/$(DEFFILE) "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" $(STATICLIB): zconf $(OBJS) $(AR) $(ARFLAGS) -out:$@ $(OBJS) @@ -218,3 +236,9 @@ clean: distclean: clean -del zconf$(SUFFIX).h + -del zlib$(SUFFIX).h + -del zlib_name_mangling$(SUFFIX).h + -del $(TOP)\win32\zlib.def + -del $(TOP)\win32\zlibcompat.def + -del $(TOP)\win32\zlib-ng.def + -del gzread.c diff --git a/win32/Makefile.arm b/win32/Makefile.arm index c44c4d8c86..12b08dc671 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -16,6 +16,7 @@ LOC = STATICLIB = zlib.lib SHAREDLIB = zlib1.dll IMPLIB = zdll.lib +SYMBOL_PREFIX = CC = cl LD = link @@ -115,8 +116,25 @@ OBJS = $(OBJS) adler32_neon.obj chunkset_neon.obj slide_hash_neon.obj all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ example.exe minigzip.exe example_d.exe minigzip_d.exe -zconf: $(TOP)/zconf$(SUFFIX).h.in - $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h +!if "$(SYMBOL_PREFIX)" != "" +zlib_name_mangling$(SUFFIX).h: zlib_name_mangling$(SUFFIX).h.in + cscript $(TOP)\win32\replace.vbs $(TOP)\zlib_name_mangling$(SUFFIX).h.in zlib_name_mangling$(SUFFIX).h "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" +!else +zlib_name_mangling$(SUFFIX).h: zlib_name_mangling.h.empty + $(CP) $(TOP)\zlib_name_mangling.h.empty zlib_name_mangling$(SUFFIX).h +!endif + +zlib$(SUFFIX).h: zlib$(SUFFIX).h.in + cscript $(TOP)\win32\replace.vbs $(TOP)\zlib$(SUFFIX).h.in zlib$(SUFFIX).h "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" + +gzread.c: gzread.c.in + cscript $(TOP)\win32\replace.vbs $(TOP)\gzread.c.in gzread.c "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" + +zconf: $(TOP)/zconf$(SUFFIX).h.in $(TOP)/zlib$(SUFFIX).h $(TOP)/zlib_name_mangling$(SUFFIX).h + $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h + +$(TOP)/win32/$(DEFFILE): $(TOP)/win32/$(DEFFILE).in + cscript $(TOP)\win32\replace.vbs $(TOP)/win32/$(DEFFILE).in $(TOP)/win32/$(DEFFILE) "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" $(STATICLIB): zconf $(OBJS) $(AR) $(ARFLAGS) -out:$@ $(OBJS) @@ -229,3 +247,9 @@ clean: distclean: clean -del zconf$(SUFFIX).h + -del zlib$(SUFFIX).h + -del zlib_name_mangling$(SUFFIX).h + -del $(TOP)\win32\zlib.def + -del $(TOP)\win32\zlibcompat.def + -del $(TOP)\win32\zlib-ng.def + -del gzread.c diff --git a/win32/Makefile.msc b/win32/Makefile.msc index eec878f249..ef3f237ffc 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -16,6 +16,7 @@ LOC = STATICLIB = zlib.lib SHAREDLIB = zlib1.dll IMPLIB = zdll.lib +SYMBOL_PREFIX = CC = cl LD = link @@ -107,8 +108,25 @@ OBJS = $(OBJS) gzlib.obj gzread.obj gzwrite.obj all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ example.exe minigzip.exe example_d.exe minigzip_d.exe -zconf: $(TOP)/zconf$(SUFFIX).h.in - $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h +!if "$(SYMBOL_PREFIX)" != "" +zlib_name_mangling$(SUFFIX).h: zlib_name_mangling$(SUFFIX).h.in + cscript $(TOP)\win32\replace.vbs $(TOP)\zlib_name_mangling$(SUFFIX).h.in zlib_name_mangling$(SUFFIX).h "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" +!else +zlib_name_mangling$(SUFFIX).h: zlib_name_mangling.h.empty + $(CP) $(TOP)\zlib_name_mangling.h.empty zlib_name_mangling$(SUFFIX).h +!endif + +zlib$(SUFFIX).h: zlib$(SUFFIX).h.in + cscript $(TOP)\win32\replace.vbs $(TOP)\zlib$(SUFFIX).h.in zlib$(SUFFIX).h "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" + +gzread.c: gzread.c.in + cscript $(TOP)\win32\replace.vbs $(TOP)\gzread.c.in gzread.c "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" + +zconf: $(TOP)/zconf$(SUFFIX).h.in $(TOP)/zlib$(SUFFIX).h $(TOP)/zlib_name_mangling$(SUFFIX).h + $(CP) $(TOP)\zconf$(SUFFIX).h.in $(TOP)\zconf$(SUFFIX).h + +$(TOP)/win32/$(DEFFILE): $(TOP)/win32/$(DEFFILE).in + cscript $(TOP)\win32\replace.vbs $(TOP)/win32/$(DEFFILE).in $(TOP)/win32/$(DEFFILE) "@ZLIB_SYMBOL_PREFIX@" "$(SYMBOL_PREFIX)" $(STATICLIB): zconf $(OBJS) $(AR) $(ARFLAGS) -out:$@ $(OBJS) @@ -226,3 +244,9 @@ clean: distclean: clean -del zconf$(SUFFIX).h + -del zlib$(SUFFIX).h + -del zlib_name_mangling$(SUFFIX).h + -del $(TOP)\win32\zlib.def + -del $(TOP)\win32\zlibcompat.def + -del $(TOP)\win32\zlib-ng.def + -del gzread.c diff --git a/win32/replace.vbs b/win32/replace.vbs new file mode 100644 index 0000000000..6779971d07 --- /dev/null +++ b/win32/replace.vbs @@ -0,0 +1,15 @@ +strInputFileName = Wscript.Arguments(0) +strOutputFileName = Wscript.Arguments(1) +strOldText = Wscript.Arguments(2) +strNewText = Wscript.Arguments(3) + +Set objFSO = CreateObject("Scripting.FileSystemObject") +Set objFile = objFSO.OpenTextFile(strInputFileName, 1) + +strText = objFile.ReadAll +objFile.Close +strNewText = Replace(strText, strOldText, strNewText) + +Set objFile = objFSO.OpenTextFile(strOutputFileName, 2, True) +objFile.Write strNewText +objFile.Close diff --git a/win32/zlib-ng.def b/win32/zlib-ng.def deleted file mode 100644 index 467d790097..0000000000 --- a/win32/zlib-ng.def +++ /dev/null @@ -1,60 +0,0 @@ -; zlib-ng data compression library -EXPORTS -; basic functions - zlibng_version - zng_deflate - zng_deflateEnd - zng_inflate - zng_inflateEnd -; advanced functions - zng_deflateSetDictionary - zng_deflateGetDictionary - zng_deflateCopy - zng_deflateReset - zng_deflateParams - zng_deflateTune - zng_deflateBound - zng_deflatePending - zng_deflatePrime - zng_deflateSetHeader - zng_deflateSetParams - zng_deflateGetParams - zng_inflateSetDictionary - zng_inflateGetDictionary - zng_inflateSync - zng_inflateCopy - zng_inflateReset - zng_inflateReset2 - zng_inflatePrime - zng_inflateMark - zng_inflateGetHeader - zng_inflateBack - zng_inflateBackEnd - zng_zlibCompileFlags -; utility functions - zng_compress - zng_compress2 - zng_compressBound - zng_uncompress - zng_uncompress2 -; checksum functions - zng_adler32 - zng_adler32_z - zng_crc32 - zng_crc32_z - zng_adler32_combine - zng_crc32_combine -; various hacks, don't look :) - zng_deflateInit_ - zng_deflateInit2_ - zng_inflateInit_ - zng_inflateInit2_ - zng_inflateBackInit_ - zng_zError - zng_inflateSyncPoint - zng_get_crc_table - zng_inflateUndermine - zng_inflateValidate - zng_inflateCodesUsed - zng_inflateResetKeep - zng_deflateResetKeep diff --git a/win32/zlib-ng.def.in b/win32/zlib-ng.def.in new file mode 100644 index 0000000000..642acf7db6 --- /dev/null +++ b/win32/zlib-ng.def.in @@ -0,0 +1,60 @@ +; zlib-ng data compression library +EXPORTS +; basic functions + @ZLIB_SYMBOL_PREFIX@zlibng_version + @ZLIB_SYMBOL_PREFIX@zng_deflate + @ZLIB_SYMBOL_PREFIX@zng_deflateEnd + @ZLIB_SYMBOL_PREFIX@zng_inflate + @ZLIB_SYMBOL_PREFIX@zng_inflateEnd +; advanced functions + @ZLIB_SYMBOL_PREFIX@zng_deflateSetDictionary + @ZLIB_SYMBOL_PREFIX@zng_deflateGetDictionary + @ZLIB_SYMBOL_PREFIX@zng_deflateCopy + @ZLIB_SYMBOL_PREFIX@zng_deflateReset + @ZLIB_SYMBOL_PREFIX@zng_deflateParams + @ZLIB_SYMBOL_PREFIX@zng_deflateTune + @ZLIB_SYMBOL_PREFIX@zng_deflateBound + @ZLIB_SYMBOL_PREFIX@zng_deflatePending + @ZLIB_SYMBOL_PREFIX@zng_deflatePrime + @ZLIB_SYMBOL_PREFIX@zng_deflateSetHeader + @ZLIB_SYMBOL_PREFIX@zng_deflateSetParams + @ZLIB_SYMBOL_PREFIX@zng_deflateGetParams + @ZLIB_SYMBOL_PREFIX@zng_inflateSetDictionary + @ZLIB_SYMBOL_PREFIX@zng_inflateGetDictionary + @ZLIB_SYMBOL_PREFIX@zng_inflateSync + @ZLIB_SYMBOL_PREFIX@zng_inflateCopy + @ZLIB_SYMBOL_PREFIX@zng_inflateReset + @ZLIB_SYMBOL_PREFIX@zng_inflateReset2 + @ZLIB_SYMBOL_PREFIX@zng_inflatePrime + @ZLIB_SYMBOL_PREFIX@zng_inflateMark + @ZLIB_SYMBOL_PREFIX@zng_inflateGetHeader + @ZLIB_SYMBOL_PREFIX@zng_inflateBack + @ZLIB_SYMBOL_PREFIX@zng_inflateBackEnd + @ZLIB_SYMBOL_PREFIX@zng_zlibCompileFlags +; utility functions + @ZLIB_SYMBOL_PREFIX@zng_compress + @ZLIB_SYMBOL_PREFIX@zng_compress2 + @ZLIB_SYMBOL_PREFIX@zng_compressBound + @ZLIB_SYMBOL_PREFIX@zng_uncompress + @ZLIB_SYMBOL_PREFIX@zng_uncompress2 +; checksum functions + @ZLIB_SYMBOL_PREFIX@zng_adler32 + @ZLIB_SYMBOL_PREFIX@zng_adler32_z + @ZLIB_SYMBOL_PREFIX@zng_crc32 + @ZLIB_SYMBOL_PREFIX@zng_crc32_z + @ZLIB_SYMBOL_PREFIX@zng_adler32_combine + @ZLIB_SYMBOL_PREFIX@zng_crc32_combine +; various hacks, don't look :) + @ZLIB_SYMBOL_PREFIX@zng_deflateInit_ + @ZLIB_SYMBOL_PREFIX@zng_deflateInit2_ + @ZLIB_SYMBOL_PREFIX@zng_inflateInit_ + @ZLIB_SYMBOL_PREFIX@zng_inflateInit2_ + @ZLIB_SYMBOL_PREFIX@zng_inflateBackInit_ + @ZLIB_SYMBOL_PREFIX@zng_zError + @ZLIB_SYMBOL_PREFIX@zng_inflateSyncPoint + @ZLIB_SYMBOL_PREFIX@zng_get_crc_table + @ZLIB_SYMBOL_PREFIX@zng_inflateUndermine + @ZLIB_SYMBOL_PREFIX@zng_inflateValidate + @ZLIB_SYMBOL_PREFIX@zng_inflateCodesUsed + @ZLIB_SYMBOL_PREFIX@zng_inflateResetKeep + @ZLIB_SYMBOL_PREFIX@zng_deflateResetKeep diff --git a/win32/zlib-ng1.rc b/win32/zlib-ng1.rc index b53906904b..f524131462 100644 --- a/win32/zlib-ng1.rc +++ b/win32/zlib-ng1.rc @@ -1,5 +1,5 @@ #include -#include "../zlib-ng.h" +#include "zlib-ng.h" #ifdef GCC_WINDRES VS_VERSION_INFO VERSIONINFO diff --git a/win32/zlib.def b/win32/zlib.def deleted file mode 100644 index 67644205a7..0000000000 --- a/win32/zlib.def +++ /dev/null @@ -1,61 +0,0 @@ -; zlib data compression library -EXPORTS -; basic functions - zlibVersion - deflate - deflateEnd - inflate - inflateEnd -; advanced functions - deflateSetDictionary - deflateGetDictionary - deflateCopy - deflateReset - deflateParams - deflateTune - deflateBound - deflatePending - deflatePrime - deflateSetHeader - inflateSetDictionary - inflateGetDictionary - inflateSync - inflateCopy - inflateReset - inflateReset2 - inflatePrime - inflateMark - inflateGetHeader - inflateBack - inflateBackEnd - zlibCompileFlags -; utility functions - compress - compress2 - compressBound - uncompress - uncompress2 -; large file functions - adler32_combine64 - crc32_combine64 -; checksum functions - adler32 - adler32_z - crc32 - crc32_z - adler32_combine - crc32_combine -; various hacks, don't look :) - deflateInit_ - deflateInit2_ - inflateInit_ - inflateInit2_ - inflateBackInit_ - zError - inflateSyncPoint - get_crc_table - inflateUndermine - inflateValidate - inflateCodesUsed - inflateResetKeep - deflateResetKeep diff --git a/win32/zlib.def.in b/win32/zlib.def.in new file mode 100644 index 0000000000..66a6f66fb4 --- /dev/null +++ b/win32/zlib.def.in @@ -0,0 +1,61 @@ +; zlib data compression library +EXPORTS +; basic functions + @ZLIB_SYMBOL_PREFIX@zlibVersion + @ZLIB_SYMBOL_PREFIX@deflate + @ZLIB_SYMBOL_PREFIX@deflateEnd + @ZLIB_SYMBOL_PREFIX@inflate + @ZLIB_SYMBOL_PREFIX@inflateEnd +; advanced functions + @ZLIB_SYMBOL_PREFIX@deflateSetDictionary + @ZLIB_SYMBOL_PREFIX@deflateGetDictionary + @ZLIB_SYMBOL_PREFIX@deflateCopy + @ZLIB_SYMBOL_PREFIX@deflateReset + @ZLIB_SYMBOL_PREFIX@deflateParams + @ZLIB_SYMBOL_PREFIX@deflateTune + @ZLIB_SYMBOL_PREFIX@deflateBound + @ZLIB_SYMBOL_PREFIX@deflatePending + @ZLIB_SYMBOL_PREFIX@deflatePrime + @ZLIB_SYMBOL_PREFIX@deflateSetHeader + @ZLIB_SYMBOL_PREFIX@inflateSetDictionary + @ZLIB_SYMBOL_PREFIX@inflateGetDictionary + @ZLIB_SYMBOL_PREFIX@inflateSync + @ZLIB_SYMBOL_PREFIX@inflateCopy + @ZLIB_SYMBOL_PREFIX@inflateReset + @ZLIB_SYMBOL_PREFIX@inflateReset2 + @ZLIB_SYMBOL_PREFIX@inflatePrime + @ZLIB_SYMBOL_PREFIX@inflateMark + @ZLIB_SYMBOL_PREFIX@inflateGetHeader + @ZLIB_SYMBOL_PREFIX@inflateBack + @ZLIB_SYMBOL_PREFIX@inflateBackEnd + @ZLIB_SYMBOL_PREFIX@zlibCompileFlags +; utility functions + @ZLIB_SYMBOL_PREFIX@compress + @ZLIB_SYMBOL_PREFIX@compress2 + @ZLIB_SYMBOL_PREFIX@compressBound + @ZLIB_SYMBOL_PREFIX@uncompress + @ZLIB_SYMBOL_PREFIX@uncompress2 +; large file functions + @ZLIB_SYMBOL_PREFIX@adler32_combine64 + @ZLIB_SYMBOL_PREFIX@crc32_combine64 +; checksum functions + @ZLIB_SYMBOL_PREFIX@adler32 + @ZLIB_SYMBOL_PREFIX@adler32_z + @ZLIB_SYMBOL_PREFIX@crc32 + @ZLIB_SYMBOL_PREFIX@crc32_z + @ZLIB_SYMBOL_PREFIX@adler32_combine + @ZLIB_SYMBOL_PREFIX@crc32_combine +; various hacks, don't look :) + @ZLIB_SYMBOL_PREFIX@deflateInit_ + @ZLIB_SYMBOL_PREFIX@deflateInit2_ + @ZLIB_SYMBOL_PREFIX@inflateInit_ + @ZLIB_SYMBOL_PREFIX@inflateInit2_ + @ZLIB_SYMBOL_PREFIX@inflateBackInit_ + @ZLIB_SYMBOL_PREFIX@zError + @ZLIB_SYMBOL_PREFIX@inflateSyncPoint + @ZLIB_SYMBOL_PREFIX@get_crc_table + @ZLIB_SYMBOL_PREFIX@inflateUndermine + @ZLIB_SYMBOL_PREFIX@inflateValidate + @ZLIB_SYMBOL_PREFIX@inflateCodesUsed + @ZLIB_SYMBOL_PREFIX@inflateResetKeep + @ZLIB_SYMBOL_PREFIX@deflateResetKeep diff --git a/win32/zlib1.rc b/win32/zlib1.rc index 11be5f49f9..ee0b287953 100644 --- a/win32/zlib1.rc +++ b/win32/zlib1.rc @@ -1,5 +1,5 @@ #include -#include "../zlib.h" +#include "zlib.h" #ifdef GCC_WINDRES VS_VERSION_INFO VERSIONINFO diff --git a/win32/zlibcompat.def b/win32/zlibcompat.def deleted file mode 100644 index a2188b0006..0000000000 --- a/win32/zlibcompat.def +++ /dev/null @@ -1,94 +0,0 @@ -; zlib data compression library -EXPORTS -; basic functions - zlibVersion - deflate - deflateEnd - inflate - inflateEnd -; advanced functions - deflateSetDictionary - deflateGetDictionary - deflateCopy - deflateReset - deflateParams - deflateTune - deflateBound - deflatePending - deflatePrime - deflateSetHeader - inflateSetDictionary - inflateGetDictionary - inflateSync - inflateCopy - inflateReset - inflateReset2 - inflatePrime - inflateMark - inflateGetHeader - inflateBack - inflateBackEnd - zlibCompileFlags -; utility functions - compress - compress2 - compressBound - uncompress - uncompress2 - gzopen - gzdopen - gzbuffer - gzsetparams - gzread - gzfread - gzwrite - gzfwrite - gzprintf - gzvprintf - gzputs - gzgets - gzputc - gzgetc - gzungetc - gzflush - gzseek - gzrewind - gztell - gzoffset - gzeof - gzdirect - gzclose - gzclose_r - gzclose_w - gzerror - gzclearerr -; large file functions - gzopen64 - gzseek64 - gztell64 - gzoffset64 - adler32_combine64 - crc32_combine64 -; checksum functions - adler32 - adler32_z - crc32 - crc32_z - adler32_combine - crc32_combine -; various hacks, don't look :) - deflateInit_ - deflateInit2_ - inflateInit_ - inflateInit2_ - inflateBackInit_ - gzgetc_ - zError - inflateSyncPoint - get_crc_table - inflateUndermine - inflateValidate - inflateCodesUsed - inflateResetKeep - deflateResetKeep - gzopen_w diff --git a/win32/zlibcompat.def.in b/win32/zlibcompat.def.in new file mode 100644 index 0000000000..dbb3c3f712 --- /dev/null +++ b/win32/zlibcompat.def.in @@ -0,0 +1,94 @@ +; zlib data compression library +EXPORTS +; basic functions + @ZLIB_SYMBOL_PREFIX@zlibVersion + @ZLIB_SYMBOL_PREFIX@deflate + @ZLIB_SYMBOL_PREFIX@deflateEnd + @ZLIB_SYMBOL_PREFIX@inflate + @ZLIB_SYMBOL_PREFIX@inflateEnd +; advanced functions + @ZLIB_SYMBOL_PREFIX@deflateSetDictionary + @ZLIB_SYMBOL_PREFIX@deflateGetDictionary + @ZLIB_SYMBOL_PREFIX@deflateCopy + @ZLIB_SYMBOL_PREFIX@deflateReset + @ZLIB_SYMBOL_PREFIX@deflateParams + @ZLIB_SYMBOL_PREFIX@deflateTune + @ZLIB_SYMBOL_PREFIX@deflateBound + @ZLIB_SYMBOL_PREFIX@deflatePending + @ZLIB_SYMBOL_PREFIX@deflatePrime + @ZLIB_SYMBOL_PREFIX@deflateSetHeader + @ZLIB_SYMBOL_PREFIX@inflateSetDictionary + @ZLIB_SYMBOL_PREFIX@inflateGetDictionary + @ZLIB_SYMBOL_PREFIX@inflateSync + @ZLIB_SYMBOL_PREFIX@inflateCopy + @ZLIB_SYMBOL_PREFIX@inflateReset + @ZLIB_SYMBOL_PREFIX@inflateReset2 + @ZLIB_SYMBOL_PREFIX@inflatePrime + @ZLIB_SYMBOL_PREFIX@inflateMark + @ZLIB_SYMBOL_PREFIX@inflateGetHeader + @ZLIB_SYMBOL_PREFIX@inflateBack + @ZLIB_SYMBOL_PREFIX@inflateBackEnd + @ZLIB_SYMBOL_PREFIX@zlibCompileFlags +; utility functions + @ZLIB_SYMBOL_PREFIX@compress + @ZLIB_SYMBOL_PREFIX@compress2 + @ZLIB_SYMBOL_PREFIX@compressBound + @ZLIB_SYMBOL_PREFIX@uncompress + @ZLIB_SYMBOL_PREFIX@uncompress2 + @ZLIB_SYMBOL_PREFIX@gzopen + @ZLIB_SYMBOL_PREFIX@gzdopen + @ZLIB_SYMBOL_PREFIX@gzbuffer + @ZLIB_SYMBOL_PREFIX@gzsetparams + @ZLIB_SYMBOL_PREFIX@gzread + @ZLIB_SYMBOL_PREFIX@gzfread + @ZLIB_SYMBOL_PREFIX@gzwrite + @ZLIB_SYMBOL_PREFIX@gzfwrite + @ZLIB_SYMBOL_PREFIX@gzprintf + @ZLIB_SYMBOL_PREFIX@gzvprintf + @ZLIB_SYMBOL_PREFIX@gzputs + @ZLIB_SYMBOL_PREFIX@gzgets + @ZLIB_SYMBOL_PREFIX@gzputc + @ZLIB_SYMBOL_PREFIX@gzgetc + @ZLIB_SYMBOL_PREFIX@gzungetc + @ZLIB_SYMBOL_PREFIX@gzflush + @ZLIB_SYMBOL_PREFIX@gzseek + @ZLIB_SYMBOL_PREFIX@gzrewind + @ZLIB_SYMBOL_PREFIX@gztell + @ZLIB_SYMBOL_PREFIX@gzoffset + @ZLIB_SYMBOL_PREFIX@gzeof + @ZLIB_SYMBOL_PREFIX@gzdirect + @ZLIB_SYMBOL_PREFIX@gzclose + @ZLIB_SYMBOL_PREFIX@gzclose_r + @ZLIB_SYMBOL_PREFIX@gzclose_w + @ZLIB_SYMBOL_PREFIX@gzerror + @ZLIB_SYMBOL_PREFIX@gzclearerr +; large file functions + @ZLIB_SYMBOL_PREFIX@gzopen64 + @ZLIB_SYMBOL_PREFIX@gzseek64 + @ZLIB_SYMBOL_PREFIX@gztell64 + @ZLIB_SYMBOL_PREFIX@gzoffset64 + @ZLIB_SYMBOL_PREFIX@adler32_combine64 + @ZLIB_SYMBOL_PREFIX@crc32_combine64 +; checksum functions + @ZLIB_SYMBOL_PREFIX@adler32 + @ZLIB_SYMBOL_PREFIX@adler32_z + @ZLIB_SYMBOL_PREFIX@crc32 + @ZLIB_SYMBOL_PREFIX@crc32_z + @ZLIB_SYMBOL_PREFIX@adler32_combine + @ZLIB_SYMBOL_PREFIX@crc32_combine +; various hacks, don't look :) + @ZLIB_SYMBOL_PREFIX@deflateInit_ + @ZLIB_SYMBOL_PREFIX@deflateInit2_ + @ZLIB_SYMBOL_PREFIX@inflateInit_ + @ZLIB_SYMBOL_PREFIX@inflateInit2_ + @ZLIB_SYMBOL_PREFIX@inflateBackInit_ + @ZLIB_SYMBOL_PREFIX@gzgetc_ + @ZLIB_SYMBOL_PREFIX@zError + @ZLIB_SYMBOL_PREFIX@inflateSyncPoint + @ZLIB_SYMBOL_PREFIX@get_crc_table + @ZLIB_SYMBOL_PREFIX@inflateUndermine + @ZLIB_SYMBOL_PREFIX@inflateValidate + @ZLIB_SYMBOL_PREFIX@inflateCodesUsed + @ZLIB_SYMBOL_PREFIX@inflateResetKeep + @ZLIB_SYMBOL_PREFIX@deflateResetKeep + @ZLIB_SYMBOL_PREFIX@gzopen_w diff --git a/zconf-ng.h.in b/zconf-ng.h.in index 66ab4cf662..21629c7b30 100644 --- a/zconf-ng.h.in +++ b/zconf-ng.h.in @@ -6,6 +6,8 @@ #ifndef ZCONFNG_H #define ZCONFNG_H +#include "zlib_name_mangling-ng.h" + #if !defined(_WIN32) && defined(__WIN32__) # define _WIN32 #endif diff --git a/zconf.h.in b/zconf.h.in index 2c6b12dff1..fef6bab42d 100644 --- a/zconf.h.in +++ b/zconf.h.in @@ -6,6 +6,8 @@ #ifndef ZCONF_H #define ZCONF_H +#include "zlib_name_mangling.h" + #if !defined(_WIN32) && defined(__WIN32__) # define _WIN32 #endif diff --git a/zlib-ng.h b/zlib-ng.h.in similarity index 99% rename from zlib-ng.h rename to zlib-ng.h.in index 36750cf1d7..2603707816 100644 --- a/zlib-ng.h +++ b/zlib-ng.h.in @@ -1800,13 +1800,13 @@ Z_EXTERN Z_EXPORT int32_t zng_inflateInit2_(zng_stream *strm, int32_t windowBit Z_EXTERN Z_EXPORT int32_t zng_inflateBackInit_(zng_stream *strm, int32_t windowBits, uint8_t *window, const char *version, int32_t stream_size); -#define zng_deflateInit(strm, level) zng_deflateInit_((strm), (level), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define zng_inflateInit(strm) zng_inflateInit_((strm), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define zng_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ +#define @ZLIB_SYMBOL_PREFIX@zng_deflateInit(strm, level) zng_deflateInit_((strm), (level), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) +#define @ZLIB_SYMBOL_PREFIX@zng_inflateInit(strm) zng_inflateInit_((strm), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) +#define @ZLIB_SYMBOL_PREFIX@zng_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ zng_deflateInit2_((strm), (level), (method), (windowBits), (memLevel), \ (strategy), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define zng_inflateInit2(strm, windowBits) zng_inflateInit2_((strm), (windowBits), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) -#define zng_inflateBackInit(strm, windowBits, window) \ +#define @ZLIB_SYMBOL_PREFIX@zng_inflateInit2(strm, windowBits) zng_inflateInit2_((strm), (windowBits), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) +#define @ZLIB_SYMBOL_PREFIX@zng_inflateBackInit(strm, windowBits, window) \ zng_inflateBackInit_((strm), (windowBits), (window), ZLIBNG_VERSION, (int32_t)sizeof(zng_stream)) #ifdef WITH_GZFILEOP @@ -1824,7 +1824,7 @@ struct gzFile_s { z_off64_t pos; }; Z_EXTERN Z_EXPORT int32_t zng_gzgetc_(gzFile file); /* backward compatibility */ -# define zng_gzgetc(g) ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (zng_gzgetc)(g)) +# define @ZLIB_SYMBOL_PREFIX@zng_gzgetc(g) ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (@ZLIB_SYMBOL_PREFIX@zng_gzgetc)(g)) #endif /* WITH_GZFILEOP */ diff --git a/zlib.h b/zlib.h.in similarity index 98% rename from zlib.h rename to zlib.h.in index 842559485d..40d1f73e2e 100644 --- a/zlib.h +++ b/zlib.h.in @@ -1757,13 +1757,13 @@ Z_EXTERN int Z_EXPORT deflateInit2_(z_stream *strm, int level, int method, int Z_EXTERN int Z_EXPORT inflateInit2_(z_stream *strm, int windowBits, const char *version, int stream_size); Z_EXTERN int Z_EXPORT inflateBackInit_(z_stream *strm, int windowBits, unsigned char *window, const char *version, int stream_size); -#define deflateInit(strm, level) deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit(strm) inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ +#define @ZLIB_SYMBOL_PREFIX@deflateInit(strm, level) deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +#define @ZLIB_SYMBOL_PREFIX@inflateInit(strm) inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +#define @ZLIB_SYMBOL_PREFIX@deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm), (level), (method), (windowBits), (memLevel), \ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) inflateInit2_((strm), (windowBits), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ +#define @ZLIB_SYMBOL_PREFIX@inflateInit2(strm, windowBits) inflateInit2_((strm), (windowBits), ZLIB_VERSION, (int)sizeof(z_stream)) +#define @ZLIB_SYMBOL_PREFIX@inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), ZLIB_VERSION, (int)sizeof(z_stream)) @@ -1781,7 +1781,7 @@ struct gzFile_s { z_off64_t pos; }; Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ -# define gzgetc(g) ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +# define @ZLIB_SYMBOL_PREFIX@gzgetc(g) ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (@ZLIB_SYMBOL_PREFIX@gzgetc)(g)) /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if @@ -1801,21 +1801,21 @@ Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ #endif #if !defined(Z_INTERNAL) && defined(Z_WANT64) -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# define crc32_combine_gen crc32_combine_gen64 +# define @ZLIB_SYMBOL_PREFIX@gzopen @ZLIB_SYMBOL_PREFIX@gzopen64 +# define @ZLIB_SYMBOL_PREFIX@gzseek @ZLIB_SYMBOL_PREFIX@gzseek64 +# define @ZLIB_SYMBOL_PREFIX@gztell @ZLIB_SYMBOL_PREFIX@gztell64 +# define @ZLIB_SYMBOL_PREFIX@gzoffset @ZLIB_SYMBOL_PREFIX@gzoffset64 +# define @ZLIB_SYMBOL_PREFIX@adler32_combine @ZLIB_SYMBOL_PREFIX@adler32_combine64 +# define @ZLIB_SYMBOL_PREFIX@crc32_combine @ZLIB_SYMBOL_PREFIX@crc32_combine64 +# define @ZLIB_SYMBOL_PREFIX@crc32_combine_gen @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64 # ifndef Z_LARGE64 - Z_EXTERN gzFile Z_EXPORT gzopen64(const char *, const char *); - Z_EXTERN z_off_t Z_EXPORT gzseek64(gzFile, z_off_t, int); - Z_EXTERN z_off_t Z_EXPORT gztell64(gzFile); - Z_EXTERN z_off_t Z_EXPORT gzoffset64(gzFile); - Z_EXTERN unsigned long Z_EXPORT adler32_combine64(unsigned long, unsigned long, z_off_t); - Z_EXTERN unsigned long Z_EXPORT crc32_combine64(unsigned long, unsigned long, z_off_t); - Z_EXTERN void Z_EXPORT crc32_combine_gen64(uint32_t *op, z_off64_t); + Z_EXTERN gzFile Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzopen64(const char *, const char *); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzseek64(gzFile, z_off_t, int); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gztell64(gzFile); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzoffset64(gzFile); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@adler32_combine64(unsigned long, unsigned long, z_off_t); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine64(unsigned long, unsigned long, z_off_t); + Z_EXTERN void Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64(uint32_t *op, z_off64_t); # endif #else Z_EXTERN gzFile Z_EXPORT gzopen(const char *, const char *); diff --git a/zlib.pc.cmakein b/zlib.pc.cmakein index 9b64252dc2..3d440ce6bd 100644 --- a/zlib.pc.cmakein +++ b/zlib.pc.cmakein @@ -1,5 +1,6 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} +symbol_prefix=@ZLIB_SYMBOL_PREFIX@ libdir=@PC_LIB_INSTALL_DIR@ sharedlibdir=${libdir} includedir=@PC_INC_INSTALL_DIR@ diff --git a/zlib.pc.in b/zlib.pc.in index d0a6766b5c..a0678fbe03 100644 --- a/zlib.pc.in +++ b/zlib.pc.in @@ -1,5 +1,6 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ +symbol_prefix=@symbol_prefix@ libdir=@libdir@ sharedlibdir=@sharedlibdir@ includedir=@includedir@ diff --git a/zlib_name_mangling-ng.h.in b/zlib_name_mangling-ng.h.in new file mode 100644 index 0000000000..7c754fc1e6 --- /dev/null +++ b/zlib_name_mangling-ng.h.in @@ -0,0 +1,173 @@ +/* zlib_name_mangling.h has been automatically generated from + * zlib_name_mangling.h.in because ZLIB_SYMBOL_PREFIX was set. + */ + +#ifndef ZLIB_NAME_MANGLING_H +#define ZLIB_NAME_MANGLING_H + +/* all linked symbols and init macros */ +#define zng__dist_code @ZLIB_SYMBOL_PREFIX@zng__dist_code +#define zng__length_code @ZLIB_SYMBOL_PREFIX@zng__length_code +#define zng__tr_align @ZLIB_SYMBOL_PREFIX@zng__tr_align +#define zng__tr_flush_bits @ZLIB_SYMBOL_PREFIX@zng__tr_flush_bits +#define zng__tr_flush_block @ZLIB_SYMBOL_PREFIX@zng__tr_flush_block +#define zng__tr_init @ZLIB_SYMBOL_PREFIX@zng__tr_init +#define zng__tr_stored_block @ZLIB_SYMBOL_PREFIX@zng__tr_stored_block +#define zng__tr_tally @ZLIB_SYMBOL_PREFIX@zng__tr_tally +#define zng_adler32 @ZLIB_SYMBOL_PREFIX@zng_adler32 +#define zng_adler32_combine @ZLIB_SYMBOL_PREFIX@zng_adler32_combine +#define zng_adler32_combine64 @ZLIB_SYMBOL_PREFIX@zng_adler32_combine64 +#define zng_adler32_z @ZLIB_SYMBOL_PREFIX@zng_adler32_z +#ifndef Z_SOLO +# define zng_compress @ZLIB_SYMBOL_PREFIX@zng_compress +# define zng_compress2 @ZLIB_SYMBOL_PREFIX@zng_compress2 +# define zng_compressBound @ZLIB_SYMBOL_PREFIX@zng_compressBound +#endif +#define zng_crc32 @ZLIB_SYMBOL_PREFIX@zng_crc32 +#define zng_crc32_combine @ZLIB_SYMBOL_PREFIX@zng_crc32_combine +#define zng_crc32_combine64 @ZLIB_SYMBOL_PREFIX@zng_crc32_combine64 +#define zng_crc32_z @ZLIB_SYMBOL_PREFIX@zng_crc32_z +#define zng_deflate @ZLIB_SYMBOL_PREFIX@zng_deflate +#define zng_deflateBound @ZLIB_SYMBOL_PREFIX@zng_deflateBound +#define zng_deflateCopy @ZLIB_SYMBOL_PREFIX@zng_deflateCopy +#define zng_deflateEnd @ZLIB_SYMBOL_PREFIX@zng_deflateEnd +#define zng_deflateGetDictionary @ZLIB_SYMBOL_PREFIX@zng_deflateGetDictionary +#define zng_deflateInit @ZLIB_SYMBOL_PREFIX@zng_deflateInit +#define zng_deflateInit2 @ZLIB_SYMBOL_PREFIX@zng_deflateInit2 +#define zng_deflateInit2_ @ZLIB_SYMBOL_PREFIX@zng_deflateInit2_ +#define zng_deflateInit_ @ZLIB_SYMBOL_PREFIX@zng_deflateInit_ +#define zng_deflateParams @ZLIB_SYMBOL_PREFIX@zng_deflateParams +#define zng_deflatePending @ZLIB_SYMBOL_PREFIX@zng_deflatePending +#define zng_deflatePrime @ZLIB_SYMBOL_PREFIX@zng_deflatePrime +#define zng_deflateReset @ZLIB_SYMBOL_PREFIX@zng_deflateReset +#define zng_deflateResetKeep @ZLIB_SYMBOL_PREFIX@zng_deflateResetKeep +#define zng_deflateSetDictionary @ZLIB_SYMBOL_PREFIX@zng_deflateSetDictionary +#define zng_deflateSetHeader @ZLIB_SYMBOL_PREFIX@zng_deflateSetHeader +#define zng_deflateTune @ZLIB_SYMBOL_PREFIX@zng_deflateTune +#define zng_deflate_copyright @ZLIB_SYMBOL_PREFIX@zng_deflate_copyright +#define zng_get_crc_table @ZLIB_SYMBOL_PREFIX@zng_get_crc_table +#ifndef Z_SOLO +# define zng_gz_error @ZLIB_SYMBOL_PREFIX@zng_gz_error +# define zng_gz_intmax @ZLIB_SYMBOL_PREFIX@zng_gz_intmax +# define zng_gz_strwinerror @ZLIB_SYMBOL_PREFIX@zng_gz_strwinerror +# define zng_gzbuffer @ZLIB_SYMBOL_PREFIX@zng_gzbuffer +# define zng_gzclearerr @ZLIB_SYMBOL_PREFIX@zng_gzclearerr +# define zng_gzclose @ZLIB_SYMBOL_PREFIX@zng_gzclose +# define zng_gzclose_r @ZLIB_SYMBOL_PREFIX@zng_gzclose_r +# define zng_gzclose_w @ZLIB_SYMBOL_PREFIX@zng_gzclose_w +# define zng_gzdirect @ZLIB_SYMBOL_PREFIX@zng_gzdirect +# define zng_gzdopen @ZLIB_SYMBOL_PREFIX@zng_gzdopen +# define zng_gzeof @ZLIB_SYMBOL_PREFIX@zng_gzeof +# define zng_gzerror @ZLIB_SYMBOL_PREFIX@zng_gzerror +# define zng_gzflush @ZLIB_SYMBOL_PREFIX@zng_gzflush +# define zng_gzfread @ZLIB_SYMBOL_PREFIX@zng_gzfread +# define zng_gzfwrite @ZLIB_SYMBOL_PREFIX@zng_gzfwrite +# define zng_gzgetc @ZLIB_SYMBOL_PREFIX@zng_gzgetc +# define zng_gzgetc_ @ZLIB_SYMBOL_PREFIX@zng_gzgetc_ +# define zng_gzgets @ZLIB_SYMBOL_PREFIX@zng_gzgets +# define zng_gzoffset @ZLIB_SYMBOL_PREFIX@zng_gzoffset +# define zng_gzoffset64 @ZLIB_SYMBOL_PREFIX@zng_gzoffset64 +# define zng_gzopen @ZLIB_SYMBOL_PREFIX@zng_gzopen +# define zng_gzopen64 @ZLIB_SYMBOL_PREFIX@zng_gzopen64 +# ifdef _WIN32 +# define zng_gzopen_w @ZLIB_SYMBOL_PREFIX@zng_gzopen_w +# endif +# define zng_gzprintf @ZLIB_SYMBOL_PREFIX@zng_gzprintf +# define zng_gzputc @ZLIB_SYMBOL_PREFIX@zng_gzputc +# define zng_gzputs @ZLIB_SYMBOL_PREFIX@zng_gzputs +# define zng_gzread @ZLIB_SYMBOL_PREFIX@zng_gzread +# define zng_gzrewind @ZLIB_SYMBOL_PREFIX@zng_gzrewind +# define zng_gzseek @ZLIB_SYMBOL_PREFIX@zng_gzseek +# define zng_gzseek64 @ZLIB_SYMBOL_PREFIX@zng_gzseek64 +# define zng_gzsetparams @ZLIB_SYMBOL_PREFIX@zng_gzsetparams +# define zng_gztell @ZLIB_SYMBOL_PREFIX@zng_gztell +# define zng_gztell64 @ZLIB_SYMBOL_PREFIX@zng_gztell64 +# define zng_gzungetc @ZLIB_SYMBOL_PREFIX@zng_gzungetc +# define zng_gzvprintf @ZLIB_SYMBOL_PREFIX@zng_gzvprintf +# define zng_gzwrite @ZLIB_SYMBOL_PREFIX@zng_gzwrite +#endif +#define zng_inflate @ZLIB_SYMBOL_PREFIX@zng_inflate +#define zng_inflateBack @ZLIB_SYMBOL_PREFIX@zng_inflateBack +#define zng_inflateBackEnd @ZLIB_SYMBOL_PREFIX@zng_inflateBackEnd +#define zng_inflateBackInit @ZLIB_SYMBOL_PREFIX@zng_inflateBackInit +#define zng_inflateBackInit_ @ZLIB_SYMBOL_PREFIX@zng_inflateBackInit_ +#define zng_inflateCodesUsed @ZLIB_SYMBOL_PREFIX@zng_inflateCodesUsed +#define zng_inflateCopy @ZLIB_SYMBOL_PREFIX@zng_inflateCopy +#define zng_inflateEnd @ZLIB_SYMBOL_PREFIX@zng_inflateEnd +#define zng_inflateGetDictionary @ZLIB_SYMBOL_PREFIX@zng_inflateGetDictionary +#define zng_inflateGetHeader @ZLIB_SYMBOL_PREFIX@zng_inflateGetHeader +#define zng_inflateInit @ZLIB_SYMBOL_PREFIX@zng_inflateInit +#define zng_inflateInit2 @ZLIB_SYMBOL_PREFIX@zng_inflateInit2 +#define zng_inflateInit2_ @ZLIB_SYMBOL_PREFIX@zng_inflateInit2_ +#define zng_inflateInit_ @ZLIB_SYMBOL_PREFIX@zng_inflateInit_ +#define zng_inflateMark @ZLIB_SYMBOL_PREFIX@zng_inflateMark +#define zng_inflatePrime @ZLIB_SYMBOL_PREFIX@zng_inflatePrime +#define zng_inflateReset @ZLIB_SYMBOL_PREFIX@zng_inflateReset +#define zng_inflateReset2 @ZLIB_SYMBOL_PREFIX@zng_inflateReset2 +#define zng_inflateResetKeep @ZLIB_SYMBOL_PREFIX@zng_inflateResetKeep +#define zng_inflateSetDictionary @ZLIB_SYMBOL_PREFIX@zng_inflateSetDictionary +#define zng_inflateSync @ZLIB_SYMBOL_PREFIX@zng_inflateSync +#define zng_inflateSyncPoint @ZLIB_SYMBOL_PREFIX@zng_inflateSyncPoint +#define zng_inflateUndermine @ZLIB_SYMBOL_PREFIX@zng_inflateUndermine +#define zng_inflateValidate @ZLIB_SYMBOL_PREFIX@zng_inflateValidate +#define zng_inflate_copyright @ZLIB_SYMBOL_PREFIX@zng_inflate_copyright +#define zng_inflate_fast @ZLIB_SYMBOL_PREFIX@zng_inflate_fast +#define zng_inflate_table @ZLIB_SYMBOL_PREFIX@zng_inflate_table +#ifndef Z_SOLO +# define zng_uncompress @ZLIB_SYMBOL_PREFIX@zng_uncompress +# define zng_uncompress2 @ZLIB_SYMBOL_PREFIX@zng_uncompress2 +#endif +#define zng_zError @ZLIB_SYMBOL_PREFIX@zng_zError +#ifndef Z_SOLO +# define zng_zcalloc @ZLIB_SYMBOL_PREFIX@zng_zcalloc +# define zng_zcfree @ZLIB_SYMBOL_PREFIX@zng_zcfree +#endif +#define zng_zlibCompileFlags @ZLIB_SYMBOL_PREFIX@zng_zlibCompileFlags +#define zng_zlibVersion @ZLIB_SYMBOL_PREFIX@zng_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +#define Byte @ZLIB_SYMBOL_PREFIX@Byte +#define Bytef @ZLIB_SYMBOL_PREFIX@Bytef +#define alloc_func @ZLIB_SYMBOL_PREFIX@alloc_func +#define charf @ZLIB_SYMBOL_PREFIX@charf +#define free_func @ZLIB_SYMBOL_PREFIX@free_func +#ifndef Z_SOLO +# define gzFile @ZLIB_SYMBOL_PREFIX@gzFile +#endif +#define gz_header @ZLIB_SYMBOL_PREFIX@gz_header +#define gz_headerp @ZLIB_SYMBOL_PREFIX@gz_headerp +#define in_func @ZLIB_SYMBOL_PREFIX@in_func +#define intf @ZLIB_SYMBOL_PREFIX@intf +#define out_func @ZLIB_SYMBOL_PREFIX@out_func +#define uInt @ZLIB_SYMBOL_PREFIX@uInt +#define uIntf @ZLIB_SYMBOL_PREFIX@uIntf +#define uLong @ZLIB_SYMBOL_PREFIX@uLong +#define uLongf @ZLIB_SYMBOL_PREFIX@uLongf +#define voidp @ZLIB_SYMBOL_PREFIX@voidp +#define voidpc @ZLIB_SYMBOL_PREFIX@voidpc +#define voidpf @ZLIB_SYMBOL_PREFIX@voidpf + +/* all zlib structs in zlib.h and zconf.h */ +#define zng_gz_header_s @ZLIB_SYMBOL_PREFIX@zng_gz_header_s +#define internal_state @ZLIB_SYMBOL_PREFIX@internal_state + +/* zlib-ng specific symbols */ +#define zng_deflate_param @ZLIB_SYMBOL_PREFIX@zng_deflate_param +#define zng_deflate_param_value @ZLIB_SYMBOL_PREFIX@zng_deflate_param_value +#define zng_deflateSetParams @ZLIB_SYMBOL_PREFIX@zng_deflateSetParams +#define zng_deflateGetParams @ZLIB_SYMBOL_PREFIX@zng_deflateGetParams + +#define zlibng_version @ZLIB_SYMBOL_PREFIX@zlibng_version +#define zng_zError @ZLIB_SYMBOL_PREFIX@zng_zError +#define zng_inflateSyncPoint @ZLIB_SYMBOL_PREFIX@zng_inflateSyncPoint +#define zng_get_crc_table @ZLIB_SYMBOL_PREFIX@zng_get_crc_table +#define zng_inflateUndermine @ZLIB_SYMBOL_PREFIX@zng_inflateUndermine +#define zng_inflateValidate @ZLIB_SYMBOL_PREFIX@zng_inflateValidate +#define zng_inflateCodesUsed @ZLIB_SYMBOL_PREFIX@zng_inflateCodesUsed +#define zng_inflateResetKeep @ZLIB_SYMBOL_PREFIX@zng_inflateResetKeep +#define zng_deflateResetKeep @ZLIB_SYMBOL_PREFIX@zng_deflateResetKeep + +#define zng_gzopen_w @ZLIB_SYMBOL_PREFIX@zng_gzopen_w +#define zng_gzvprintf @ZLIB_SYMBOL_PREFIX@zng_gzvprintf + +#endif /* ZLIB_NAME_MANGLING_H */ diff --git a/zlib_name_mangling.h.empty b/zlib_name_mangling.h.empty new file mode 100644 index 0000000000..b24cb834a6 --- /dev/null +++ b/zlib_name_mangling.h.empty @@ -0,0 +1,8 @@ +/* zlib_name_mangling.h has been automatically generated from + * zlib_name_mangling.h.empty because ZLIB_SYMBOL_PREFIX was NOT set. + */ + +#ifndef ZLIB_NAME_MANGLING_H +#define ZLIB_NAME_MANGLING_H + +#endif /* ZLIB_NAME_MANGLING_H */ diff --git a/zlib_name_mangling.h.in b/zlib_name_mangling.h.in new file mode 100644 index 0000000000..07265f3c1a --- /dev/null +++ b/zlib_name_mangling.h.in @@ -0,0 +1,157 @@ +/* zlib_name_mangling.h has been automatically generated from + * zlib_name_mangling.h.in because ZLIB_SYMBOL_PREFIX was set. + */ + +#ifndef ZLIB_NAME_MANGLING_H +#define ZLIB_NAME_MANGLING_H + +/* all linked symbols and init macros */ +#define _dist_code @ZLIB_SYMBOL_PREFIX@_dist_code +#define _length_code @ZLIB_SYMBOL_PREFIX@_length_code +#define _tr_align @ZLIB_SYMBOL_PREFIX@_tr_align +#define _tr_flush_bits @ZLIB_SYMBOL_PREFIX@_tr_flush_bits +#define _tr_flush_block @ZLIB_SYMBOL_PREFIX@_tr_flush_block +#define _tr_init @ZLIB_SYMBOL_PREFIX@_tr_init +#define _tr_stored_block @ZLIB_SYMBOL_PREFIX@_tr_stored_block +#define _tr_tally @ZLIB_SYMBOL_PREFIX@_tr_tally +#define adler32 @ZLIB_SYMBOL_PREFIX@adler32 +#define adler32_combine @ZLIB_SYMBOL_PREFIX@adler32_combine +#define adler32_combine64 @ZLIB_SYMBOL_PREFIX@adler32_combine64 +#define adler32_z @ZLIB_SYMBOL_PREFIX@adler32_z +#ifndef Z_SOLO +# define compress @ZLIB_SYMBOL_PREFIX@compress +# define compress2 @ZLIB_SYMBOL_PREFIX@compress2 +# define compressBound @ZLIB_SYMBOL_PREFIX@compressBound +#endif +#define crc32 @ZLIB_SYMBOL_PREFIX@crc32 +#define crc32_combine @ZLIB_SYMBOL_PREFIX@crc32_combine +#define crc32_combine64 @ZLIB_SYMBOL_PREFIX@crc32_combine64 +#define crc32_z @ZLIB_SYMBOL_PREFIX@crc32_z +#define deflate @ZLIB_SYMBOL_PREFIX@deflate +#define deflateBound @ZLIB_SYMBOL_PREFIX@deflateBound +#define deflateCopy @ZLIB_SYMBOL_PREFIX@deflateCopy +#define deflateEnd @ZLIB_SYMBOL_PREFIX@deflateEnd +#define deflateGetDictionary @ZLIB_SYMBOL_PREFIX@deflateGetDictionary +#define deflateInit @ZLIB_SYMBOL_PREFIX@deflateInit +#define deflateInit2 @ZLIB_SYMBOL_PREFIX@deflateInit2 +#define deflateInit2_ @ZLIB_SYMBOL_PREFIX@deflateInit2_ +#define deflateInit_ @ZLIB_SYMBOL_PREFIX@deflateInit_ +#define deflateParams @ZLIB_SYMBOL_PREFIX@deflateParams +#define deflatePending @ZLIB_SYMBOL_PREFIX@deflatePending +#define deflatePrime @ZLIB_SYMBOL_PREFIX@deflatePrime +#define deflateReset @ZLIB_SYMBOL_PREFIX@deflateReset +#define deflateResetKeep @ZLIB_SYMBOL_PREFIX@deflateResetKeep +#define deflateSetDictionary @ZLIB_SYMBOL_PREFIX@deflateSetDictionary +#define deflateSetHeader @ZLIB_SYMBOL_PREFIX@deflateSetHeader +#define deflateTune @ZLIB_SYMBOL_PREFIX@deflateTune +#define deflate_copyright @ZLIB_SYMBOL_PREFIX@deflate_copyright +#define get_crc_table @ZLIB_SYMBOL_PREFIX@get_crc_table +#ifndef Z_SOLO +# define gz_error @ZLIB_SYMBOL_PREFIX@gz_error +# define gz_intmax @ZLIB_SYMBOL_PREFIX@gz_intmax +# define gz_strwinerror @ZLIB_SYMBOL_PREFIX@gz_strwinerror +# define gzbuffer @ZLIB_SYMBOL_PREFIX@gzbuffer +# define gzclearerr @ZLIB_SYMBOL_PREFIX@gzclearerr +# define gzclose @ZLIB_SYMBOL_PREFIX@gzclose +# define gzclose_r @ZLIB_SYMBOL_PREFIX@gzclose_r +# define gzclose_w @ZLIB_SYMBOL_PREFIX@gzclose_w +# define gzdirect @ZLIB_SYMBOL_PREFIX@gzdirect +# define gzdopen @ZLIB_SYMBOL_PREFIX@gzdopen +# define gzeof @ZLIB_SYMBOL_PREFIX@gzeof +# define gzerror @ZLIB_SYMBOL_PREFIX@gzerror +# define gzflush @ZLIB_SYMBOL_PREFIX@gzflush +# define gzfread @ZLIB_SYMBOL_PREFIX@gzfread +# define gzfwrite @ZLIB_SYMBOL_PREFIX@gzfwrite +# define gzgetc @ZLIB_SYMBOL_PREFIX@gzgetc +# define gzgetc_ @ZLIB_SYMBOL_PREFIX@gzgetc_ +# define gzgets @ZLIB_SYMBOL_PREFIX@gzgets +# define gzoffset @ZLIB_SYMBOL_PREFIX@gzoffset +# define gzoffset64 @ZLIB_SYMBOL_PREFIX@gzoffset64 +# define gzopen @ZLIB_SYMBOL_PREFIX@gzopen +# define gzopen64 @ZLIB_SYMBOL_PREFIX@gzopen64 +# ifdef _WIN32 +# define gzopen_w @ZLIB_SYMBOL_PREFIX@gzopen_w +# endif +# define gzprintf @ZLIB_SYMBOL_PREFIX@gzprintf +# define gzputc @ZLIB_SYMBOL_PREFIX@gzputc +# define gzputs @ZLIB_SYMBOL_PREFIX@gzputs +# define gzread @ZLIB_SYMBOL_PREFIX@gzread +# define gzrewind @ZLIB_SYMBOL_PREFIX@gzrewind +# define gzseek @ZLIB_SYMBOL_PREFIX@gzseek +# define gzseek64 @ZLIB_SYMBOL_PREFIX@gzseek64 +# define gzsetparams @ZLIB_SYMBOL_PREFIX@gzsetparams +# define gztell @ZLIB_SYMBOL_PREFIX@gztell +# define gztell64 @ZLIB_SYMBOL_PREFIX@gztell64 +# define gzungetc @ZLIB_SYMBOL_PREFIX@gzungetc +# define gzvprintf @ZLIB_SYMBOL_PREFIX@gzvprintf +# define gzwrite @ZLIB_SYMBOL_PREFIX@gzwrite +#endif +#define inflate @ZLIB_SYMBOL_PREFIX@inflate +#define inflateBack @ZLIB_SYMBOL_PREFIX@inflateBack +#define inflateBackEnd @ZLIB_SYMBOL_PREFIX@inflateBackEnd +#define inflateBackInit @ZLIB_SYMBOL_PREFIX@inflateBackInit +#define inflateBackInit_ @ZLIB_SYMBOL_PREFIX@inflateBackInit_ +#define inflateCodesUsed @ZLIB_SYMBOL_PREFIX@inflateCodesUsed +#define inflateCopy @ZLIB_SYMBOL_PREFIX@inflateCopy +#define inflateEnd @ZLIB_SYMBOL_PREFIX@inflateEnd +#define inflateGetDictionary @ZLIB_SYMBOL_PREFIX@inflateGetDictionary +#define inflateGetHeader @ZLIB_SYMBOL_PREFIX@inflateGetHeader +#define inflateInit @ZLIB_SYMBOL_PREFIX@inflateInit +#define inflateInit2 @ZLIB_SYMBOL_PREFIX@inflateInit2 +#define inflateInit2_ @ZLIB_SYMBOL_PREFIX@inflateInit2_ +#define inflateInit_ @ZLIB_SYMBOL_PREFIX@inflateInit_ +#define inflateMark @ZLIB_SYMBOL_PREFIX@inflateMark +#define inflatePrime @ZLIB_SYMBOL_PREFIX@inflatePrime +#define inflateReset @ZLIB_SYMBOL_PREFIX@inflateReset +#define inflateReset2 @ZLIB_SYMBOL_PREFIX@inflateReset2 +#define inflateResetKeep @ZLIB_SYMBOL_PREFIX@inflateResetKeep +#define inflateSetDictionary @ZLIB_SYMBOL_PREFIX@inflateSetDictionary +#define inflateSync @ZLIB_SYMBOL_PREFIX@inflateSync +#define inflateSyncPoint @ZLIB_SYMBOL_PREFIX@inflateSyncPoint +#define inflateUndermine @ZLIB_SYMBOL_PREFIX@inflateUndermine +#define inflateValidate @ZLIB_SYMBOL_PREFIX@inflateValidate +#define inflate_copyright @ZLIB_SYMBOL_PREFIX@inflate_copyright +#define inflate_fast @ZLIB_SYMBOL_PREFIX@inflate_fast +#define inflate_table @ZLIB_SYMBOL_PREFIX@inflate_table +#ifndef Z_SOLO +# define uncompress @ZLIB_SYMBOL_PREFIX@uncompress +# define uncompress2 @ZLIB_SYMBOL_PREFIX@uncompress2 +#endif +#define zError @ZLIB_SYMBOL_PREFIX@zError +#ifndef Z_SOLO +# define zcalloc @ZLIB_SYMBOL_PREFIX@zcalloc +# define zcfree @ZLIB_SYMBOL_PREFIX@zcfree +#endif +#define zlibCompileFlags @ZLIB_SYMBOL_PREFIX@zlibCompileFlags +#define zlibVersion @ZLIB_SYMBOL_PREFIX@zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +#define Byte @ZLIB_SYMBOL_PREFIX@Byte +#define Bytef @ZLIB_SYMBOL_PREFIX@Bytef +#define alloc_func @ZLIB_SYMBOL_PREFIX@alloc_func +#define charf @ZLIB_SYMBOL_PREFIX@charf +#define free_func @ZLIB_SYMBOL_PREFIX@free_func +#ifndef Z_SOLO +# define gzFile @ZLIB_SYMBOL_PREFIX@gzFile +#endif +#define gz_header @ZLIB_SYMBOL_PREFIX@gz_header +#define gz_headerp @ZLIB_SYMBOL_PREFIX@gz_headerp +#define in_func @ZLIB_SYMBOL_PREFIX@in_func +#define intf @ZLIB_SYMBOL_PREFIX@intf +#define out_func @ZLIB_SYMBOL_PREFIX@out_func +#define uInt @ZLIB_SYMBOL_PREFIX@uInt +#define uIntf @ZLIB_SYMBOL_PREFIX@uIntf +#define uLong @ZLIB_SYMBOL_PREFIX@uLong +#define uLongf @ZLIB_SYMBOL_PREFIX@uLongf +#define voidp @ZLIB_SYMBOL_PREFIX@voidp +#define voidpc @ZLIB_SYMBOL_PREFIX@voidpc +#define voidpf @ZLIB_SYMBOL_PREFIX@voidpf + +/* all zlib structs in zlib.h and zconf.h */ +#define gz_header_s @ZLIB_SYMBOL_PREFIX@gz_header_s +#define internal_state @ZLIB_SYMBOL_PREFIX@internal_state + +/* all zlib structs in zutil.h */ +#define z_errmsg @ZLIB_SYMBOL_PREFIX@z_errmsg + +#endif /* ZLIB_NAME_MANGLING_H */ From b418e9c85ba06ff3bf8bc23f0704be2f308f732b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Wed, 22 Sep 2021 17:08:06 -0400 Subject: [PATCH 141/798] Exercise the new symbol prefix option in CI tests --- .github/workflows/cmake.yml | 12 ++++++++++++ .github/workflows/configure.yml | 10 ++++++++++ .github/workflows/nmake.yml | 24 +++++++++++++++++++++--- .github/workflows/pigz.yml | 6 ++++++ .github/workflows/pkgcheck.yml | 6 ++++++ 5 files changed, 55 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index aac24c7b2b..267e845341 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -18,6 +18,18 @@ jobs: cmake-args: -DWITH_SANITIZER=Address codecov: ubuntu_gcc + - name: Ubuntu GCC Symbol Prefix + os: ubuntu-latest + compiler: gcc + cmake-args: -DZLIB_SYMBOL_PREFIX=zTest_ + codecov: ubuntu_gcc_sprefix + + - name: Ubuntu GCC Compat SPrefix + os: ubuntu-latest + compiler: gcc + cmake-args: -DZLIB_COMPAT=ON -DZLIB_SYMBOL_PREFIX=zTest_ + codecov: ubuntu_gcc_compat_sprefix + - name: Ubuntu GCC OSB -O1 No Unaligned64 os: ubuntu-latest compiler: gcc diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 3892932b8c..cb404f537f 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -186,6 +186,16 @@ jobs: cflags: -static ldflags: -static + - name: macOS GCC symbol prefix + os: macOS-latest + compiler: gcc + configure-args: --sprefix=zTest_ + + - name: macOS GCC symbol prefix & compat + os: macOS-latest + compiler: gcc + configure-args: --zlib-compat --sprefix=zTest_ + - name: macOS GCC os: macOS-latest compiler: gcc diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index 38c0b42ebf..da6d99d202 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -13,6 +13,24 @@ jobs: makefile: win32/Makefile.msc vc-vars: x86 + - name: Windows NMake x64 compat + os: windows-latest + makefile: win32/Makefile.msc + vc-vars: x86_amd64 + additional-args: ZLIB_COMPAT=yes + + - name: Windows NMake x64 sprefix + os: windows-latest + makefile: win32/Makefile.msc + vc-vars: x86_amd64 + additional-args: SYMBOL_PREFIX=zTest_ + + - name: Windows NMake x64 sprefix compat + os: windows-latest + makefile: win32/Makefile.msc + vc-vars: x86_amd64 + additional-args: ZLIB_COMPAT=yes SYMBOL_PREFIX=zTest_ + - name: Windows NMake x64 os: windows-latest makefile: win32/Makefile.msc @@ -36,7 +54,7 @@ jobs: shell: cmd run: | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} - nmake -f ${{ matrix.makefile }} + nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} - name: Run test cases shell: cmd @@ -44,5 +62,5 @@ jobs: if: contains(matrix.vc-vars, 'arm') == false run: | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} - nmake -f ${{ matrix.makefile }} test - nmake -f ${{ matrix.makefile }} testdll + nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} test + nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} testdll diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 8260c82fb7..bce94fa4ea 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -13,6 +13,12 @@ jobs: compiler: gcc codecov: ubuntu_gcc_pigz + - name: Ubuntu GCC Symbol Prefix + os: ubuntu-latest + compiler: gcc + codecov: ubuntu_gcc_pigz + cmake-args: -DZLIB_SYMBOL_PREFIX=zTest_ + - name: Ubuntu Clang os: ubuntu-latest compiler: clang diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index c74e41aec9..780c6e86f9 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -58,6 +58,12 @@ jobs: cmake-args: -DWITH_NATIVE_INSTRUCTIONS=ON configure-args: --native + - name: macOS Clang Symbol Prefix + os: macOS-latest + compiler: clang + cmake-args: -DZLIB_SYMBOL_PREFIX=zTest_ + configure-args: --sprefix=zTest_ + steps: - name: Checkout repository uses: actions/checkout@v1 From 8ba6642b9867cb5208f519011f10b79a61e44fa2 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 11 Oct 2021 13:12:42 +0200 Subject: [PATCH 142/798] IBM Z: Fix building outside of a source directory Do not use relative includes, since they are valid only within the source directory. Rely on the build system to pass the necessary include flags instead. --- arch/s390/crc32-vx.c | 4 ++-- arch/s390/dfltcc_common.c | 2 +- arch/s390/dfltcc_common.h | 6 +++--- arch/s390/dfltcc_deflate.c | 8 ++++---- arch/s390/dfltcc_inflate.c | 8 ++++---- arch/s390/s390.c | 2 +- arch/s390/s390.h | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index bb23289cd1..18b8bb2235 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -12,8 +12,8 @@ * relicensed under the zlib license. */ -#include "../../zutil.h" -#include "../../crc32_p.h" +#include "zutil.h" +#include "crc32_p.h" #include diff --git a/arch/s390/dfltcc_common.c b/arch/s390/dfltcc_common.c index c82c3b220c..f1ae904ad5 100644 --- a/arch/s390/dfltcc_common.c +++ b/arch/s390/dfltcc_common.c @@ -1,6 +1,6 @@ /* dfltcc_deflate.c - IBM Z DEFLATE CONVERSION CALL general support. */ -#include "../../zbuild.h" +#include "zbuild.h" #include "dfltcc_common.h" #include "dfltcc_detail.h" diff --git a/arch/s390/dfltcc_common.h b/arch/s390/dfltcc_common.h index 5c3be91b97..f46f9cafb2 100644 --- a/arch/s390/dfltcc_common.h +++ b/arch/s390/dfltcc_common.h @@ -2,11 +2,11 @@ #define DFLTCC_COMMON_H #ifdef ZLIB_COMPAT -#include "../../zlib.h" +#include "zlib.h" #else -#include "../../zlib-ng.h" +#include "zlib-ng.h" #endif -#include "../../zutil.h" +#include "zutil.h" void Z_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size); void Z_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size); diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index 1878656676..e3b53ee131 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -13,10 +13,10 @@ $ make */ -#include "../../zbuild.h" -#include "../../zutil.h" -#include "../../deflate.h" -#include "../../trees_emit.h" +#include "zbuild.h" +#include "zutil.h" +#include "deflate.h" +#include "trees_emit.h" #include "dfltcc_deflate.h" #include "dfltcc_detail.h" diff --git a/arch/s390/dfltcc_inflate.c b/arch/s390/dfltcc_inflate.c index f6a7e8f865..253506466d 100644 --- a/arch/s390/dfltcc_inflate.c +++ b/arch/s390/dfltcc_inflate.c @@ -13,10 +13,10 @@ $ make */ -#include "../../zbuild.h" -#include "../../zutil.h" -#include "../../inftrees.h" -#include "../../inflate.h" +#include "zbuild.h" +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" #include "dfltcc_inflate.h" #include "dfltcc_detail.h" diff --git a/arch/s390/s390.c b/arch/s390/s390.c index 6dd5252ce3..a67bfc249a 100644 --- a/arch/s390/s390.c +++ b/arch/s390/s390.c @@ -1,4 +1,4 @@ -#include "../../zutil.h" +#include "zutil.h" #include "s390.h" #include diff --git a/arch/s390/s390.h b/arch/s390/s390.h index dec035b3d9..453c58137c 100644 --- a/arch/s390/s390.h +++ b/arch/s390/s390.h @@ -1,7 +1,7 @@ #ifndef S390_H_ #define S390_H_ -#include "../../zutil.h" +#include "zutil.h" extern int s390_cpu_has_vx; From 8ffb6aef94443a135ad3b0da547dcc96d3bb4421 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 11 Oct 2021 12:36:28 +0200 Subject: [PATCH 143/798] Link crc32_test and infcover with $(CFLAGS) This fixes link failures when using CFLAGS=-m31 on IBM Z. All the other tests are already linked this way. --- Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.in b/Makefile.in index 8e855e456d..928805fc58 100644 --- a/Makefile.in +++ b/Makefile.in @@ -231,7 +231,7 @@ infcover.o: $(SRCDIR)/test/infcover.c zlib$(SUFFIX).h zconf$(SUFFIX).h zlib_name $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c infcover$(EXE): infcover.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ infcover.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ infcover.o $(STATICLIB) ifneq ($(STRIP),) $(STRIP) $@ endif @@ -315,7 +315,7 @@ ifneq ($(STRIP),) endif crc32_test$(EXE): crc32_test.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ crc32_test.o $(TEST_LIBS) $(LDSHAREDLIBC) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ crc32_test.o $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif From 4b4b8a7777b0bd7a18184cd3969683e40a395069 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 11 Oct 2021 13:47:20 +0200 Subject: [PATCH 144/798] IBM Z: Do not check inflateGetDictionary() with DFLTCC The zlib manual does not specify a strict contract for inflateGetDictionary(), it merely says that it "Returns the sliding dictionary being maintained by inflate", which is an implementation detail. IBM Z inflate's behavior differs from that of software, and may change in the future to boot. --- test/example.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/example.c b/test/example.c index 53abb5ee93..2a03328432 100644 --- a/test/example.c +++ b/test/example.c @@ -29,6 +29,9 @@ static const char hello[] = "hello, hello!"; static const char dictionary[] = "hello"; static unsigned long dictId = 0; /* Adler32 value of the dictionary */ +/* Maximum dictionary size, according to inflateGetDictionary() description. */ +#define MAX_DICTIONARY_SIZE 32768 + void test_compress (unsigned char *compr, z_size_t comprLen,unsigned char *uncompr, z_size_t uncomprLen); void test_gzio (const char *fname, unsigned char *uncompr, z_size_t uncomprLen); @@ -514,7 +517,7 @@ void test_dict_deflate(unsigned char *compr, size_t comprLen) { */ void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) { int err; - uint8_t check_dictionary[10]; + uint8_t check_dictionary[MAX_DICTIONARY_SIZE]; uint32_t check_dictionary_len = 0; PREFIX3(stream) d_stream; /* decompression stream */ @@ -547,13 +550,17 @@ void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *unc err = PREFIX(inflateGetDictionary)(&d_stream, NULL, &check_dictionary_len); CHECK_ERR(err, "inflateGetDictionary"); +#ifndef S390_DFLTCC_INFLATE if (check_dictionary_len != sizeof(dictionary)) error("bad dictionary length\n"); +#endif err = PREFIX(inflateGetDictionary)(&d_stream, check_dictionary, &check_dictionary_len); CHECK_ERR(err, "inflateGetDictionary"); +#ifndef S390_DFLTCC_INFLATE if (memcmp(dictionary, check_dictionary, sizeof(dictionary)) != 0) error("bad dictionary\n"); +#endif err = PREFIX(inflateEnd)(&d_stream); CHECK_ERR(err, "inflateEnd"); From 33aacca93b6aeabe44325ece1a315710329e37e6 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 11 Oct 2021 13:22:13 +0200 Subject: [PATCH 145/798] IBM Z: Sync crc_fold with DFLTCC Intermediate CRC32 value was moved from strm->adler to state->crc_fold. --- arch/s390/dfltcc_deflate.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index e3b53ee131..0a65aa7e8e 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -210,7 +210,7 @@ int Z_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *res *strm->next_out = (unsigned char)state->bi_buf; /* Honor history and check value */ param->nt = 0; - param->cv = state->wrap == 2 ? ZSWAP32(strm->adler) : strm->adler; + param->cv = state->wrap == 2 ? ZSWAP32(state->crc_fold.value) : strm->adler; /* When opening a block, choose a Huffman-Table Type */ if (!param->bcf) { @@ -241,7 +241,10 @@ int Z_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *res state->bi_buf = 0; /* Avoid accessing next_out */ else state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1); - strm->adler = state->wrap == 2 ? ZSWAP32(param->cv) : param->cv; + if (state->wrap == 2) + state->crc_fold.value = ZSWAP32(param->cv); + else + strm->adler = param->cv; /* Unmask the input data */ strm->avail_in += masked_avail_in; From 63e0002cba437eda71f263d306bcd6dbb5fe90a6 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 11 Oct 2021 12:24:20 +0200 Subject: [PATCH 146/798] IBM Z: Adjust compressBound() for DFLTCC When DFLTCC was introduced, deflateBound() was adjusted, but compressBound() was not, leading to compression failures when using compressBound() + compress() with poorly compressible data. --- arch/s390/dfltcc_common.h | 24 ++++++++++++++++++++++++ arch/s390/dfltcc_deflate.h | 3 +-- compress.c | 19 ++++++++++++++++++- zutil.h | 2 ++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/arch/s390/dfltcc_common.h b/arch/s390/dfltcc_common.h index f46f9cafb2..6de8bb18f6 100644 --- a/arch/s390/dfltcc_common.h +++ b/arch/s390/dfltcc_common.h @@ -26,4 +26,28 @@ void Z_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w); #define TRY_FREE_WINDOW dfltcc_free_window +#define DFLTCC_BLOCK_HEADER_BITS 3 +#define DFLTCC_HLITS_COUNT_BITS 5 +#define DFLTCC_HDISTS_COUNT_BITS 5 +#define DFLTCC_HCLENS_COUNT_BITS 4 +#define DFLTCC_MAX_HCLENS 19 +#define DFLTCC_HCLEN_BITS 3 +#define DFLTCC_MAX_HLITS 286 +#define DFLTCC_MAX_HDISTS 30 +#define DFLTCC_MAX_HLIT_HDIST_BITS 7 +#define DFLTCC_MAX_SYMBOL_BITS 16 +#define DFLTCC_MAX_EOBS_BITS 15 +#define DFLTCC_MAX_PADDING_BITS 7 + +#define DEFLATE_BOUND_COMPLEN(source_len) \ + ((DFLTCC_BLOCK_HEADER_BITS + \ + DFLTCC_HLITS_COUNT_BITS + \ + DFLTCC_HDISTS_COUNT_BITS + \ + DFLTCC_HCLENS_COUNT_BITS + \ + DFLTCC_MAX_HCLENS * DFLTCC_HCLEN_BITS + \ + (DFLTCC_MAX_HLITS + DFLTCC_MAX_HDISTS) * DFLTCC_MAX_HLIT_HDIST_BITS + \ + (source_len) * DFLTCC_MAX_SYMBOL_BITS + \ + DFLTCC_MAX_EOBS_BITS + \ + DFLTCC_MAX_PADDING_BITS) >> 3) + #endif diff --git a/arch/s390/dfltcc_deflate.h b/arch/s390/dfltcc_deflate.h index 7e32380bd8..218e594693 100644 --- a/arch/s390/dfltcc_deflate.h +++ b/arch/s390/dfltcc_deflate.h @@ -41,8 +41,7 @@ int Z_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned cha #define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \ do { \ if (dfltcc_can_deflate((strm))) \ - (complen) = (3 + 5 + 5 + 4 + 19 * 3 + (286 + 30) * 7 + \ - (source_len) * 16 + 15 + 7) >> 3; \ + (complen) = DEFLATE_BOUND_COMPLEN(source_len); \ } while (0) #define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) (dfltcc_can_deflate((strm))) diff --git a/compress.c b/compress.c index d5379591d1..de45e29e6a 100644 --- a/compress.c +++ b/compress.c @@ -3,14 +3,25 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#define ZLIB_INTERNAL #include "zbuild.h" +#include "zutil.h" #if defined(ZLIB_COMPAT) # include "zlib.h" #else # include "zlib-ng.h" #endif +/* =========================================================================== + * Architecture-specific hooks. + */ +#ifdef S390_DFLTCC_DEFLATE +# include "arch/s390/dfltcc_common.h" +#else +/* Returns the upper bound on compressed data length based on uncompressed data length, assuming default settings. + * Zero means that arch-specific deflation code behaves identically to the regular zlib-ng algorithms. */ +# define DEFLATE_BOUND_COMPLEN(source_len) 0 +#endif + /* =========================================================================== Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte @@ -73,6 +84,12 @@ int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsi this function needs to be updated. */ z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) { + z_size_t complen = DEFLATE_BOUND_COMPLEN(sourceLen); + + if (complen > 0) + /* Architecture-specific code provided an upper bound. */ + return complen + ZLIB_WRAPLEN; + #ifndef NO_QUICK_STRATEGY /* Quick deflate strategy worse case is 9 bits per literal, rounded to nearest byte, plus the size of block & gzip headers and footers */ diff --git a/zutil.h b/zutil.h index 0a44f775c3..e7cb9ad3e4 100644 --- a/zutil.h +++ b/zutil.h @@ -78,6 +78,8 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ #define ADLER32_INITIAL_VALUE 1 /* initial adler-32 hash value */ #define CRC32_INITIAL_VALUE 0 /* initial crc-32 hash value */ +#define ZLIB_WRAPLEN 6 /* zlib format overhead */ + /* target dependencies */ #ifdef AMIGA From 9c4aec63f0df63bb9f340cf3f67cc5462791c3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Mon, 6 Sep 2021 14:26:56 -0400 Subject: [PATCH 147/798] Make integration into bigger projects easier --- CMakeLists.txt | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 342a9b8c91..0ef7258a64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -956,7 +956,8 @@ endif() foreach(ZLIB_INSTALL_LIBRARY ${ZLIB_INSTALL_LIBRARIES}) target_include_directories(${ZLIB_INSTALL_LIBRARY} PUBLIC - ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + "$" + "$") endforeach() if(WIN32) @@ -1090,7 +1091,9 @@ option(ZLIB_ENABLE_TESTS "Build test binaries" ON) if(ZLIB_ENABLE_TESTS) enable_testing() macro(configure_test_executable target) - target_include_directories(${target} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(${target} PUBLIC + "$" + "$") if(NOT WITH_GZFILEOP) target_compile_definitions(${target} PUBLIC -DWITH_GZFILEOP) target_sources(${target} PRIVATE ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) @@ -1149,7 +1152,9 @@ if(ZLIB_ENABLE_TESTS) target_sources(infcover PRIVATE inftrees.c) add_executable(makefixed tools/makefixed.c inftrees.c) - target_include_directories(makefixed PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(makefixed PUBLIC + "$" + "$") set(MAKEFIXED_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) add_test(NAME makefixed @@ -1161,7 +1166,9 @@ if(ZLIB_ENABLE_TESTS) -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) add_executable(maketrees tools/maketrees.c trees.c zutil.c) - target_include_directories(maketrees PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(maketrees PUBLIC + "$" + "$") set(MAKETREES_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) add_test(NAME maketrees @@ -1173,7 +1180,9 @@ if(ZLIB_ENABLE_TESTS) -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) add_executable(makecrct tools/makecrct.c) - target_include_directories(makecrct PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) + target_include_directories(makecrct PUBLIC + "$" + "$") set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) add_test(NAME makecrct-crc32 From 5d37363b97c6dd3098e1c0b39d2900b0e4c5545a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Sun, 10 Oct 2021 10:51:09 -0400 Subject: [PATCH 148/798] COMP: Fix data loss warning Fix data loss warning. Fixes: ``` itkzlib-ng/inflate.c(1209,24): warning C4267: '=': conversion from 'size_t' to 'unsigned long', possible loss of data itkzlib-ng/inflate.c(1210,26): warning C4267: '=': conversion from 'size_t' to 'unsigned long', possible loss of data ``` --- inflate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inflate.c b/inflate.c index 45c90232ad..f87d6c94d5 100644 --- a/inflate.c +++ b/inflate.c @@ -1206,8 +1206,8 @@ int32_t Z_EXPORT PREFIX(inflateSync)(PREFIX3(stream) *strm) { in = strm->total_in; out = strm->total_out; PREFIX(inflateReset)(strm); - strm->total_in = in; - strm->total_out = out; + strm->total_in = (z_size_t)in; + strm->total_out = (z_size_t)out; state->flags = flags; state->mode = TYPE; return Z_OK; From a7b773697b34c19f246defc1ffb760b0d39be391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Mon, 6 Sep 2021 14:38:09 -0400 Subject: [PATCH 149/798] Fix minor formatting issues From ITK PR: https://github.com/InsightSoftwareConsortium/ITK/pull/2803 CI check: https://github.com/InsightSoftwareConsortium/ITK/runs/3864083025 commit 5434d42 adds bad whitespace: README.md:223: new blank line at EOF. commit 5434d42 is not allowed; missing newline at the end of file in .gitattributes. --- .gitattributes | 2 +- README.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index 0414401042..3b35744b02 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,4 +3,4 @@ *.h text Makefile text configure text eol=lf -testCVEinputs.sh text eol=lf \ No newline at end of file +testCVEinputs.sh text eol=lf diff --git a/README.md b/README.md index d7a6689b61..541ffb94fc 100644 --- a/README.md +++ b/README.md @@ -220,4 +220,3 @@ Related Projects * Python tool to benchmark minigzip/minideflate https://github.com/zlib-ng/deflatebench * Python tool to benchmark pigz https://github.com/zlib-ng/pigzbench * 3rd party patches for zlib-ng compatibility https://github.com/zlib-ng/patches - From 071e4da02377b05f5f4a5a1db9f07ea3507a5d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Wed, 13 Oct 2021 09:58:41 -0400 Subject: [PATCH 150/798] ENH: Transition to Ubuntu 18.04 in `GitHub` actions workflows Transition to Ubuntu 18.04 in `GitHub` actions workflows. Fixes: ``` Ubuntu 16.04 Clang This request was automatically failed because there were no enabled runners online to process the request for more than 1 days. Ubuntu 16.04 GCC This request was automatically failed because there were no enabled runners online to process the request for more than 1 days. ``` reported for example at: https://github.com/zlib-ng/zlib-ng/actions/runs/1326434358 Official `GitHub` notice related to the removal of the 16.04 virtual environments: https://github.blog/changelog/2021-04-29-github-actions-ubuntu-16-04-lts-virtual-environment-will-be-removed-on-september-20-2021/ --- .github/workflows/cmake.yml | 8 ++++---- .github/workflows/configure.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 267e845341..256a9eca49 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -8,8 +8,8 @@ jobs: fail-fast: false matrix: include: - - name: Ubuntu 16.04 GCC - os: ubuntu-16.04 + - name: Ubuntu 18.04 GCC + os: ubuntu-18.04 compiler: gcc - name: Ubuntu GCC @@ -290,8 +290,8 @@ jobs: # Limit parallel test jobs to prevent wine errors parallels-jobs: 1 - - name: Ubuntu 16.04 Clang - os: ubuntu-16.04 + - name: Ubuntu 18.04 Clang + os: ubuntu-18.04 compiler: clang-6.0 packages: clang-6.0 diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index cb404f537f..4e64a8789e 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -13,8 +13,8 @@ jobs: compiler: gcc configure-args: --warn - - name: Ubuntu 16.04 GCC - os: ubuntu-16.04 + - name: Ubuntu 18.04 GCC + os: ubuntu-18.04 compiler: gcc configure-args: --warn From c762db1366541fe56ec95d64dad49947b27dfcf3 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Thu, 5 Aug 2021 00:27:31 +0200 Subject: [PATCH 151/798] IBM Z: Run DFLTCC tests on the self-hosted builder * Use the self-hosted builder instead of ubuntu-latest. * Drop qemu-related settings from DFLTCC configurations. * Install codecov only for the current user, since the self-hosted builder runs under a restricted non-root account. * Use actions/checkout@v2 for configure checks, since for some reason actions/checkout@v1 cannot find git on the self-hosted builder. * Update the testing section of the DFLTCC README. * Add the infrastructure code for the self-hosted builder. --- .github/workflows/cmake.yml | 20 ++---- .github/workflows/configure.yml | 20 ++---- arch/s390/README.md | 71 ++++++++++++++++++- .../actions-runner.Dockerfile | 40 +++++++++++ .../actions-runner.service | 23 ++++++ .../fs/usr/bin/actions-runner | 40 +++++++++++ .../self-hosted-builder/fs/usr/bin/entrypoint | 30 ++++++++ .../qemu-user-static.service | 11 +++ 8 files changed, 225 insertions(+), 30 deletions(-) create mode 100644 arch/s390/self-hosted-builder/actions-runner.Dockerfile create mode 100644 arch/s390/self-hosted-builder/actions-runner.service create mode 100755 arch/s390/self-hosted-builder/fs/usr/bin/actions-runner create mode 100755 arch/s390/self-hosted-builder/fs/usr/bin/entrypoint create mode 100644 arch/s390/self-hosted-builder/qemu-user-static.service diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 256a9eca49..97078fa575 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -253,23 +253,17 @@ jobs: codecov: ubuntu_gcc_s390x - name: Ubuntu GCC S390X DFLTCC - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Address + os: z15 + compiler: gcc + cmake-args: -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross - qemu-run: qemu-s390x - ldflags: -static codecov: ubuntu_gcc_s390x - name: Ubuntu GCC S390X DFLTCC Compat - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined + os: z15 + compiler: gcc + cmake-args: -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross - qemu-run: qemu-s390x - ldflags: -static codecov: ubuntu_gcc_s390x - name: Ubuntu MinGW i686 @@ -432,7 +426,7 @@ jobs: - name: Install codecov.io tools if: matrix.codecov run: | - python -u -m pip install codecov + python -u -m pip install --user codecov - name: Initialize Wine # Prevent parallel test jobs from initializing Wine at the same time diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 4e64a8789e..6458673a1e 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -167,24 +167,14 @@ jobs: ldflags: -static - name: Ubuntu GCC S390X DFLTCC - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc + os: z15 + compiler: gcc configure-args: --warn --static --with-dfltcc-deflate --with-dfltcc-inflate - chost: s390x-linux-gnu - packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross - qemu-run: qemu-s390x - cflags: -static - ldflags: -static - name: Ubuntu GCC S390X DFLTCC Compat - os: ubuntu-latest - compiler: s390x-linux-gnu-gcc + os: z15 + compiler: gcc configure-args: --warn --zlib-compat --static --with-dfltcc-deflate --with-dfltcc-inflate - chost: s390x-linux-gnu - packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross - qemu-run: qemu-s390x - cflags: -static - ldflags: -static - name: macOS GCC symbol prefix os: macOS-latest @@ -203,7 +193,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages diff --git a/arch/s390/README.md b/arch/s390/README.md index 9425de3901..90066f0f96 100644 --- a/arch/s390/README.md +++ b/arch/s390/README.md @@ -212,5 +212,72 @@ access to an IBM z15+ VM or LPAR in order to test DFLTCC support. Since DFLTCC is a non-privileged instruction, neither special VM/LPAR configuration nor root are required. -Still, zlib-ng CI has a few QEMU TCG-based configurations that check -whether fallback to software is working. +zlib-ng CI uses an IBM-provided z15 self-hosted builder for the DFLTCC +testing. There are no IBM Z builds of GitHub Actions runner, and +stable qemu-user has problems with .NET apps, so the builder runs the +x86_64 runner version with qemu-user built from the master branch. + +## Configuring the builder. + +### Install prerequisites. + +``` +$ sudo dnf install docker +``` + +### Add services. + +``` +$ sudo cp self-hosted-builder/*.service /etc/systemd/system/ +$ sudo systemctl daemon-reload +``` + +### Create a config file. + +``` +$ sudo tee /etc/actions-runner +repo=/ +access_token= +``` + +Access token should have the repo scope, consult +https://docs.github.com/en/rest/reference/actions#create-a-registration-token-for-a-repository +for details. + +### Autostart the x86_64 emulation support. + +``` +$ sudo systemctl enable --now qemu-user-static +``` + +### Autostart the runner. + +``` +$ sudo systemctl enable --now actions-runner +``` + +## Rebuilding the image + +In order to update the `iiilinuxibmcom/actions-runner` image, e.g. to get the +latest OS security fixes, use the following commands: + +``` +$ sudo docker build \ + --pull \ + -f self-hosted-builder/actions-runner.Dockerfile \ + -t iiilinuxibmcom/actions-runner +$ sudo systemctl restart actions-runner +``` + +## Removing persistent data + +The `actions-runner` service stores various temporary data, such as runner +registration information, work directories and logs, in the `actions-runner` +volume. In order to remove it and start from scratch, e.g. when switching the +runner to a different repository, use the following commands: + +``` +$ sudo systemctl stop actions-runner +$ sudo docker rm -f actions-runner +$ sudo docker volume rm actions-runner +``` diff --git a/arch/s390/self-hosted-builder/actions-runner.Dockerfile b/arch/s390/self-hosted-builder/actions-runner.Dockerfile new file mode 100644 index 0000000000..a4bb774ab0 --- /dev/null +++ b/arch/s390/self-hosted-builder/actions-runner.Dockerfile @@ -0,0 +1,40 @@ +# Self-Hosted IBM Z Github Actions Runner. + +# Temporary image: amd64 dependencies. +FROM amd64/ubuntu:20.04 as ld-prefix +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get -y install ca-certificates libicu66 libssl1.1 + +# Main image. +FROM s390x/ubuntu:20.04 + +# Packages for zlib-ng testing. +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get -y install \ + cmake \ + curl \ + gcc \ + git \ + jq \ + ninja-build \ + python-is-python3 \ + python3 \ + python3-pip + +# amd64 dependencies. +COPY --from=ld-prefix / /usr/x86_64-linux-gnu/ +RUN ln -fs ../lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /usr/x86_64-linux-gnu/lib64/ +RUN ln -fs /etc/resolv.conf /usr/x86_64-linux-gnu/etc/ +ENV QEMU_LD_PREFIX=/usr/x86_64-linux-gnu + +# amd64 Github Actions Runner. +RUN useradd -m actions-runner +USER actions-runner +WORKDIR /home/actions-runner +RUN curl -L https://github.com/actions/runner/releases/download/v2.283.2/actions-runner-linux-x64-2.283.2.tar.gz | tar -xz +VOLUME /home/actions-runner + +# Scripts. +COPY fs/ / +ENTRYPOINT ["/usr/bin/entrypoint"] +CMD ["/usr/bin/actions-runner"] diff --git a/arch/s390/self-hosted-builder/actions-runner.service b/arch/s390/self-hosted-builder/actions-runner.service new file mode 100644 index 0000000000..1d3129ff50 --- /dev/null +++ b/arch/s390/self-hosted-builder/actions-runner.service @@ -0,0 +1,23 @@ +[Unit] +Description=Self-Hosted IBM Z Github Actions Runner +Wants=qemu-user-static +After=qemu-user-static +StartLimitIntervalSec=0 + +[Service] +Type=simple +Restart=always +ExecStart=/usr/bin/docker run \ + --env-file=/etc/actions-runner \ + --init \ + --interactive \ + --name=actions-runner \ + --rm \ + --volume=actions-runner:/home/actions-runner \ + iiilinuxibmcom/actions-runner +ExecStop=/bin/sh -c "docker exec actions-runner kill -INT -- -1" +ExecStop=/bin/sh -c "docker wait actions-runner" +ExecStop=/bin/sh -c "docker rm actions-runner" + +[Install] +WantedBy=multi-user.target diff --git a/arch/s390/self-hosted-builder/fs/usr/bin/actions-runner b/arch/s390/self-hosted-builder/fs/usr/bin/actions-runner new file mode 100755 index 0000000000..c9d8227d47 --- /dev/null +++ b/arch/s390/self-hosted-builder/fs/usr/bin/actions-runner @@ -0,0 +1,40 @@ +#!/bin/bash + +# +# Ephemeral runner startup script. +# +# Expects the following environment variables: +# +# - repo=/ +# - access_token= +# + +set -e -u + +# Check the cached registration token. +token_file=registration-token.json +set +e +expires_at=$(jq --raw-output .expires_at "$token_file" 2>/dev/null) +status=$? +set -e +if [[ $status -ne 0 || $(date +%s) -ge $(date -d "$expires_at" +%s) ]]; then + # Refresh the cached registration token. + curl \ + -X POST \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: token $access_token" \ + "https://api.github.com/repos/$repo/actions/runners/registration-token" \ + -o "$token_file" +fi + +# (Re-)register the runner. +registration_token=$(jq --raw-output .token "$token_file") +./config.sh remove --token "$registration_token" || true +./config.sh \ + --url "https://github.com/$repo" \ + --token "$registration_token" \ + --labels z15 \ + --ephemeral + +# Run one job. +./run.sh diff --git a/arch/s390/self-hosted-builder/fs/usr/bin/entrypoint b/arch/s390/self-hosted-builder/fs/usr/bin/entrypoint new file mode 100755 index 0000000000..eb8772becf --- /dev/null +++ b/arch/s390/self-hosted-builder/fs/usr/bin/entrypoint @@ -0,0 +1,30 @@ +#!/bin/bash + +# +# Container entrypoint that waits for all spawned processes. +# + +set -e -u + +# Create a FIFO and start reading from its read end. +tempdir=$(mktemp -d "/tmp/done.XXXXXXXXXX") +trap 'rm -r "$tempdir"' EXIT +done="$tempdir/pipe" +mkfifo "$done" +cat "$done" & waiter=$! + +# Start the workload. Its descendants will inherit the FIFO's write end. +status=0 +if [ "$#" -eq 0 ]; then + bash 9>"$done" || status=$? +else + "$@" 9>"$done" || status=$? +fi + +# When the workload and all of its descendants exit, the FIFO's write end will +# be closed and `cat "$done"` will exit. Wait until it happens. This is needed +# in order to handle SelfUpdater, which the workload may start in background +# before exiting. +wait "$waiter" + +exit "$status" diff --git a/arch/s390/self-hosted-builder/qemu-user-static.service b/arch/s390/self-hosted-builder/qemu-user-static.service new file mode 100644 index 0000000000..301f3edd94 --- /dev/null +++ b/arch/s390/self-hosted-builder/qemu-user-static.service @@ -0,0 +1,11 @@ +[Unit] +Description=Support for transparent execution of non-native binaries with QEMU user emulation + +[Service] +Type=oneshot +# The source code for iiilinuxibmcom/qemu-user-static is at https://github.com/iii-i/qemu-user-static/tree/v6.1.0-1 +# TODO: replace it with multiarch/qemu-user-static once version >6.1 is available +ExecStart=/usr/bin/docker run --rm --interactive --privileged iiilinuxibmcom/qemu-user-static --reset -p yes + +[Install] +WantedBy=multi-user.target From 564a40c2f50136e546f919cb390d6ac425909aff Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 29 Oct 2021 20:57:31 +0300 Subject: [PATCH 152/798] [MacOS] Downgrade to XCode 11.7.0 for pkgcheck. --- .github/workflows/pkgcheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 780c6e86f9..2cc4bdbca4 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -88,7 +88,7 @@ jobs: if: runner.os == 'macOS' uses: maxim-lobanov/setup-xcode@v1 with: - xcode-version: '12.1.1' + xcode-version: '11.7.0' - name: Compare builds run: | From e12fc9da60ae14969fb6853e51c070739f03f1b5 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 29 Oct 2021 20:08:30 +0300 Subject: [PATCH 153/798] [ARM] Try to compile test for float-abi detection code. --- CMakeLists.txt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ef7258a64..26558fd325 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -197,15 +197,24 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(BASEARCH_ARM_FOUND) if("${ARCH}" MATCHES "arm" AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") # Auto-detect support for ARM floating point ABI - check_c_compiler_flag(-mfloat-abi=softfp HAVE_FLOATABI_SOFTFP) + set(CMAKE_REQUIRED_FLAGS "-mfloat-abi=softfp") + check_c_source_compiles( + "#include + int main() { return 0; }" + HAVE_FLOATABI_SOFTFP) if(HAVE_FLOATABI_SOFTFP) set(FLOATABI "-mfloat-abi=softfp") else() - check_c_compiler_flag(-mfloat-abi=hard HAVE_FLOATABI_HARD) + set(CMAKE_REQUIRED_FLAGS "-mfloat-abi=hard") + check_c_source_compiles( + "#include + int main() { return 0; }" + HAVE_FLOATABI_HARD) if(HAVE_FLOATABI_HARD) set(FLOATABI "-mfloat-abi=hard") endif() endif() + set(CMAKE_REQUIRED_FLAGS) if(FLOATABI) message(STATUS "ARM floating point arch: ${FLOATABI}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLOATABI}") From 81154c58da8aa516fc1acb1ae3429406dc734bb7 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 11 Nov 2021 17:55:13 -0800 Subject: [PATCH 154/798] Fixed minideflate write buffers being overwritten. --- test/minideflate.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index 8ce57fad58..ae04a29e89 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -70,6 +70,8 @@ void deflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ c_stream.opaque = (void *)0; c_stream.total_in = 0; c_stream.total_out = 0; + c_stream.next_out = write_buf; + c_stream.avail_out = write_buf_size; err = PREFIX(deflateInit2)(&c_stream, level, Z_DEFLATED, window_bits, mem_level, strategy); CHECK_ERR(err, "deflateInit2"); @@ -82,11 +84,9 @@ void deflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ break; c_stream.next_in = (z_const uint8_t *)read_buf; - c_stream.next_out = write_buf; c_stream.avail_in = read; do { - c_stream.avail_out = write_buf_size; err = PREFIX(deflate)(&c_stream, flush); if (err == Z_STREAM_END) break; CHECK_ERR(err, "deflate"); @@ -94,6 +94,7 @@ void deflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ if (c_stream.next_out == write_buf + write_buf_size) { fwrite(write_buf, 1, write_buf_size, fout); c_stream.next_out = write_buf; + c_stream.avail_out = write_buf_size; } } while (c_stream.next_in < read_buf + read); } while (err == Z_OK); @@ -105,9 +106,9 @@ void deflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ if (c_stream.next_out == write_buf + write_buf_size) { fwrite(write_buf, 1, write_buf_size, fout); c_stream.next_out = write_buf; + c_stream.avail_out = write_buf_size; } - c_stream.avail_out = write_buf_size; err = PREFIX(deflate)(&c_stream, Z_FINISH); if (err == Z_STREAM_END) break; CHECK_ERR(err, "deflate"); @@ -155,6 +156,8 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ d_stream.opaque = (void *)0; d_stream.total_in = 0; d_stream.total_out = 0; + d_stream.next_out = write_buf; + d_stream.avail_out = write_buf_size; err = PREFIX(inflateInit2)(&d_stream, window_bits); CHECK_ERR(err, "inflateInit2"); @@ -167,11 +170,9 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ break; d_stream.next_in = (z_const uint8_t *)read_buf; - d_stream.next_out = write_buf; d_stream.avail_in = read; do { - d_stream.avail_out = write_buf_size; err = PREFIX(inflate)(&d_stream, flush); if (err == Z_STREAM_END) break; CHECK_ERR(err, "deflate"); @@ -179,6 +180,7 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ if (d_stream.next_out == write_buf + write_buf_size) { fwrite(write_buf, 1, write_buf_size, fout); d_stream.next_out = write_buf; + d_stream.avail_out = write_buf_size; } } while (d_stream.next_in < read_buf + read); } while (err == Z_OK); @@ -190,9 +192,9 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ if (d_stream.next_out == write_buf + write_buf_size) { fwrite(write_buf, 1, write_buf_size, fout); d_stream.next_out = write_buf; + d_stream.avail_out = write_buf_size; } - d_stream.avail_out = write_buf_size; err = PREFIX(inflate)(&d_stream, Z_FINISH); if (err == Z_STREAM_END) break; CHECK_ERR(err, "inflate"); From dc3b60841dbfa9cf37be3efb4568f055b4e15580 Mon Sep 17 00:00:00 2001 From: Jim Kukunas Date: Wed, 30 Jun 2021 19:36:08 -0400 Subject: [PATCH 155/798] Reorganize inflate window layout This commit significantly improves inflate performance by reorganizing the window buffer into a contiguous window and pending output buffer. The goal of this layout is to reduce branching, improve cache locality, and enable for the use of crc folding with gzip input. The window buffer is allocated as a multiple of the user-selected window size. In this commit, a factor of 2 is utilized. The layout of the window buffer is divided into two sections. The first section, window offset [0, wsize), is reserved for history that has already been output. The second section, window offset [wsize, 2 * wsize), is reserved for buffering pending output that hasn't been flushed to the user's output buffer yet. The history section grows downwards, towards the window offset of 0. The pending output section grows upwards, towards the end of the buffer. As a result, all of the possible distance/length data that may need to be copied is contiguous. This removes the need to stitch together output from 2 separate buffers. In the case of gzip input, crc folding is used to copy the pending output to the user's buffers. Co-authored-by: Nathan Moinvaziri --- infback.c | 15 +-- inffast.c | 117 +++++---------------- inffast.h | 2 +- inflate.c | 267 +++++++++++++++++++++--------------------------- inflate.h | 5 + inflate_p.h | 100 ++++++++++++++++-- test/infcover.c | 19 +--- 7 files changed, 243 insertions(+), 282 deletions(-) diff --git a/infback.c b/infback.c index cab3f66cf6..8c43a7cef8 100644 --- a/infback.c +++ b/infback.c @@ -40,7 +40,7 @@ int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowB } if (strm->zfree == NULL) strm->zfree = zng_cfree; - state = (struct inflate_state *) ZALLOC(strm, 1, sizeof(struct inflate_state)); + state = (struct inflate_state *)ZALLOC_STATE(strm, 1, sizeof(struct inflate_state)); if (state == NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); @@ -338,17 +338,6 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in state->mode = LEN; case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= INFLATE_FAST_MIN_HAVE && - left >= INFLATE_FAST_MIN_LEFT) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - zng_inflate_fast(strm, state->wsize); - LOAD(); - break; - } - /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; @@ -490,7 +479,7 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in int32_t Z_EXPORT PREFIX(inflateBackEnd)(PREFIX3(stream) *strm) { if (strm == NULL || strm->state == NULL || strm->zfree == NULL) return Z_STREAM_ERROR; - ZFREE(strm, strm->state); + ZFREE_STATE(strm, strm->state); strm->state = NULL; Tracev((stderr, "inflate: end\n")); return Z_OK; diff --git a/inffast.c b/inffast.c index 2c3add3a84..57031aeca7 100644 --- a/inffast.c +++ b/inffast.c @@ -62,22 +62,16 @@ static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ -void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { - /* start: inflate()'s starting value for strm->avail_out */ +void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { struct inflate_state *state; z_const unsigned char *in; /* local strm->next_in */ const unsigned char *last; /* have enough input while in < last */ unsigned char *out; /* local strm->next_out */ - unsigned char *beg; /* inflate()'s initial strm->next_out */ unsigned char *end; /* while out < end, enough space available */ - unsigned char *safe; /* can use chunkcopy provided out < safe */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char *window; /* allocated sliding window, if wsize != 0 */ /* hold is a local copy of strm->hold. By default, hold satisfies the same invariants that strm->hold does, namely that (hold >> bits) == 0. This @@ -127,24 +121,17 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ - unsigned char *from; /* where to copy match from */ - unsigned extra_safe; /* copy chunks safely in all cases */ /* copy state to local variables */ state = (struct inflate_state *)strm->state; in = strm->next_in; last = in + (strm->avail_in - (INFLATE_FAST_MIN_HAVE - 1)); - out = strm->next_out; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - (INFLATE_FAST_MIN_LEFT - 1)); - safe = out + strm->avail_out; + wsize = state->wsize; + out = state->window + wsize + state->wnext; + end = state->window + (wsize * 2) - (INFLATE_FAST_MIN_LEFT - 1); #ifdef INFLATE_STRICT dmax = state->dmax; #endif - wsize = state->wsize; - whave = state->whave; - wnext = state->wnext; - window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; @@ -152,11 +139,6 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; - /* Detect if out and window point to the same memory allocation. In this instance it is - necessary to use safe chunk copy functions to prevent overwriting the window. If the - window is overwritten then future matches with far distances will fail to copy correctly. */ - extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); - /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { @@ -165,6 +147,13 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { in += 6; bits += 48; } + if (out >= end) { + state->wnext = (uint32_t)(out - (state->window + wsize)); + window_output_flush(strm); + out = state->window + state->wsize + state->wnext; + if (strm->avail_out == 0) + break; + } here = lcode + (hold & lmask); dolen: DROPBITS(here->bits); @@ -211,76 +200,18 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { #endif DROPBITS(op); Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state->sane) { - SET_BAD("invalid distance too far back"); - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (len <= op - whave) { - do { - *out++ = 0; - } while (--len); - continue; - } - len -= op - whave; - do { - *out++ = 0; - } while (--op > whave); - if (op == 0) { - from = out - dist; - do { - *out++ = *from++; - } while (--len); - continue; - } -#endif - } - from = window; - if (wnext == 0) { /* very common case */ - from += wsize - op; - } else if (wnext >= op) { /* contiguous in window */ - from += wnext - op; - } else { /* wrap around window */ - op -= wnext; - from += wsize - op; - if (op < len) { /* some from end of window */ - len -= op; - out = functable.chunkcopy_safe(out, from, op, safe); - from = window; /* more from start of window */ - op = wnext; - /* This (rare) case can create a situation where - the first chunkcopy below must be checked. - */ - } - } - if (op < len) { /* still need some from output */ - len -= op; - out = functable.chunkcopy_safe(out, from, op, safe); - out = functable.chunkunroll(out, &dist, &len); - out = functable.chunkcopy_safe(out, out - dist, len, safe); - } else { - out = functable.chunkcopy_safe(out, from, len, safe); + + if (out - dist < ((state->window + state->wsize) - state->whave)) { + if (state->sane) { + SET_BAD("invalid distance too far back"); + break; } - } else if (extra_safe) { - /* Whole reference is in range of current output. */ - if (dist >= len || dist >= state->chunksize) - out = functable.chunkcopy_safe(out, out - dist, len, safe); - else - out = functable.chunkmemset_safe(out, dist, len, (unsigned)((safe - out) + 1)); + } + + if (len > dist || dist < state->chunksize) { + out = functable.chunkmemset(out, dist, len); } else { - /* Whole reference is in range of current output. No range checks are - necessary because we start with room for at least 258 bytes of output, - so unroll and roundoff operations can write beyond `out+len` so long - as they stay within 258 bytes of `out`. - */ - if (dist >= len || dist >= state->chunksize) - out = functable.chunkcopy(out, out - dist, len); - else - out = functable.chunkmemset(out, dist, len); + out = functable.chunkcopy(out, out - dist, len); } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode + here->val + BITS(op); @@ -300,7 +231,7 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { SET_BAD("invalid literal/length code"); break; } - } while (in < last && out < end); + } while (in < last); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; @@ -310,12 +241,10 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { /* update state and return */ strm->next_in = in; - strm->next_out = out; strm->avail_in = (unsigned)(in < last ? (INFLATE_FAST_MIN_HAVE - 1) + (last - in) : (INFLATE_FAST_MIN_HAVE - 1) - (in - last)); - strm->avail_out = (unsigned)(out < end ? (INFLATE_FAST_MIN_LEFT - 1) + (end - out) - : (INFLATE_FAST_MIN_LEFT - 1) - (out - end)); + state->wnext = (uint32_t)(out - (state->window + state->wsize)); Assert(bits <= 32, "Remaining bits greater than 32"); state->hold = (uint32_t)hold; state->bits = bits; diff --git a/inffast.h b/inffast.h index 179a65da60..cf9a3e2d2b 100644 --- a/inffast.h +++ b/inffast.h @@ -10,7 +10,7 @@ subject to change. Applications should only use zlib.h. */ -void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start); +void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm); #define INFLATE_FAST_MIN_HAVE 8 #define INFLATE_FAST_MIN_LEFT 258 diff --git a/inflate.c b/inflate.c index f87d6c94d5..cca8df67a7 100644 --- a/inflate.c +++ b/inflate.c @@ -12,36 +12,8 @@ #include "inffixed_tbl.h" #include "functable.h" -/* Architecture-specific hooks. */ -#ifdef S390_DFLTCC_INFLATE -# include "arch/s390/dfltcc_inflate.h" -#else -/* Memory management for the inflate state. Useful for allocating arch-specific extension blocks. */ -# define ZALLOC_STATE(strm, items, size) ZALLOC(strm, items, size) -# define ZFREE_STATE(strm, addr) ZFREE(strm, addr) -# define ZCOPY_STATE(dst, src, size) memcpy(dst, src, size) -/* Memory management for the window. Useful for allocation the aligned window. */ -# define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) -# define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr) -/* Invoked at the end of inflateResetKeep(). Useful for initializing arch-specific extension blocks. */ -# define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0) -/* Invoked at the beginning of inflatePrime(). Useful for updating arch-specific buffers. */ -# define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0) -/* Invoked at the beginning of each block. Useful for plugging arch-specific inflation code. */ -# define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0) -/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */ -# define INFLATE_NEED_CHECKSUM(strm) 1 -/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */ -# define INFLATE_NEED_UPDATEWINDOW(strm) 1 -/* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */ -# define INFLATE_MARK_HOOK(strm) do {} while (0) -/* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */ -#define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) -#endif - /* function prototypes */ static int inflateStateCheck(PREFIX3(stream) *strm); -static int updatewindow(PREFIX3(stream) *strm, const unsigned char *end, uint32_t copy); static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t len); static int inflateStateCheck(PREFIX3(stream) *strm) { @@ -87,7 +59,6 @@ int32_t Z_EXPORT PREFIX(inflateReset)(PREFIX3(stream) *strm) { if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; - state->wsize = 0; state->whave = 0; state->wnext = 0; return PREFIX(inflateResetKeep)(strm); @@ -120,6 +91,7 @@ int32_t Z_EXPORT PREFIX(inflateReset2)(PREFIX3(stream) *strm, int32_t windowBits if (state->window != NULL && state->wbits != (unsigned)windowBits) { ZFREE_WINDOW(strm, state->window); state->window = NULL; + state->wsize = 0; } /* update state and reset the rest of it */ @@ -156,12 +128,14 @@ int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits strm->state = (struct internal_state *)state; state->strm = strm; state->window = NULL; + state->wsize = 0; state->mode = HEAD; /* to pass state test in inflateReset2() */ state->chunksize = functable.chunksize(); ret = PREFIX(inflateReset2)(strm, windowBits); if (ret != Z_OK) { ZFREE_STATE(strm, state); strm->state = NULL; + return ret; } return ret; } @@ -206,9 +180,9 @@ int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) { /* if it hasn't been done already, allocate space for the window */ if (state->window == NULL) { unsigned wsize = 1U << state->wbits; - state->window = (unsigned char *) ZALLOC_WINDOW(state->strm, wsize + state->chunksize, sizeof(unsigned char)); - if (state->window == Z_NULL) - return 1; + state->window = (unsigned char *)ZALLOC_WINDOW(state->strm, (wsize * 2) + state->chunksize, sizeof(unsigned char)); + if (state->window == NULL) + return Z_MEM_ERROR; memset(state->window + wsize, 0, state->chunksize); } @@ -219,58 +193,9 @@ int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) { state->whave = 0; } - return 0; -} - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t copy) { - struct inflate_state *state; - uint32_t dist; - - state = (struct inflate_state *)strm->state; - - if (inflate_ensure_window(state)) return 1; - - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state->wsize) { - memcpy(state->window, end - state->wsize, state->wsize); - state->wnext = 0; - state->whave = state->wsize; - } else { - dist = state->wsize - state->wnext; - if (dist > copy) - dist = copy; - memcpy(state->window + state->wnext, end - copy, dist); - copy -= dist; - if (copy) { - memcpy(state->window, end - copy, copy); - state->wnext = copy; - state->whave = state->wsize; - } else { - state->wnext += dist; - if (state->wnext == state->wsize) - state->wnext = 0; - if (state->whave < state->wsize) - state->whave += dist; - } - } - return 0; + return Z_OK; } - /* Private macros for inflate() Look in inflate_p.h for macros shared with inflateBack() @@ -376,7 +301,6 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { unsigned bits; /* bits in bit buffer */ uint32_t in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ - unsigned char *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ @@ -578,7 +502,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } - strm->adler = state->check = CRC32_INITIAL_VALUE; + strm->adler = state->check = functable.crc32_fold_reset(&state->crc_fold); state->mode = TYPE; break; #endif @@ -601,6 +525,17 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { goto inf_leave; case TYPEDO: + /* create window if it doesn't exist */ + if (state->window == NULL) { + RESTORE(); + ret = inflate_ensure_window(state); + if (ret != Z_OK) { + ZFREE_STATE(strm, state); + strm->state = NULL; + return ret; + } + LOAD(); + } /* determine and dispatch block type */ INFLATE_TYPEDO_HOOK(strm, flush); /* hook for IBM Z DFLTCC */ if (state->last) { @@ -657,13 +592,24 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* copy stored block from input to output */ copy = state->length; if (copy) { + unsigned char *end = state->window + (state->wsize * 2); + int64_t diff = end - put; + copy = MIN(copy, have); - copy = MIN(copy, left); - if (copy == 0) goto inf_leave; + if (copy > diff) { + if (left > 0) { + RESTORE(); + window_output_flush(strm); + LOAD(); + diff = end - put; + } + copy = MIN(copy, (uint32_t)diff); + } + if (copy == 0) + goto inf_leave; memcpy(put, next, copy); have -= copy; next += copy; - left -= copy; put += copy; state->length -= copy; break; @@ -799,7 +745,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* use inflate_fast() if we have enough input and output */ if (have >= INFLATE_FAST_MIN_HAVE && left >= INFLATE_FAST_MIN_LEFT) { RESTORE(); - zng_inflate_fast(strm, out); + zng_inflate_fast(strm); LOAD(); if (state->mode == TYPE) state->back = -1; @@ -914,69 +860,73 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; - case MATCH: + case MATCH: { /* copy match from window to output */ - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->whave) { - if (state->sane) { - SET_BAD("invalid distance too far back"); - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - Trace((stderr, "inflate.c too far\n")); - copy -= state->whave; - copy = MIN(copy, state->length); - copy = MIN(copy, left); - left -= copy; - state->length -= copy; - do { - *put++ = 0; - } while (--copy); - if (state->length == 0) - state->mode = LEN; - break; -#endif + if (left == 0) + goto inf_leave; + + unsigned char *end = state->window + (state->wsize * 2); + int64_t buf_left = end - put; + copy = state->length; + RESTORE(); + if (copy > buf_left) { + if (strm->avail_out > 0) { + /* relies on RESTORE() above with no changes to those vars */ + window_output_flush(strm); + LOAD(); + buf_left = end - put; } - if (copy > state->wnext) { - copy -= state->wnext; - from = state->window + (state->wsize - copy); - } else { - from = state->window + (state->wnext - copy); + copy = MIN(copy, (uint32_t)buf_left); + } + if (copy == 0) + goto inf_leave; + if (state->offset > state->wnext + state->whave) { + if (state->sane) { + SET_BAD("invalid distance too far back"); + break; } - copy = MIN(copy, state->length); - copy = MIN(copy, left); - - put = functable.chunkcopy_safe(put, from, copy, put + left); + } + unsigned char *next_out = state->window + state->wsize + state->wnext; + if (copy <= state->offset) { + functable.chunkcopy_safe(next_out, next_out - state->offset, copy, put + buf_left); } else { /* copy from output */ - copy = MIN(state->length, left); - - put = functable.chunkmemset_safe(put, state->offset, copy, left); + functable.chunkmemset_safe(next_out, state->offset, copy, (uint32_t)buf_left); } - left -= copy; + state->wnext += copy; state->length -= copy; + LOAD(); if (state->length == 0) state->mode = LEN; break; - + } case LIT: + if (put >= state->window + (state->wsize * 2)) { + RESTORE(); + window_output_flush(strm); + LOAD(); + } if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); - left--; state->mode = LEN; break; case CHECK: + RESTORE(); + window_output_flush(strm); + LOAD(); + if (strm->avail_out == 0 && state->wnext) + goto inf_leave; if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out) - strm->adler = state->check = UPDATE(state->check, put - out, out); + + if (INFLATE_NEED_CHECKSUM(strm) && strm->total_out) { + if (state->wrap & 2) + strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold); + } out = left; if ((state->wrap & 4) && ( #ifdef GUNZIP @@ -1026,26 +976,21 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. + error. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); - if (INFLATE_NEED_UPDATEWINDOW(strm) && - (state->wsize || (out != strm->avail_out && state->mode < BAD && - (state->mode < CHECK || flush != Z_FINISH)))) { - if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - } + + if (strm->avail_out && state->wnext) + window_output_flush(strm); + in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out) - strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) @@ -1086,8 +1031,10 @@ int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *di int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) { struct inflate_state *state; - unsigned long dictid; - int32_t ret; + unsigned long dictid, dict_copy, hist_copy; + const unsigned char *dict_from, *hist_from; + unsigned char *dict_to, *hist_to; + int ret; /* check state */ if (inflateStateCheck(strm)) @@ -1102,14 +1049,33 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8 if (dictid != state->check) return Z_DATA_ERROR; } - - /* copy dictionary to window using updatewindow(), which will amend the - existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary + dictLength, dictLength); - if (ret) { - state->mode = MEM; + ret = inflate_ensure_window(state); + if (ret != Z_OK) return Z_MEM_ERROR; + + Tracec(state->wnext != 0, (stderr, "Setting dictionary with unflushed output")); + + /* copy dictionary to window and amend if necessary */ + dict_from = dictionary; + dict_copy = dictLength; + if (dict_copy > state->wsize) { + dict_copy = state->wsize; + dict_from += (dictLength - dict_copy); } + dict_to = state->window + state->wsize - dict_copy; + + hist_from = state->window + state->wsize - state->whave; + hist_copy = state->wsize - dict_copy; + if (hist_copy > state->whave) + hist_copy = state->whave; + hist_to = dict_to - hist_copy; + + if (hist_copy) + memcpy(hist_to, hist_from, hist_copy); + if (dict_copy) + memcpy(dict_to, dict_from, dict_copy); + + state->whave = hist_copy + dict_copy; state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; @@ -1248,7 +1214,8 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou return Z_MEM_ERROR; window = NULL; if (state->window != NULL) { - window = (unsigned char *)ZALLOC_WINDOW(source, 1U << state->wbits, sizeof(unsigned char)); + wsize = 1U << state->wbits; + window = (unsigned char *)ZALLOC_WINDOW(state->strm, (wsize * 2) + state->chunksize, sizeof(unsigned char)); if (window == NULL) { ZFREE_STATE(source, copy); return Z_MEM_ERROR; @@ -1266,7 +1233,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou copy->next = copy->codes + (state->next - state->codes); if (window != NULL) { wsize = 1U << state->wbits; - memcpy(window, state->window, wsize); + memcpy(window, state->window, (wsize * 2) + state->chunksize); } copy->window = window; dest->state = (struct internal_state *)copy; diff --git a/inflate.h b/inflate.h index a427494659..d33ea2a708 100644 --- a/inflate.h +++ b/inflate.h @@ -11,6 +11,8 @@ #ifndef INFLATE_H_ #define INFLATE_H_ +#include "crc32_fold.h" + /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ @@ -100,6 +102,9 @@ struct inflate_state { uint32_t whave; /* valid bytes in the window */ uint32_t wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if needed */ + + crc32_fold ALIGNED_(16) crc_fold; + /* bit accumulator */ uint32_t hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ diff --git a/inflate_p.h b/inflate_p.h index 76fe2dccbe..168f270fad 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -5,18 +5,41 @@ #ifndef INFLATE_P_H #define INFLATE_P_H -/* - * Macros shared by inflate() and inflateBack() - */ +#include "zbuild.h" +#include "functable.h" -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE(check, buf, len) \ - (state->flags ? PREFIX(crc32)(check, buf, len) : functable.adler32(check, buf, len)) +/* Architecture-specific hooks. */ +#ifdef S390_DFLTCC_INFLATE +# include "arch/s390/dfltcc_inflate.h" #else -# define UPDATE(check, buf, len) functable.adler32(check, buf, len) +/* Memory management for the inflate state. Useful for allocating arch-specific extension blocks. */ +# define ZALLOC_STATE(strm, items, size) ZALLOC(strm, items, size) +# define ZFREE_STATE(strm, addr) ZFREE(strm, addr) +# define ZCOPY_STATE(dst, src, size) memcpy(dst, src, size) +/* Memory management for the window. Useful for allocation the aligned window. */ +# define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) +# define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr) +/* Invoked at the end of inflateResetKeep(). Useful for initializing arch-specific extension blocks. */ +# define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0) +/* Invoked at the beginning of inflatePrime(). Useful for updating arch-specific buffers. */ +# define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0) +/* Invoked at the beginning of each block. Useful for plugging arch-specific inflation code. */ +# define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0) +/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */ +# define INFLATE_NEED_CHECKSUM(strm) 1 +/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */ +# define INFLATE_NEED_UPDATEWINDOW(strm) 1 +/* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */ +# define INFLATE_MARK_HOOK(strm) do {} while (0) +/* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */ +#define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) #endif + +/* + * Macros shared by inflate() and inflateBack() + */ + /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ @@ -39,7 +62,7 @@ /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ - put = strm->next_out; \ + put = state->window + state->wsize + state->wnext; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ @@ -50,7 +73,7 @@ /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ - strm->next_out = put; \ + state->wnext = (uint32_t)(put - (state->window + state->wsize)); \ strm->avail_out = left; \ strm->next_in = (z_const unsigned char *)next; \ strm->avail_in = have; \ @@ -99,3 +122,60 @@ state->mode = BAD; \ strm->msg = (char *)errmsg; \ } while (0) + + +static inline void inf_crc_copy(PREFIX3(stream) *strm, unsigned char *const dst, + const unsigned char *const src, size_t len) { + struct inflate_state *const state = (struct inflate_state *const)strm->state; + + if (!INFLATE_NEED_CHECKSUM(strm)) + return; + + /* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP + if (state->flags) + functable.crc32_fold_copy(&state->crc_fold, dst, src, len); + else +#endif + { + memcpy(dst, src, len); + strm->adler = state->check = functable.adler32(state->check, dst, len); + } +} + +static inline void window_output_flush(PREFIX3(stream) *strm) { + struct inflate_state *const state = (struct inflate_state *const)strm->state; + size_t write_offset, read_offset, copy_size; + uint32_t out_bytes; + + if (state->wnext > strm->avail_out) { + out_bytes = strm->avail_out; + copy_size = state->wnext - out_bytes; + } else { + out_bytes = state->wnext; + copy_size = 0; + } + + /* Copy from pending buffer to stream output */ + inf_crc_copy(strm, strm->next_out, state->window + state->wsize, out_bytes); + + strm->avail_out -= out_bytes; + strm->next_out += out_bytes; + + /* Discard bytes in sliding window */ + if (state->whave + out_bytes > state->wsize) { + write_offset = 0; + read_offset = out_bytes; + copy_size += state->wsize; + } else { + read_offset = state->wsize - state->whave; + write_offset = read_offset - out_bytes; + copy_size += state->whave + out_bytes; + } + + memmove(state->window + write_offset, state->window + read_offset, copy_size); + + state->wnext -= out_bytes; + state->whave += out_bytes; + state->whave = MIN(state->whave, state->wsize); +} diff --git a/test/infcover.c b/test/infcover.c index 3446289eff..72a4c575be 100644 --- a/test/infcover.c +++ b/test/infcover.c @@ -15,13 +15,8 @@ /* get definition of internal structure so we can mess with it (see pull()), and so we can call inflate_trees() (see cover5()) */ -#define ZLIB_INTERNAL #include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif +#include "zutil.h" #include "inftrees.h" #include "inflate.h" @@ -293,6 +288,10 @@ static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int mem_setup(&strm); strm.avail_in = 0; strm.next_in = NULL; + + mem_limit(&strm, 1); + ret = PREFIX(inflateInit2)(&strm, win); assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); ret = PREFIX(inflateInit2)(&strm, win); if (ret != Z_OK) { mem_done(&strm, what); @@ -325,10 +324,6 @@ static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int if (ret == Z_NEED_DICT) { ret = PREFIX(inflateSetDictionary)(&strm, in, 1); assert(ret == Z_DATA_ERROR); - mem_limit(&strm, 1); - ret = PREFIX(inflateSetDictionary)(&strm, out, 0); - assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); ((struct inflate_state *)strm.state)->mode = DICT; ret = PREFIX(inflateSetDictionary)(&strm, out, 0); assert(ret == Z_OK); @@ -422,10 +417,6 @@ static void cover_wrap(void) { strm.next_in = (void *)"\x63"; strm.avail_out = 1; strm.next_out = (void *)&ret; - mem_limit(&strm, 1); - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); memset(dict, 0, 257); ret = PREFIX(inflateSetDictionary)(&strm, dict, 257); assert(ret == Z_OK); From 2d2dde43b11c40cb58a339ff4a8425bca0091c31 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 23 Aug 2021 12:21:40 -0700 Subject: [PATCH 156/798] Add back original version of inflate_fast for use with inflateBack. --- infback.c | 11 +++ inffast.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++ inffast.h | 1 + inflate_p.h | 22 +++++ 4 files changed, 286 insertions(+) diff --git a/infback.c b/infback.c index 8c43a7cef8..cf0549ae1e 100644 --- a/infback.c +++ b/infback.c @@ -338,6 +338,17 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in state->mode = LEN; case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= INFLATE_FAST_MIN_HAVE && + left >= INFLATE_FAST_MIN_LEFT) { + RESTORE_BACK(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + zng_inflate_fast_back(strm, state->wsize); + LOAD_BACK(); + break; + } + /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; diff --git a/inffast.c b/inffast.c index 57031aeca7..899534f0dc 100644 --- a/inffast.c +++ b/inffast.c @@ -250,6 +250,258 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { state->bits = bits; return; } +void Z_INTERNAL zng_inflate_fast_back(PREFIX3(stream) *strm, unsigned long start) { + /* start: inflate()'s starting value for strm->avail_out */ + struct inflate_state *state; + z_const unsigned char *in; /* local strm->next_in */ + const unsigned char *last; /* have enough input while in < last */ + unsigned char *out; /* local strm->next_out */ + unsigned char *beg; /* inflate()'s initial strm->next_out */ + unsigned char *end; /* while out < end, enough space available */ + unsigned char *safe; /* can use chunkcopy provided out < safe */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char *window; /* allocated sliding window, if wsize != 0 */ + + /* hold is a local copy of strm->hold. By default, hold satisfies the same + invariants that strm->hold does, namely that (hold >> bits) == 0. This + invariant is kept by loading bits into hold one byte at a time, like: + hold |= next_byte_of_input << bits; in++; bits += 8; + If we need to ensure that bits >= 15 then this code snippet is simply + repeated. Over one iteration of the outermost do/while loop, this + happens up to six times (48 bits of input), as described in the NOTES + above. + However, on some little endian architectures, it can be significantly + faster to load 64 bits once instead of 8 bits six times: + if (bits <= 16) { + hold |= next_8_bytes_of_input << bits; in += 6; bits += 48; + } + Unlike the simpler one byte load, shifting the next_8_bytes_of_input + by bits will overflow and lose those high bits, up to 2 bytes' worth. + The conservative estimate is therefore that we have read only 6 bytes + (48 bits). Again, as per the NOTES above, 48 bits is sufficient for the + rest of the iteration, and we will not need to load another 8 bytes. + Inside this function, we no longer satisfy (hold >> bits) == 0, but + this is not problematic, even if that overflow does not land on an 8 bit + byte boundary. Those excess bits will eventually shift down lower as the + Huffman decoder consumes input, and when new input bits need to be loaded + into the bits variable, the same input bits will be or'ed over those + existing bits. A bitwise or is idempotent: (a | b | b) equals (a | b). + Note that we therefore write that load operation as "hold |= etc" and not + "hold += etc". + Outside that loop, at the end of the function, hold is bitwise and'ed + with (1<hold >> state->bits) == 0. + */ + uint64_t hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const *lcode; /* local strm->lencode */ + code const *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + const code *here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char *from; /* where to copy match from */ + unsigned extra_safe; /* copy chunks safely in all cases */ + + /* copy state to local variables */ + state = (struct inflate_state *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - (INFLATE_FAST_MIN_HAVE - 1)); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - (INFLATE_FAST_MIN_LEFT - 1)); + safe = out + strm->avail_out; +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* Detect if out and window point to the same memory allocation. In this instance it is + necessary to use safe chunk copy functions to prevent overwriting the window. If the + window is overwritten then future matches with far distances will fail to copy correctly. */ + extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold |= load_64_bits(in, bits); + in += 6; + bits += 48; + } + here = lcode + (hold & lmask); + dolen: + DROPBITS(here->bits); + op = here->op; + if (op == 0) { /* literal */ + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); + } else if (op & 16) { /* length base */ + len = here->val; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold |= load_64_bits(in, bits); + in += 6; + bits += 48; + } + len += BITS(op); + DROPBITS(op); + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold |= load_64_bits(in, bits); + in += 6; + bits += 48; + } + here = dcode + (hold & dmask); + dodist: + DROPBITS(here->bits); + op = here->op; + if (op & 16) { /* distance base */ + dist = here->val; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold |= load_64_bits(in, bits); + in += 6; + bits += 48; + } + dist += BITS(op); +#ifdef INFLATE_STRICT + if (dist > dmax) { + SET_BAD("invalid distance too far back"); + break; + } +#endif + DROPBITS(op); + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + SET_BAD("invalid distance too far back"); + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + } else if (wnext >= op) { /* contiguous in window */ + from += wnext - op; + } else { /* wrap around window */ + op -= wnext; + from += wsize - op; + if (op < len) { /* some from end of window */ + len -= op; + out = functable.chunkcopy_safe(out, from, op, safe); + from = window; /* more from start of window */ + op = wnext; + /* This (rare) case can create a situation where + the first chunkcopy below must be checked. + */ + } + } + if (op < len) { /* still need some from output */ + len -= op; + out = functable.chunkcopy_safe(out, from, op, safe); + out = functable.chunkunroll(out, &dist, &len); + out = functable.chunkcopy_safe(out, out - dist, len, safe); + } else { + out = functable.chunkcopy_safe(out, from, len, safe); + } + } else if (extra_safe) { + /* Whole reference is in range of current output. */ + if (dist >= len || dist >= state->chunksize) + out = functable.chunkcopy_safe(out, out - dist, len, safe); + else + out = functable.chunkmemset_safe(out, dist, len, (unsigned)((safe - out) + 1)); + } else { + /* Whole reference is in range of current output. No range checks are + necessary because we start with room for at least 258 bytes of output, + so unroll and roundoff operations can write beyond `out+len` so long + as they stay within 258 bytes of `out`. + */ + if (dist >= len || dist >= state->chunksize) + out = functable.chunkcopy(out, out - dist, len); + else + out = functable.chunkmemset(out, dist, len); + } + } else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode + here->val + BITS(op); + goto dodist; + } else { + SET_BAD("invalid distance code"); + break; + } + } else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode + here->val + BITS(op); + goto dolen; + } else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } else { + SET_BAD("invalid literal/length code"); + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (UINT64_C(1) << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? (INFLATE_FAST_MIN_HAVE - 1) + (last - in) + : (INFLATE_FAST_MIN_HAVE - 1) - (in - last)); + strm->avail_out = (unsigned)(out < end ? (INFLATE_FAST_MIN_LEFT - 1) + (end - out) + : (INFLATE_FAST_MIN_LEFT - 1) - (out - end)); + + Assert(bits <= 32, "Remaining bits greater than 32"); + state->hold = (uint32_t)hold; + state->bits = bits; + return; +} /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): diff --git a/inffast.h b/inffast.h index cf9a3e2d2b..e8d7e6e01d 100644 --- a/inffast.h +++ b/inffast.h @@ -11,6 +11,7 @@ */ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm); +void Z_INTERNAL zng_inflate_fast_back(PREFIX3(stream) *strm, unsigned long start); #define INFLATE_FAST_MIN_HAVE 8 #define INFLATE_FAST_MIN_LEFT 258 diff --git a/inflate_p.h b/inflate_p.h index 168f270fad..b2e8d8de2f 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -70,6 +70,17 @@ bits = state->bits; \ } while (0) +/* Load registers with state in inflateBack() for speed */ +#define LOAD_BACK() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ @@ -81,6 +92,17 @@ state->bits = bits; \ } while (0) +/* Restore state from registers in inflateBack() */ +#define RESTORE_BACK() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = (z_const unsigned char *)next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + /* Clear the input bit accumulator */ #define INITBITS() \ do { \ From b4ca25afabba7b4bf74d36e26728006d28df891d Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 25 Oct 2021 18:50:26 -0400 Subject: [PATCH 157/798] DFLTCC update for window optimization from Jim & Nathan Stop relying on software and hardware inflate window formats being the same and act the way we already do for deflate: provide and implement window-related hooks. Another possibility would be to use an in-line history buffer (by not setting HBT_CIRCULAR), but this would require an extra memmove(). Also fix a couple corner cases in the software implementation of inflateGetDictionary() and inflateSetDictionary(). --- arch/s390/README.md | 20 +++++++++------- arch/s390/dfltcc_deflate.c | 48 ++------------------------------------ arch/s390/dfltcc_detail.h | 47 +++++++++++++++++++++++++++++++++++++ arch/s390/dfltcc_inflate.c | 30 ++++++++++++++++++++---- arch/s390/dfltcc_inflate.h | 16 ++++++++++++- deflate.c | 2 +- inflate.c | 28 +++++++++++----------- inflate_p.h | 11 ++++++--- 8 files changed, 126 insertions(+), 76 deletions(-) diff --git a/arch/s390/README.md b/arch/s390/README.md index 90066f0f96..b4b3fb8b51 100644 --- a/arch/s390/README.md +++ b/arch/s390/README.md @@ -66,11 +66,10 @@ buffer and a window. `ZALLOC_STATE()`, `ZFREE_STATE()`, `ZCOPY_STATE()`, details for the parameter block (which is allocated alongside zlib-ng state) and the window (which must be page-aligned). -While inflate software and hardware window formats match, this is not -the case for deflate. Therefore, `deflateSetDictionary()` and -`deflateGetDictionary()` need special handling, which is triggered using -`DEFLATE_SET_DICTIONARY_HOOK()` and `DEFLATE_GET_DICTIONARY_HOOK()` -macros. +Software and hardware deflate window formats don't match, therefore, +`deflateSetDictionary()` and `deflateGetDictionary()` need special handling, +which is triggered using `DEFLATE_SET_DICTIONARY_HOOK()` and +`DEFLATE_GET_DICTIONARY_HOOK()` macros. `deflateResetKeep()` and `inflateResetKeep()` update the DFLTCC parameter block using `DEFLATE_RESET_KEEP_HOOK()` and @@ -92,9 +91,14 @@ and `DEFLATE_NEED_CONSERVATIVE_BOUND()` macros make `deflateBound()` return the correct results for the hardware implementation. Actual compression and decompression are handled by `DEFLATE_HOOK()` and -`INFLATE_TYPEDO_HOOK()` macros. Since inflation with DFLTCC manages the -window on its own, calling `updatewindow()` is suppressed using -`INFLATE_NEED_UPDATEWINDOW()` macro. +`INFLATE_TYPEDO_HOOK()` macros. + +Software and hardware inflate window formats don't match, therefore, +`inflateSetDictionary()` and `inflateGetDictionary()` need special handling, +which is triggered using `INFLATE_SET_DICTIONARY_HOOK()` and +`INFLATE_GET_DICTIONARY_HOOK()` macros. Furthermore, calling +`window_output_flush()` is suppressed using +`INFLATE_NEED_WINDOW_OUTPUT_FLUSH()` macro. In addition to compression, DFLTCC computes CRC-32 and Adler-32 checksums, therefore, whenever it's used, software checksumming is diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index 0a65aa7e8e..519f97ea59 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -343,46 +343,13 @@ int Z_INTERNAL dfltcc_can_set_reproducible(PREFIX3(streamp) strm, int reproducib return reproducible != state->reproducible && !dfltcc_was_deflate_used(strm); } -/* - Preloading history. -*/ -static void append_history(struct dfltcc_param_v0 *param, unsigned char *history, const unsigned char *buf, uInt count) { - size_t offset; - size_t n; - - /* Do not use more than 32K */ - if (count > HB_SIZE) { - buf += count - HB_SIZE; - count = HB_SIZE; - } - offset = (param->ho + param->hl) % HB_SIZE; - if (offset + count <= HB_SIZE) - /* Circular history buffer does not wrap - copy one chunk */ - memcpy(history + offset, buf, count); - else { - /* Circular history buffer wraps - copy two chunks */ - n = HB_SIZE - offset; - memcpy(history + offset, buf, n); - memcpy(history, buf + n, count - n); - } - n = param->hl + count; - if (n <= HB_SIZE) - /* All history fits into buffer - no need to discard anything */ - param->hl = n; - else { - /* History does not fit into buffer - discard extra bytes */ - param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE; - param->hl = HB_SIZE; - } -} - int Z_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length) { deflate_state *state = (deflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; - append_history(param, state->window, dictionary, dict_length); + dfltcc_append_history(param, state->window, dictionary, dict_length); state->strstart = 1; /* Add FDICT to zlib header */ state->block_start = state->strstart; /* Make deflate_stored happy */ return Z_OK; @@ -393,17 +360,6 @@ int Z_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned cha struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; - if (dictionary) { - if (param->ho + param->hl <= HB_SIZE) - /* Circular history buffer does not wrap - copy one chunk */ - memcpy(dictionary, state->window + param->ho, param->hl); - else { - /* Circular history buffer wraps - copy two chunks */ - memcpy(dictionary, state->window + param->ho, HB_SIZE - param->ho); - memcpy(dictionary + HB_SIZE - param->ho, state->window, param->ho + param->hl - HB_SIZE); - } - } - if (dict_length) - *dict_length = param->hl; + dfltcc_get_history(param, state->window, dictionary, dict_length); return Z_OK; } diff --git a/arch/s390/dfltcc_detail.h b/arch/s390/dfltcc_detail.h index 4ec03f8097..5fb8f47c52 100644 --- a/arch/s390/dfltcc_detail.h +++ b/arch/s390/dfltcc_detail.h @@ -197,3 +197,50 @@ struct dfltcc_state { #define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1)) #define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8))) + +static inline void dfltcc_get_history(struct dfltcc_param_v0 *param, const unsigned char *history, + unsigned char *buf, uInt *count) { + if (buf) { + if (param->ho + param->hl <= HB_SIZE) + /* Circular history buffer does not wrap - copy one chunk */ + memcpy(buf, history + param->ho, param->hl); + else { + /* Circular history buffer wraps - copy two chunks */ + memcpy(buf, history + param->ho, HB_SIZE - param->ho); + memcpy(buf + HB_SIZE - param->ho, history, param->ho + param->hl - HB_SIZE); + } + } + if (count) + *count = param->hl; +} + +static inline void dfltcc_append_history(struct dfltcc_param_v0 *param, unsigned char *history, + const unsigned char *buf, uInt count) { + size_t offset; + size_t n; + + /* Do not use more than 32K */ + if (count > HB_SIZE) { + buf += count - HB_SIZE; + count = HB_SIZE; + } + offset = (param->ho + param->hl) % HB_SIZE; + if (offset + count <= HB_SIZE) + /* Circular history buffer does not wrap - copy one chunk */ + memcpy(history + offset, buf, count); + else { + /* Circular history buffer wraps - copy two chunks */ + n = HB_SIZE - offset; + memcpy(history + offset, buf, n); + memcpy(history, buf + n, count - n); + } + n = param->hl + count; + if (n <= HB_SIZE) + /* All history fits into buffer - no need to discard anything */ + param->hl = n; + else { + /* History does not fit into buffer - discard extra bytes */ + param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE; + param->hl = HB_SIZE; + } +} diff --git a/arch/s390/dfltcc_inflate.c b/arch/s390/dfltcc_inflate.c index 253506466d..9b1497d2b8 100644 --- a/arch/s390/dfltcc_inflate.c +++ b/arch/s390/dfltcc_inflate.c @@ -83,8 +83,6 @@ dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush /* Translate stream to parameter block */ param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32; param->sbb = state->bits; - param->hl = state->whave; /* Software and hardware history formats match */ - param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1); if (param->hl) param->nt = 0; /* Honor history for the first block */ param->cv = state->flags ? ZSWAP32(state->check) : state->check; @@ -98,8 +96,6 @@ dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); state->last = cc == DFLTCC_CC_OK; state->bits = param->sbb; - state->whave = param->hl; - state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1); state->check = state->flags ? ZSWAP32(param->cv) : param->cv; if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) { /* Report an error if stream is corrupted */ @@ -122,6 +118,8 @@ int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm) { int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); + struct dfltcc_param_v0 *param = &dfltcc_state->param; + uInt count; if (!dfltcc_can_inflate(strm)) return 0; @@ -133,5 +131,29 @@ int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm) { return 1; /* DFLTCC was not used yet - decompress in software */ memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); + /* Convert window from hardware to software format. Use its second part as scratch space. */ + dfltcc_get_history(param, state->window, state->window + state->wsize, &count); + state->whave = count; + state->wnext = 0; + memcpy(state->window + state->wsize - state->whave, state->window + state->wsize, state->whave); return 0; } + +int Z_INTERNAL dfltcc_inflate_set_dictionary(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length) { + struct inflate_state *state = (struct inflate_state *)strm->state; + struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); + struct dfltcc_param_v0 *param = &dfltcc_state->param; + + dfltcc_append_history(param, state->window, dictionary, dict_length); + state->havedict = 1; + return Z_OK; +} + +int Z_INTERNAL dfltcc_inflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt *dict_length) { + struct inflate_state *state = (struct inflate_state *)strm->state; + struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); + struct dfltcc_param_v0 *param = &dfltcc_state->param; + + dfltcc_get_history(param, state->window, dictionary, dict_length); + return Z_OK; +} diff --git a/arch/s390/dfltcc_inflate.h b/arch/s390/dfltcc_inflate.h index fc8a000f7b..4b68b7048e 100644 --- a/arch/s390/dfltcc_inflate.h +++ b/arch/s390/dfltcc_inflate.h @@ -12,6 +12,8 @@ typedef enum { dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret); int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm); int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm); +int Z_INTERNAL dfltcc_inflate_set_dictionary(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length); +int Z_INTERNAL dfltcc_inflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length); #define INFLATE_RESET_KEEP_HOOK(strm) \ dfltcc_reset((strm), sizeof(struct inflate_state)) @@ -34,7 +36,7 @@ int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm); #define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm))) -#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm))) +#define INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) (!dfltcc_can_inflate((strm))) #define INFLATE_MARK_HOOK(strm) \ do { \ @@ -46,4 +48,16 @@ int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm); if (dfltcc_was_inflate_used((strm))) return Z_STREAM_ERROR; \ } while (0) +#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \ + do { \ + if (dfltcc_can_inflate((strm))) \ + return dfltcc_inflate_set_dictionary((strm), (dict), (dict_len)); \ + } while (0) + +#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \ + do { \ + if (dfltcc_can_inflate((strm))) \ + return dfltcc_inflate_get_dictionary((strm), (dict), (dict_len)); \ + } while (0) + #endif diff --git a/deflate.c b/deflate.c index 79fa85dbc4..bb20a7d7a6 100644 --- a/deflate.c +++ b/deflate.c @@ -82,7 +82,7 @@ const char PREFIX(deflate_copyright)[] = " deflate 1.2.11.f Copyright 1995-2016 /* Invoked at the beginning of deflateParams(). Useful for updating arch-specific compression parameters. */ # define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) do {} while (0) /* Returns whether the last deflate(flush) operation did everything it's supposed to do. */ -# define DEFLATE_DONE(strm, flush) 1 +# define DEFLATE_DONE(strm, flush) 1 /* Adjusts the upper bound on compressed data length based on compression parameters and uncompressed data length. * Useful when arch-specific deflation code behaves differently than regular zlib-ng algorithms. */ # define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen) do {} while (0) diff --git a/inflate.c b/inflate.c index cca8df67a7..1abb0290f6 100644 --- a/inflate.c +++ b/inflate.c @@ -912,11 +912,13 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { break; case CHECK: - RESTORE(); - window_output_flush(strm); - LOAD(); - if (strm->avail_out == 0 && state->wnext) - goto inf_leave; + if (INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm)) { + RESTORE(); + window_output_flush(strm); + LOAD(); + if (strm->avail_out == 0 && state->wnext) + goto inf_leave; + } if (state->wrap) { NEEDBITS(32); out -= left; @@ -982,7 +984,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { inf_leave: RESTORE(); - if (strm->avail_out && state->wnext) + if (INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) && strm->avail_out && state->wnext) window_output_flush(strm); in -= strm->avail_in; @@ -1017,13 +1019,12 @@ int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *di /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + INFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ state = (struct inflate_state *)strm->state; /* copy dictionary */ - if (state->whave && dictionary != NULL) { - memcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); - memcpy(dictionary + state->whave - state->wnext, state->window, state->wnext); - } + if (state->whave && dictionary != NULL) + memcpy(dictionary, state->window + state->wsize - state->whave, state->whave); if (dictLength != NULL) *dictLength = state->whave; return Z_OK; @@ -1032,7 +1033,7 @@ int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *di int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) { struct inflate_state *state; unsigned long dictid, dict_copy, hist_copy; - const unsigned char *dict_from, *hist_from; + const unsigned char *dict_from; unsigned char *dict_to, *hist_to; int ret; @@ -1055,6 +1056,8 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8 Tracec(state->wnext != 0, (stderr, "Setting dictionary with unflushed output")); + INFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ + /* copy dictionary to window and amend if necessary */ dict_from = dictionary; dict_copy = dictLength; @@ -1064,14 +1067,13 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8 } dict_to = state->window + state->wsize - dict_copy; - hist_from = state->window + state->wsize - state->whave; hist_copy = state->wsize - dict_copy; if (hist_copy > state->whave) hist_copy = state->whave; hist_to = dict_to - hist_copy; if (hist_copy) - memcpy(hist_to, hist_from, hist_copy); + memcpy(hist_to, state->window + state->wsize - hist_copy, hist_copy); if (dict_copy) memcpy(dict_to, dict_from, dict_copy); diff --git a/inflate_p.h b/inflate_p.h index b2e8d8de2f..464b04fdfe 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -27,12 +27,17 @@ # define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0) /* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */ # define INFLATE_NEED_CHECKSUM(strm) 1 -/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */ -# define INFLATE_NEED_UPDATEWINDOW(strm) 1 +/* Returns whether zlib-ng should flush the window to the output buffer. + Set to 0 if arch-specific inflation code already does that. */ +# define INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) 1 /* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */ # define INFLATE_MARK_HOOK(strm) do {} while (0) /* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */ -#define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) +# define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) +/* Invoked at the beginning of inflateSetDictionary(). Useful for checking arch-specific window data. */ +# define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) +/* Invoked at the beginning of inflateGetDictionary(). Useful for adjusting arch-specific window data. */ +# define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) #endif From d87543910abc7fad7097a29c052aac6e6860f792 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 27 Oct 2021 17:58:21 -0700 Subject: [PATCH 158/798] Fixed inflateGetDictionary length check may include bytes added by last call to inflate. --- test/example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example.c b/test/example.c index 2a03328432..6324a33c60 100644 --- a/test/example.c +++ b/test/example.c @@ -551,7 +551,7 @@ void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *unc err = PREFIX(inflateGetDictionary)(&d_stream, NULL, &check_dictionary_len); CHECK_ERR(err, "inflateGetDictionary"); #ifndef S390_DFLTCC_INFLATE - if (check_dictionary_len != sizeof(dictionary)) + if (check_dictionary_len < sizeof(dictionary)) error("bad dictionary length\n"); #endif From 330445c51b95cc6c8f1dae28876e9992cbc58912 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 14 Nov 2021 20:58:01 -0800 Subject: [PATCH 159/798] Reuse adler32_len_64 in adler32_c. --- adler32.c | 25 +------------------------ adler32_p.h | 8 ++++++++ 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/adler32.c b/adler32.c index 7b245fc849..499adbb60b 100644 --- a/adler32.c +++ b/adler32.c @@ -51,30 +51,7 @@ Z_INTERNAL uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t l } /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ -#ifdef UNROLL_MORE - while (len >= 16) { - len -= 16; - DO16(adler, sum2, buf); - buf += 16; -#else - while (len >= 8) { - len -= 8; - DO8(adler, sum2, buf, 0); - buf += 8; -#endif - } - while (len) { - --len; - adler += *buf++; - sum2 += adler; - } - adler %= BASE; - sum2 %= BASE; - } - - /* return recombined sums */ - return adler | (sum2 << 16); + return adler32_len_64(adler, buf, len, sum2); } #ifdef ZLIB_COMPAT diff --git a/adler32_p.h b/adler32_p.h index adcc79f01e..1adc1ccb0a 100644 --- a/adler32_p.h +++ b/adler32_p.h @@ -34,14 +34,22 @@ static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, } adler %= BASE; sum2 %= BASE; /* only added so many BASE's */ + /* return recombined sums */ return adler | (sum2 << 16); } static inline uint32_t adler32_len_64(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) { +#ifdef UNROLL_MORE while (len >= 16) { len -= 16; DO16(adler, sum2, buf); buf += 16; +#else + while (len >= 8) { + len -= 8; + DO8(adler, sum2, buf, 0); + buf += 8; +#endif } /* Process tail (len < 16). */ return adler32_len_16(adler, buf, len, sum2); From 00fa3d48d3fe8ba4f86cbc5d0895998b8cd54c95 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sat, 23 Oct 2021 12:38:12 -0400 Subject: [PATCH 160/798] Use immediate variant of shift instruction Since this is constant, anyway, we may as well use the variant that doesn't add vector register pressure, has better ILP opportunities, and has shorter instruction latency. --- arch/x86/adler32_avx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/x86/adler32_avx.c b/arch/x86/adler32_avx.c index 3d30d4d783..db43446fad 100644 --- a/arch/x86/adler32_avx.c +++ b/arch/x86/adler32_avx.c @@ -50,9 +50,6 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; __m256i dot3v = _mm256_load_si256((__m256i*)dot3); - // We will need to multiply by - char ALIGNED_(32) shift[16] = {5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - __m128i shiftv = _mm_load_si128((__m128i*)shift); while (len >= 32) { __m256i vs1 = _mm256_load_si256((__m256i*)s1); @@ -77,7 +74,7 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); vs1 = _mm256_add_epi32(vsum1, vs1); __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); - vs1_0 = _mm256_sll_epi32(vs1_0, shiftv); + vs1_0 = _mm256_slli_epi32(vs1_0, 5); vsum2 = _mm256_add_epi32(vsum2, vs2); vs2 = _mm256_add_epi32(vsum2, vs1_0); vs1_0 = vs1; From 9a1109bd77159c43150eb32c5e09e16293da332d Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 24 Oct 2021 19:24:53 -0400 Subject: [PATCH 161/798] Minor efficiency improvement This now leverages the broadcasting instrinsics with an AND mask to load up the registers. Additionally, there's a minor efficiency boost here by casting up to 64 bit precision (by means of register aliasing) so that the modulo can be safely deferred until the write back to the full sums. The "write" back to the stack here is actually optimized out by GCC and turned into a write directly to a 32 bit GPR for each of the 8 elements. This much is not new, but now, since we don't have to do a modulus with the BASE value, we can bypass 8 64 bit multiplications, shifts, and subtractions while in those registers. I tried to do a horizontal reduction sum on the 8 64 bit elements since the vpextract* set of instructions aren't exactly low latency, however to do this safely (no overflow) it requires 2 128 bit register extractions, 8 vpmovsxdq to bring the things up to 64 bit precision, some shuffles, more 128 bit extractions to get around the 128 bit lane requirement of the shuffles, and finally a trip to a GPR and back to do the modulus on the scalar value. This method could have been more efficient if there were an inexpensive 64 bit horizontal addition instruction for AVX, but there isn't. To test this, I wrote a pretty basic benchmark using Python's zlib bindings on a huge set of random data, carefully timing only the checksum bits. Invoking perf stat from within the python process after the RNG shows a lower average number of cycles to complete and a shorter runtime. --- arch/x86/adler32_avx.c | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/x86/adler32_avx.c b/arch/x86/adler32_avx.c index db43446fad..183a4d6f14 100644 --- a/arch/x86/adler32_avx.c +++ b/arch/x86/adler32_avx.c @@ -33,27 +33,22 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); - uint32_t ALIGNED_(32) s1[8], s2[8]; + __m256i vsMask = _mm256_setr_epi32(0, 0, 0, 0, 0, 0, 0, -1); + __m256i vs1 = _mm256_set1_epi32(adler); + __m256i vs2 = _mm256_set1_epi32(sum2); + vs1 = _mm256_and_si256(vs1, vsMask); + vs2 = _mm256_and_si256(vs2, vsMask); - memset(s1, 0, sizeof(s1)); s1[7] = adler; // TODO: would a masked load be faster? - memset(s2, 0, sizeof(s2)); s2[7] = sum2; - - char ALIGNED_(32) dot1[32] = \ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m256i dot1v = _mm256_load_si256((__m256i*)dot1); - char ALIGNED_(32) dot2[32] = \ - {32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, - 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; - __m256i dot2v = _mm256_load_si256((__m256i*)dot2); - short ALIGNED_(32) dot3[16] = \ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m256i dot3v = _mm256_load_si256((__m256i*)dot3); + const __m256i dot1v = _mm256_set1_epi8(1); + const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, + 26, 25, 24, 23, 22, 21, + 20, 19, 18, 17, 16, 15, + 14, 13, 12, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1); + __m256i dot3v = _mm256_set1_epi16(1); while (len >= 32) { - __m256i vs1 = _mm256_load_si256((__m256i*)s1); - __m256i vs2 = _mm256_load_si256((__m256i*)s2); __m256i vs1_0 = vs1; int k = (len < NMAX ? (int)len : NMAX); @@ -88,15 +83,20 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ _mm256_store_si256((__m256i*)s1_unpack, vs1); _mm256_store_si256((__m256i*)s2_unpack, vs2); - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + - (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); - adler %= BASE; - s1[7] = adler; + uint64_t adler64 = ((uint64_t)s1_unpack[0] + (uint64_t)s1_unpack[1] + (uint64_t)s1_unpack[2] + + (uint64_t)s1_unpack[3] + (uint64_t)s1_unpack[4] + (uint64_t)s1_unpack[5] + + (uint64_t)s1_unpack[6] + (uint64_t)s1_unpack[7]) % BASE; + + uint64_t sum264 = ((uint64_t)s2_unpack[0] + (uint64_t)s2_unpack[1] + (uint64_t)s2_unpack[2] + + (uint64_t)s2_unpack[3] + (uint64_t)s2_unpack[4] + (uint64_t)s2_unpack[5] + + (uint64_t)s2_unpack[6] + (uint64_t)s2_unpack[7]) % BASE; - sum2 = (s2_unpack[0] % BASE) + (s2_unpack[1] % BASE) + (s2_unpack[2] % BASE) + (s2_unpack[3] % BASE) + - (s2_unpack[4] % BASE) + (s2_unpack[5] % BASE) + (s2_unpack[6] % BASE) + (s2_unpack[7] % BASE); - sum2 %= BASE; - s2[7] = sum2; + adler = (uint32_t)adler64; + sum2 = (uint32_t)sum264; + vs1 = _mm256_set1_epi32(adler); + vs2 = _mm256_set1_epi32(sum2); + vs1 = _mm256_and_si256(vs1, vsMask); + vs2 = _mm256_and_si256(vs2, vsMask); } /* Process tail (len < 16). */ From 2a9879494b6fc0d9d09686e029f72f304496211c Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 24 Oct 2021 17:44:33 -0400 Subject: [PATCH 162/798] Have horizontal sum here, decent wins --- arch/x86/adler32_avx.c | 113 +++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/arch/x86/adler32_avx.c b/arch/x86/adler32_avx.c index 183a4d6f14..954a8a73a3 100644 --- a/arch/x86/adler32_avx.c +++ b/arch/x86/adler32_avx.c @@ -9,11 +9,22 @@ #include "../../zutil.h" #include "../../adler32_p.h" +#include #include #ifdef X86_AVX2_ADLER32 +/* 64 bit horizontal sum, adapted from Agner Fog's + * vector library. */ +static inline uint64_t hsum(__m256i x) +{ + __m256i sum1 = _mm256_shuffle_epi32(x, 0x0E); + __m256i sum2 = _mm256_add_epi64(x, sum1); + __m128i sum3 = _mm256_extracti128_si256(sum2, 1); + return _mm_cvtsi128_si64(_mm_add_epi64(_mm256_castsi256_si128(sum2), sum3)); +} + Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t sum2; @@ -33,20 +44,18 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); - __m256i vsMask = _mm256_setr_epi32(0, 0, 0, 0, 0, 0, 0, -1); + /* If we could shift over 128 bit lanes, a broadcast + shift would be better */ + const __m256i sMask = _mm256_setr_epi32(0, 0, 0, 0, 0, 0, 0, -1); __m256i vs1 = _mm256_set1_epi32(adler); __m256i vs2 = _mm256_set1_epi32(sum2); - vs1 = _mm256_and_si256(vs1, vsMask); - vs2 = _mm256_and_si256(vs2, vsMask); + vs1 = _mm256_and_si256(vs1, sMask); + vs2 = _mm256_and_si256(vs2, sMask); const __m256i dot1v = _mm256_set1_epi8(1); - const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, - 26, 25, 24, 23, 22, 21, - 20, 19, 18, 17, 16, 15, - 14, 13, 12, 11, 10, 9, - 8, 7, 6, 5, 4, 3, 2, 1); - __m256i dot3v = _mm256_set1_epi16(1); - + const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m256i dot3v = _mm256_set1_epi16(1); while (len >= 32) { __m256i vs1_0 = vs1; @@ -75,28 +84,68 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ vs1_0 = vs1; } - // At this point, we have partial sums stored in vs1 and vs2. There are AVX512 instructions that - // would allow us to sum these quickly (VP4DPWSSD). For now, just unpack and move on. - uint32_t ALIGNED_(32) s1_unpack[8]; - uint32_t ALIGNED_(32) s2_unpack[8]; - - _mm256_store_si256((__m256i*)s1_unpack, vs1); - _mm256_store_si256((__m256i*)s2_unpack, vs2); - - uint64_t adler64 = ((uint64_t)s1_unpack[0] + (uint64_t)s1_unpack[1] + (uint64_t)s1_unpack[2] + - (uint64_t)s1_unpack[3] + (uint64_t)s1_unpack[4] + (uint64_t)s1_unpack[5] + - (uint64_t)s1_unpack[6] + (uint64_t)s1_unpack[7]) % BASE; - - uint64_t sum264 = ((uint64_t)s2_unpack[0] + (uint64_t)s2_unpack[1] + (uint64_t)s2_unpack[2] + - (uint64_t)s2_unpack[3] + (uint64_t)s2_unpack[4] + (uint64_t)s2_unpack[5] + - (uint64_t)s2_unpack[6] + (uint64_t)s2_unpack[7]) % BASE; - - adler = (uint32_t)adler64; - sum2 = (uint32_t)sum264; - vs1 = _mm256_set1_epi32(adler); - vs2 = _mm256_set1_epi32(sum2); - vs1 = _mm256_and_si256(vs1, vsMask); - vs2 = _mm256_and_si256(vs2, vsMask); + /* The compiler is generating the following sequence for this integer modulus + * when done the scalar way, in GPRs: + mov $0x80078071,%edi // move magic constant into 32 bit register %edi + ... + vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi + mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax + imul %rdi,%rsi // do a signed multiplication with magic constant and vector element + shr $0x2f,%rsi // shift right by 47 + imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 + sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above + ... + // repeats for each element with vpextract instructions + + This is tricky with AVX2 for a number of reasons: + 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there + 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate + back down to 32 bit precision later (there is in AVX512) + 3.) Full width integer multiplications aren't cheap + */ + + // At this point, we have partial sums stored in vs1 and vs2. There are AVX512 instructions that + // would allow us to sum these quickly (VP4DPWSSD). For now, just unpack and move on. + /*uint32_t ALIGNED_(32) s1_unpack[8]; + uint32_t ALIGNED_(32) s2_unpack[8]; + + _mm256_store_si256((__m256i*)s1_unpack, vs1); + _mm256_store_si256((__m256i*)s2_unpack, vs2); + + + adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + + (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE);*/ + + /* Will translate to nops */ + __m128i s1lo = _mm256_castsi256_si128(vs1); + __m128i s2lo = _mm256_castsi256_si128(vs2); + + __m128i s1hi = _mm256_extracti128_si256(vs1, 1); + __m128i s2hi = _mm256_extracti128_si256(vs2, 1); + + /* Convert up to 64 bit precision to prevent overflow */ + __m256i s1lo256 = _mm256_cvtepi32_epi64(s1lo); + __m256i s1hi256 = _mm256_cvtepi32_epi64(s1hi); + __m256i s2lo256 = _mm256_cvtepi32_epi64(s2lo); + __m256i s2hi256 = _mm256_cvtepi32_epi64(s2hi); + + /* sum vectors in existing lanes */ + __m256i s1Sum = _mm256_add_epi64(s1lo256, s1hi256); + __m256i s2Sum = _mm256_add_epi64(s2lo256, s2hi256); + + /* In AVX2-land, this trip through GPRs will probably + * be unvoidable, as there's no cheap and easy conversion + * from 64 bit integer to 32 bit. This casting to 32 bit + * is cheap through GPRs (just register aliasing), and safe, + * as our base is significantly smaller than UINT32_MAX */ + adler = (uint32_t)(hsum(s1Sum) % BASE); + sum2 = (uint32_t)(hsum(s2Sum) % BASE); + + vs1 = _mm256_set1_epi32(adler); + vs1 = _mm256_and_si256(vs1, sMask); + + vs2 = _mm256_set1_epi32(sum2); + vs2 = _mm256_and_si256(vs2, sMask); } /* Process tail (len < 16). */ From 1083c8e7132a010212ec490932e6f1964da58cda Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Thu, 2 Dec 2021 17:05:55 -0500 Subject: [PATCH 163/798] Made this work on 32 bit compilations For some reason the movq instruction from a 128 bit register to a 64 bit GPR is not supported in 32 bit code. A simple workaround seems to be to invoke movl if compiling with -m32. Also addressing some style nits. --- arch/x86/adler32_avx.c | 142 ++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 72 deletions(-) diff --git a/arch/x86/adler32_avx.c b/arch/x86/adler32_avx.c index 954a8a73a3..f22730bb1b 100644 --- a/arch/x86/adler32_avx.c +++ b/arch/x86/adler32_avx.c @@ -9,20 +9,24 @@ #include "../../zutil.h" #include "../../adler32_p.h" -#include #include #ifdef X86_AVX2_ADLER32 -/* 64 bit horizontal sum, adapted from Agner Fog's - * vector library. */ -static inline uint64_t hsum(__m256i x) -{ +/* 64 bit horizontal sum, adapted from Agner Fog's vector library. */ +static inline uint64_t hsum(__m256i x) { __m256i sum1 = _mm256_shuffle_epi32(x, 0x0E); __m256i sum2 = _mm256_add_epi64(x, sum1); __m128i sum3 = _mm256_extracti128_si256(sum2, 1); +#if defined(__x86_64__) || defined(_M_X64) return _mm_cvtsi128_si64(_mm_add_epi64(_mm256_castsi256_si128(sum2), sum3)); +#else + __m128i ret_vec = _mm_add_epi64(_mm256_castsi256_si128(sum2), sum3); + uint64_t ret_val; + _mm_storel_epi64((__m128i*)&ret_val, ret_vec); + return ret_val; +#endif } Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len) { @@ -44,17 +48,15 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); - /* If we could shift over 128 bit lanes, a broadcast + shift would be better */ - const __m256i sMask = _mm256_setr_epi32(0, 0, 0, 0, 0, 0, 0, -1); + const __m256i vs_mask = _mm256_setr_epi32(0, 0, 0, 0, 0, 0, 0, -1); __m256i vs1 = _mm256_set1_epi32(adler); __m256i vs2 = _mm256_set1_epi32(sum2); - vs1 = _mm256_and_si256(vs1, sMask); - vs2 = _mm256_and_si256(vs2, sMask); + vs1 = _mm256_and_si256(vs1, vs_mask); + vs2 = _mm256_and_si256(vs2, vs_mask); const __m256i dot1v = _mm256_set1_epi8(1); - const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, - 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, - 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); const __m256i dot3v = _mm256_set1_epi16(1); while (len >= 32) { @@ -67,7 +69,7 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ while (k >= 32) { /* vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + vs2 = sum2 + 32 vs1 + sum( (32-i+1) c[i] ) */ __m256i vbuf = _mm256_loadu_si256((__m256i*)buf); buf += 32; @@ -86,66 +88,62 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ /* The compiler is generating the following sequence for this integer modulus * when done the scalar way, in GPRs: - mov $0x80078071,%edi // move magic constant into 32 bit register %edi - ... - vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi - mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax - imul %rdi,%rsi // do a signed multiplication with magic constant and vector element - shr $0x2f,%rsi // shift right by 47 - imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 - sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above - ... - // repeats for each element with vpextract instructions - - This is tricky with AVX2 for a number of reasons: - 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there - 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate - back down to 32 bit precision later (there is in AVX512) - 3.) Full width integer multiplications aren't cheap - */ - - // At this point, we have partial sums stored in vs1 and vs2. There are AVX512 instructions that - // would allow us to sum these quickly (VP4DPWSSD). For now, just unpack and move on. - /*uint32_t ALIGNED_(32) s1_unpack[8]; - uint32_t ALIGNED_(32) s2_unpack[8]; - - _mm256_store_si256((__m256i*)s1_unpack, vs1); - _mm256_store_si256((__m256i*)s2_unpack, vs2); - - - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + - (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE);*/ - - /* Will translate to nops */ - __m128i s1lo = _mm256_castsi256_si128(vs1); - __m128i s2lo = _mm256_castsi256_si128(vs2); - - __m128i s1hi = _mm256_extracti128_si256(vs1, 1); - __m128i s2hi = _mm256_extracti128_si256(vs2, 1); - - /* Convert up to 64 bit precision to prevent overflow */ - __m256i s1lo256 = _mm256_cvtepi32_epi64(s1lo); - __m256i s1hi256 = _mm256_cvtepi32_epi64(s1hi); - __m256i s2lo256 = _mm256_cvtepi32_epi64(s2lo); - __m256i s2hi256 = _mm256_cvtepi32_epi64(s2hi); - - /* sum vectors in existing lanes */ - __m256i s1Sum = _mm256_add_epi64(s1lo256, s1hi256); - __m256i s2Sum = _mm256_add_epi64(s2lo256, s2hi256); - - /* In AVX2-land, this trip through GPRs will probably - * be unvoidable, as there's no cheap and easy conversion - * from 64 bit integer to 32 bit. This casting to 32 bit - * is cheap through GPRs (just register aliasing), and safe, - * as our base is significantly smaller than UINT32_MAX */ - adler = (uint32_t)(hsum(s1Sum) % BASE); - sum2 = (uint32_t)(hsum(s2Sum) % BASE); - - vs1 = _mm256_set1_epi32(adler); - vs1 = _mm256_and_si256(vs1, sMask); + + adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + + (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); + + mov $0x80078071,%edi // move magic constant into 32 bit register %edi + ... + vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi + mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax + imul %rdi,%rsi // do a signed multiplication with magic constant and vector element + shr $0x2f,%rsi // shift right by 47 + imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 + sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above + ... + // repeats for each element with vpextract instructions + + This is tricky with AVX2 for a number of reasons: + 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there + 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate + back down to 32 bit precision later (there is in AVX512) + 3.) Full width integer multiplications aren't cheap + + We can, however, cast up to 64 bit precision on all 8 integers at once, and do a relatively + cheap sequence for horizontal sums. Then, we simply do the integer modulus on the resulting + 64 bit GPR, on a scalar value + */ + - vs2 = _mm256_set1_epi32(sum2); - vs2 = _mm256_and_si256(vs2, sMask); + /* Will translate to nops */ + __m128i s1lo = _mm256_castsi256_si128(vs1); + __m128i s2lo = _mm256_castsi256_si128(vs2); + + /* Requires vextracti128 */ + __m128i s1hi = _mm256_extracti128_si256(vs1, 1); + __m128i s2hi = _mm256_extracti128_si256(vs2, 1); + + /* Convert up to 64 bit precision to prevent overflow */ + __m256i s1lo256 = _mm256_cvtepi32_epi64(s1lo); + __m256i s1hi256 = _mm256_cvtepi32_epi64(s1hi); + __m256i s2lo256 = _mm256_cvtepi32_epi64(s2lo); + __m256i s2hi256 = _mm256_cvtepi32_epi64(s2hi); + + /* Sum vectors in existing lanes */ + __m256i s1_sum = _mm256_add_epi64(s1lo256, s1hi256); + __m256i s2_sum = _mm256_add_epi64(s2lo256, s2hi256); + + /* In AVX2-land, this trip through GPRs will probably be unvoidable, as there's no cheap and easy + * conversion from 64 bit integer to 32 bit. This casting to 32 bit is cheap through GPRs + * (just register aliasing), and safe, as our base is significantly smaller than UINT32_MAX */ + adler = (uint32_t)(hsum(s1_sum) % BASE); + sum2 = (uint32_t)(hsum(s2_sum) % BASE); + + vs1 = _mm256_set1_epi32(adler); + vs2 = _mm256_set1_epi32(sum2); + + vs1 = _mm256_and_si256(vs1, vs_mask); + vs2 = _mm256_and_si256(vs2, vs_mask); } /* Process tail (len < 16). */ From 20f8dc06182a91e497c919a6275416370b5ffe06 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sat, 4 Dec 2021 08:25:17 +0200 Subject: [PATCH 164/798] Workaround for installation failure of wine32. --- .github/workflows/cmake.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 97078fa575..5662ed5d8f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -408,6 +408,7 @@ jobs: if: runner.os == 'Linux' && matrix.packages run: | sudo dpkg --add-architecture i386 # Required for wine32 + sudo apt-add-repository ppa:ondrej/php -y sudo apt-get update sudo apt-get install -y ${{ matrix.packages }} From ef56e89749066db27a751a899444da22a19bcc0b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 7 Dec 2021 15:52:05 -0500 Subject: [PATCH 165/798] Don't overwrite adler32 hash with crc32 hash. #1066 --- inflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inflate.c b/inflate.c index 1abb0290f6..38faefe2c9 100644 --- a/inflate.c +++ b/inflate.c @@ -926,7 +926,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->total += out; if (INFLATE_NEED_CHECKSUM(strm) && strm->total_out) { - if (state->wrap & 2) + if (state->flags) strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold); } out = left; From 6f8a474c5cdf8ef332f5602c0cab3447a23d8304 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 7 Dec 2021 16:24:26 -0500 Subject: [PATCH 166/798] Added unit test to ensure that inflate with adler32 hash works on previously failed test case. --- CMakeLists.txt | 1 + test/inflate_adler32.c | 59 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 test/inflate_adler32.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 26558fd325..b3befedb71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1371,6 +1371,7 @@ if(ZLIB_ENABLE_TESTS) add_simple_test_executable(deflate_quick_bi_valid) add_simple_test_executable(deflate_quick_block_open) + add_simple_test_executable(inflate_adler32) add_simple_test_executable(hash_head_0) endif() diff --git a/test/inflate_adler32.c b/test/inflate_adler32.c new file mode 100644 index 0000000000..3def08e42d --- /dev/null +++ b/test/inflate_adler32.c @@ -0,0 +1,59 @@ +/* GH-1066 - inflate small amount of data and validate with adler32 checksum. */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include + +const char* original = "The quick brown fox jumped over the lazy dog"; + +z_const unsigned char compressed[] = { + 0x78, 0x9c, 0x0b, 0xc9, 0x48, 0x55, 0x28, 0x2c, 0xcd, 0x4c, 0xce, 0x56, 0x48, + 0x2a, 0xca, 0x2f, 0xcf, 0x53, 0x48, 0xcb, 0xaf, 0x50, 0xc8, 0x2a, 0xcd, 0x2d, + 0x48, 0x4d, 0x51, 0xc8, 0x2f, 0x4b, 0x2d, 0x52, 0x28, 0xc9, 0x48, 0x55, 0xc8, + 0x49, 0xac, 0xaa, 0x54, 0x48, 0xc9, 0x4f, 0x07, 0x00, 0x6b, 0x93, 0x10, 0x30 +}; + +int main() +{ + unsigned char uncompressed[1024]; + PREFIX3(stream) strm; + + memset(&strm, 0, sizeof(strm)); + + int ret = PREFIX(inflateInit2)(&strm, 32 + MAX_WBITS); + if (ret != Z_OK) { + fprintf(stderr, "inflateInit2() failed with code %d\n", ret); + return EXIT_FAILURE; + } + + strm.next_in = compressed; + strm.avail_in = sizeof(compressed); + strm.next_out = uncompressed; + strm.avail_out = sizeof(uncompressed); + + ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); + if (ret != Z_STREAM_END) { + fprintf(stderr, "inflate() failed with code %d\n", ret); + return EXIT_FAILURE; + } + + ret = PREFIX(inflateEnd)(&strm); + if (ret != Z_OK) { + fprintf(stderr, "inflateEnd() failed with code %d\n", ret); + return EXIT_FAILURE; + } + + if (memcmp(uncompressed, original, MIN(strm.total_out, strlen(original))) != 0) { + fprintf(stderr, "expected output does not match\n"); + return EXIT_FAILURE; + } + + return 0; +} From 5b0ffa63f22d4870ae68de38c34f7ec437e7edb1 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 7 Dec 2021 19:29:01 -0500 Subject: [PATCH 167/798] Added checks and comments to ensure that when using raw mode no checksumming takes place. --- inflate.c | 7 +++++-- inflate_p.h | 17 +++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/inflate.c b/inflate.c index 38faefe2c9..44a50e61c7 100644 --- a/inflate.c +++ b/inflate.c @@ -502,7 +502,9 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } - strm->adler = state->check = functable.crc32_fold_reset(&state->crc_fold); + /* compute crc32 checksum if not in raw mode */ + if ((state->wrap & 4) && state->flags) + strm->adler = state->check = functable.crc32_fold_reset(&state->crc_fold); state->mode = TYPE; break; #endif @@ -926,7 +928,8 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->total += out; if (INFLATE_NEED_CHECKSUM(strm) && strm->total_out) { - if (state->flags) + /* compute crc32 final value if not in raw mode */ + if ((state->wrap & 4) && state->flags) strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold); } out = left; diff --git a/inflate_p.h b/inflate_p.h index 464b04fdfe..c5ba13a0c6 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -158,15 +158,20 @@ static inline void inf_crc_copy(PREFIX3(stream) *strm, unsigned char *const dst, if (!INFLATE_NEED_CHECKSUM(strm)) return; - /* check function to use adler32() for zlib or crc32() for gzip */ + /* compute checksum if not in raw mode */ + if (state->wrap & 4) { + /* check flags to use adler32() for zlib or crc32() for gzip */ #ifdef GUNZIP - if (state->flags) - functable.crc32_fold_copy(&state->crc_fold, dst, src, len); - else + if (state->flags) + functable.crc32_fold_copy(&state->crc_fold, dst, src, len); + else #endif - { + { + memcpy(dst, src, len); + strm->adler = state->check = functable.adler32(state->check, dst, len); + } + } else { memcpy(dst, src, len); - strm->adler = state->check = functable.adler32(state->check, dst, len); } } From 839c4ec9985cc7de4a9008143b67af2f4e816153 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 13 Dec 2021 16:46:21 +0100 Subject: [PATCH 168/798] inttypes.h includes stdint.h, so only include one of them. --- arch/x86/crc32_fold_pclmulqdq.c | 2 +- crc32.c | 2 +- crc32_comb.c | 2 +- test/example.c | 3 +-- test/fuzz/checksum_fuzzer.c | 1 - test/fuzz/compress_fuzzer.c | 1 - test/fuzz/example_dict_fuzzer.c | 1 - test/fuzz/example_flush_fuzzer.c | 1 - test/fuzz/example_large_fuzzer.c | 1 - test/fuzz/example_small_fuzzer.c | 1 - test/infcover.c | 1 - test/minideflate.c | 1 - trees_emit.h | 1 - 13 files changed, 4 insertions(+), 14 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 9065298f50..0e261d4069 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -19,7 +19,7 @@ #ifdef X86_PCLMULQDQ_CRC #include "../../zutil.h" -#include +#include #include #include diff --git a/crc32.c b/crc32.c index c519d874aa..c9a81d37b0 100644 --- a/crc32.c +++ b/crc32.c @@ -11,7 +11,7 @@ #include "zbuild.h" #include "zendian.h" -#include +#include #include "deflate.h" #include "functable.h" #include "crc32_tbl.h" diff --git a/crc32_comb.c b/crc32_comb.c index 092c595d9c..fa11b9b222 100644 --- a/crc32_comb.c +++ b/crc32_comb.c @@ -10,7 +10,7 @@ */ #include "zbuild.h" -#include +#include #include "deflate.h" #include "crc32_p.h" #include "crc32_comb_tbl.h" diff --git a/test/example.c b/test/example.c index 6324a33c60..3963fc2f9f 100644 --- a/test/example.c +++ b/test/example.c @@ -15,9 +15,8 @@ #include #include -#include -#include #include +#include #define TESTFILE "foo.gz" diff --git a/test/fuzz/checksum_fuzzer.c b/test/fuzz/checksum_fuzzer.c index da9f13059c..5874bb5335 100644 --- a/test/fuzz/checksum_fuzzer.c +++ b/test/fuzz/checksum_fuzzer.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/fuzz/compress_fuzzer.c b/test/fuzz/compress_fuzzer.c index 9712e882a1..11fb19f0f3 100644 --- a/test/fuzz/compress_fuzzer.c +++ b/test/fuzz/compress_fuzzer.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/fuzz/example_dict_fuzzer.c b/test/fuzz/example_dict_fuzzer.c index da1bb06c96..65df26a646 100644 --- a/test/fuzz/example_dict_fuzzer.c +++ b/test/fuzz/example_dict_fuzzer.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/fuzz/example_flush_fuzzer.c b/test/fuzz/example_flush_fuzzer.c index 81ec7e36d5..5546a6535b 100644 --- a/test/fuzz/example_flush_fuzzer.c +++ b/test/fuzz/example_flush_fuzzer.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/fuzz/example_large_fuzzer.c b/test/fuzz/example_large_fuzzer.c index bd27a84f12..864b84126a 100644 --- a/test/fuzz/example_large_fuzzer.c +++ b/test/fuzz/example_large_fuzzer.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include diff --git a/test/fuzz/example_small_fuzzer.c b/test/fuzz/example_small_fuzzer.c index d02a812de6..a4547feaf1 100644 --- a/test/fuzz/example_small_fuzzer.c +++ b/test/fuzz/example_small_fuzzer.c @@ -4,7 +4,6 @@ #include #include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/infcover.c b/test/infcover.c index 72a4c575be..0c355aa99c 100644 --- a/test/infcover.c +++ b/test/infcover.c @@ -11,7 +11,6 @@ #undef NDEBUG #include #include -#include /* get definition of internal structure so we can mess with it (see pull()), and so we can call inflate_trees() (see cover5()) */ diff --git a/test/minideflate.c b/test/minideflate.c index ae04a29e89..36c27f9046 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -12,7 +12,6 @@ #include #include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/trees_emit.h b/trees_emit.h index c957770878..922daae509 100644 --- a/trees_emit.h +++ b/trees_emit.h @@ -7,7 +7,6 @@ #ifdef ZLIB_DEBUG # include # include -# include #endif From b1ebcc0ee988b398580bced4a90050d41ec38133 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 13 Dec 2021 16:24:20 +0100 Subject: [PATCH 169/798] Remove gz_intmax implementation, since INT_MAX is always available in modern C implementations. --- gzguts.h | 7 +------ gzlib.c | 18 ------------------ zlib-ng.map | 1 - zlib.map | 1 - zlib_name_mangling-ng.h.in | 1 - zlib_name_mangling.h.in | 1 - 6 files changed, 1 insertion(+), 28 deletions(-) diff --git a/gzguts.h b/gzguts.h index c42587470e..4e71eb4b1b 100644 --- a/gzguts.h +++ b/gzguts.h @@ -144,11 +144,6 @@ void Z_INTERNAL gz_error(gz_state *, int, const char *); /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t value -- needed when comparing unsigned to z_off64_t, which is signed (possible z_off64_t types off_t, off64_t, and long are all signed) */ -#ifdef INT_MAX -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) -#else -unsigned Z_INTERNAL gz_intmax(void); -# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) -#endif +#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) #endif /* GZGUTS_H_ */ diff --git a/gzlib.c b/gzlib.c index 490551667a..c19284035c 100644 --- a/gzlib.c +++ b/gzlib.c @@ -523,21 +523,3 @@ void Z_INTERNAL gz_error(gz_state *state, int err, const char *msg) { } (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, "%s%s%s", state->path, ": ", msg); } - -#ifndef INT_MAX -/* portably return maximum value for an int (when limits.h presumed not - available) -- we need to do this to cover cases where 2's complement not - used, since C standard permits 1's complement and sign-bit representations, - otherwise we could just use ((unsigned)-1) >> 1 */ -unsigned Z_INTERNAL gz_intmax() { - unsigned p, q; - - p = 1; - do { - q = p; - p <<= 1; - p++; - } while (p > q); - return q >> 1; -} -#endif diff --git a/zlib-ng.map b/zlib-ng.map index b0046034cf..461c2566e1 100644 --- a/zlib-ng.map +++ b/zlib-ng.map @@ -66,7 +66,6 @@ ZLIB_NG_2.0.0 { zng_zcfree; zng_z_errmsg; zng_gz_error; - zng_gz_intmax; _*; }; diff --git a/zlib.map b/zlib.map index f608f2bd51..fccc0e129d 100644 --- a/zlib.map +++ b/zlib.map @@ -15,7 +15,6 @@ ZLIB_1.2.0 { zcfree; z_errmsg; gz_error; - gz_intmax; _*; }; diff --git a/zlib_name_mangling-ng.h.in b/zlib_name_mangling-ng.h.in index 7c754fc1e6..627ed46510 100644 --- a/zlib_name_mangling-ng.h.in +++ b/zlib_name_mangling-ng.h.in @@ -48,7 +48,6 @@ #define zng_get_crc_table @ZLIB_SYMBOL_PREFIX@zng_get_crc_table #ifndef Z_SOLO # define zng_gz_error @ZLIB_SYMBOL_PREFIX@zng_gz_error -# define zng_gz_intmax @ZLIB_SYMBOL_PREFIX@zng_gz_intmax # define zng_gz_strwinerror @ZLIB_SYMBOL_PREFIX@zng_gz_strwinerror # define zng_gzbuffer @ZLIB_SYMBOL_PREFIX@zng_gzbuffer # define zng_gzclearerr @ZLIB_SYMBOL_PREFIX@zng_gzclearerr diff --git a/zlib_name_mangling.h.in b/zlib_name_mangling.h.in index 07265f3c1a..22d458b1c9 100644 --- a/zlib_name_mangling.h.in +++ b/zlib_name_mangling.h.in @@ -48,7 +48,6 @@ #define get_crc_table @ZLIB_SYMBOL_PREFIX@get_crc_table #ifndef Z_SOLO # define gz_error @ZLIB_SYMBOL_PREFIX@gz_error -# define gz_intmax @ZLIB_SYMBOL_PREFIX@gz_intmax # define gz_strwinerror @ZLIB_SYMBOL_PREFIX@gz_strwinerror # define gzbuffer @ZLIB_SYMBOL_PREFIX@gzbuffer # define gzclearerr @ZLIB_SYMBOL_PREFIX@gzclearerr From 3b2d34a3114ccec0dc4040ab0616fb573bc33d0a Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 15 Dec 2021 09:18:03 +0200 Subject: [PATCH 170/798] Avoid warning C4295 when using Visual C++ and maintainer warnings are enabled. --- test/deflate_quick_bi_valid.c | 72 +++++++++++++++++------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/test/deflate_quick_bi_valid.c b/test/deflate_quick_bi_valid.c index d27e0b1532..9366bf4877 100644 --- a/test/deflate_quick_bi_valid.c +++ b/test/deflate_quick_bi_valid.c @@ -21,42 +21,42 @@ int main() { return EXIT_FAILURE; } - z_const unsigned char next_in[554] = - "\x8d\xff\xff\xff\xa2\x00\x00\xff\x00\x15\x1b\x1b\xa2\xa2\xaf\xa2" - "\xa2\x00\x00\x00\x02\x00\x1b\x3f\x00\x00\x01\x00\x00\x00\x00\x0b" - "\x00\xab\x00\x00\x00\x00\x01\x00\x01\x2b\x01\x00\x00\x00\x00\x00" - "\x00\x01\x1e\x00\x00\x01\x40\x00\x00\x00\x07\x01\x18\x00\x22\x00" - "\x00\x00\xfd\x39\xff\x00\x00\x00\x1b\xfd\x3b\x00\x68\x00\x00\x01" - "\xff\xff\xff\x57\xf8\x1e\x00\x00\xf2\xf2\xf2\xf2\xfa\xff\xff\xff" - "\xff\x7e\x00\x00\x4a\x00\xc5\x00\x41\x00\x00\x00\x01\x01\x00\x00" - "\x00\x02\x01\x01\x00\xa2\x08\x00\x00\x00\x00\x27\x4a\x4a\x4a\x32" - "\x00\xf9\xff\x00\x02\x9a\xff\x00\x00\x3f\x50\x00\x03\x00\x00\x00" - "\x3d\x00\x08\x2f\x20\x00\x23\x00\x00\x00\x00\x23\x00\xff\xff\xff" - "\xff\xff\xff\xff\x7a\x7a\x9e\xff\xff\x00\x1b\x1b\x04\x00\x1b\x1b" - "\x1b\x1b\x00\x00\x00\xaf\xad\xaf\x00\x00\xa8\x00\x00\x00\x2e\xff" - "\xff\x2e\xc1\x00\x10\x00\x00\x00\x06\x70\x00\x00\x00\xda\x67\x01" - "\x47\x00\x00\x00\x0c\x02\x00\x00\x00\x00\x00\xff\x00\x01\x00\x3f" - "\x54\x00\x00\x00\x1b\x00\x00\x00\x5c\x00\x00\x34\x3e\xc5\x00\x00" - "\x00\x00\x00\x04\x00\x00\x7a\x00\x00\x00\x0a\x01\x00\x00\x00\x00" - "\x00\x00\x7a\x7a\x7a\x7a\x7a\x00\x00\x00\x40\x1b\x1b\x88\x1b\x1b" - "\x1b\x1b\x1b\x1b\x1b\x1f\x1b\x00\x00\x00\x00\x00\x0b\x00\x00\x00" - "\x00\x04\x00\x00\x50\x3e\x7a\x7a\x00\x00\x40\x00\x40\x00\x00\x00" - "\x00\x00\x00\x08\x87\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00" - "\x01\x00\xff\x3d\x00\x11\x4d\x00\x00\x01\xd4\xd4\xd4\xd4\x2d\xd4" - "\xd4\xff\xff\xff\xfa\x01\xd4\x00\xd4\x00\x00\xd4\xd4\xd4\xd4\xd4" - "\xd4\x1e\x1e\x1e\x1e\x00\x00\xfe\xf9\x1e\x1e\x1e\x1e\x1e\x1e\x00" - "\x16\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\x00\x00\x80\x20\x00\x00" - "\xff\x2b\x2b\x2b\x2b\x35\xd4\xd4\x47\x3f\xd4\xd4\xd6\xd4\xd4\x00" - "\x00\x00\x00\x00\x32\x4a\x4a\x4a\x4a\x71\x00\x1b\x1b\x1b\x1b\x1b" - "\x1f\x1b\x1b\x1b\x57\x57\x57\x57\x00\x00\x1b\x08\x2b\x16\xc3\x00" - "\x00\x00\x29\x30\x03\xff\x03\x03\x03\x03\x07\x00\x00\x01\x0b\xff" - "\xff\xf5\xf5\xf5\x00\x00\xfe\xfa\x0f\x0f\x08\x00\xff\x00\x53\x3f" - "\x00\x04\x5d\xa8\x2e\xff\xff\x00\x2f\x2f\x05\xff\xff\xff\x2f\x2f" - "\x2f\x0a\x0a\x0a\x0a\x30\xff\xff\xff\xf0\x0a\x0a\x0a\x00\xff\x3f" - "\x4f\x00\x00\x00\x00\x08\x00\x00\x71\x00\x2e\x00\x00\x00\x00\x00" - "\x71\x71\x00\x71\x71\x71\xf5\x00\x00\x00\x00\x00\x00\x00\xf8\xff" - "\xff\xff\x00\x00\x00\x00\x00\xdb\x3f\x00\xfa\x71\x71\x71\x00\x00" - "\x00\x01\x00\x00\x00\x71\x71\x71\x71\x71"; + z_const unsigned char next_in[554] = { + 0x8d, 0xff, 0xff, 0xff, 0xa2, 0x00, 0x00, 0xff, 0x00, 0x15, 0x1b, 0x1b, 0xa2, 0xa2, 0xaf, 0xa2, + 0xa2, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1b, 0x3f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x07, 0x01, 0x18, 0x00, 0x22, 0x00, + 0x00, 0x00, 0xfd, 0x39, 0xff, 0x00, 0x00, 0x00, 0x1b, 0xfd, 0x3b, 0x00, 0x68, 0x00, 0x00, 0x01, + 0xff, 0xff, 0xff, 0x57, 0xf8, 0x1e, 0x00, 0x00, 0xf2, 0xf2, 0xf2, 0xf2, 0xfa, 0xff, 0xff, 0xff, + 0xff, 0x7e, 0x00, 0x00, 0x4a, 0x00, 0xc5, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x02, 0x01, 0x01, 0x00, 0xa2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x27, 0x4a, 0x4a, 0x4a, 0x32, + 0x00, 0xf9, 0xff, 0x00, 0x02, 0x9a, 0xff, 0x00, 0x00, 0x3f, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x3d, 0x00, 0x08, 0x2f, 0x20, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x7a, 0x7a, 0x9e, 0xff, 0xff, 0x00, 0x1b, 0x1b, 0x04, 0x00, 0x1b, 0x1b, + 0x1b, 0x1b, 0x00, 0x00, 0x00, 0xaf, 0xad, 0xaf, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x2e, 0xff, + 0xff, 0x2e, 0xc1, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x70, 0x00, 0x00, 0x00, 0xda, 0x67, 0x01, + 0x47, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x01, 0x00, 0x3f, + 0x54, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x34, 0x3e, 0xc5, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x00, 0x00, 0x00, 0x40, 0x1b, 0x1b, 0x88, 0x1b, 0x1b, + 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1f, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x50, 0x3e, 0x7a, 0x7a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x87, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0xff, 0x3d, 0x00, 0x11, 0x4d, 0x00, 0x00, 0x01, 0xd4, 0xd4, 0xd4, 0xd4, 0x2d, 0xd4, + 0xd4, 0xff, 0xff, 0xff, 0xfa, 0x01, 0xd4, 0x00, 0xd4, 0x00, 0x00, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, + 0xd4, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00, 0xfe, 0xf9, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, + 0x16, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, + 0xff, 0x2b, 0x2b, 0x2b, 0x2b, 0x35, 0xd4, 0xd4, 0x47, 0x3f, 0xd4, 0xd4, 0xd6, 0xd4, 0xd4, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x32, 0x4a, 0x4a, 0x4a, 0x4a, 0x71, 0x00, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, + 0x1f, 0x1b, 0x1b, 0x1b, 0x57, 0x57, 0x57, 0x57, 0x00, 0x00, 0x1b, 0x08, 0x2b, 0x16, 0xc3, 0x00, + 0x00, 0x00, 0x29, 0x30, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x07, 0x00, 0x00, 0x01, 0x0b, 0xff, + 0xff, 0xf5, 0xf5, 0xf5, 0x00, 0x00, 0xfe, 0xfa, 0x0f, 0x0f, 0x08, 0x00, 0xff, 0x00, 0x53, 0x3f, + 0x00, 0x04, 0x5d, 0xa8, 0x2e, 0xff, 0xff, 0x00, 0x2f, 0x2f, 0x05, 0xff, 0xff, 0xff, 0x2f, 0x2f, + 0x2f, 0x0a, 0x0a, 0x0a, 0x0a, 0x30, 0xff, 0xff, 0xff, 0xf0, 0x0a, 0x0a, 0x0a, 0x00, 0xff, 0x3f, + 0x4f, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x71, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x71, 0x71, 0x00, 0x71, 0x71, 0x71, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x3f, 0x00, 0xfa, 0x71, 0x71, 0x71, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x71, 0x71, 0x71, 0x71, 0x71}; strm.next_in = next_in; unsigned char next_out[1236]; strm.next_out = next_out; From 70f608c79c30d4b43c6f803303b797ac4f3b7f07 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Mon, 13 Dec 2021 22:30:58 +0100 Subject: [PATCH 171/798] Fix deflateBound and compressBound returning very small size estimates. Remove workaround in switchlevels.c, so we do actual testing of this. Use named defines instead of magic numbers where we can. --- compress.c | 9 +++++---- deflate.c | 16 +++++++++++----- test/switchlevels.c | 2 +- zutil.h | 14 +++++++++++++- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/compress.c b/compress.c index de45e29e6a..fded2a4cdf 100644 --- a/compress.c +++ b/compress.c @@ -91,10 +91,11 @@ z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) { return complen + ZLIB_WRAPLEN; #ifndef NO_QUICK_STRATEGY - /* Quick deflate strategy worse case is 9 bits per literal, rounded to nearest byte, - plus the size of block & gzip headers and footers */ - return sourceLen + ((sourceLen + 13 + 7) >> 3) + 18; + return sourceLen /* The source size itself */ + + DEFLATE_QUICK_OVERHEAD(sourceLen) /* Source encoding overhead, padded to next full byte */ + + DEFLATE_BLOCK_OVERHEAD /* Deflate block overhead bytes */ + + ZLIB_WRAPLEN; /* zlib wrapper */ #else - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13; + return sourceLen + (sourceLen >> 4) + 7 + ZLIB_WRAPLEN; #endif } diff --git a/deflate.c b/deflate.c index bb20a7d7a6..8f569bf2e5 100644 --- a/deflate.c +++ b/deflate.c @@ -611,11 +611,11 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long wraplen = 0; break; case 1: /* zlib wrapper */ - wraplen = 6 + (s->strstart ? 4 : 0); + wraplen = ZLIB_WRAPLEN + (s->strstart ? 4 : 0); break; #ifdef GZIP case 2: /* gzip wrapper */ - wraplen = 18; + wraplen = GZIP_WRAPLEN; if (s->gzhead != NULL) { /* user-supplied gzip header */ unsigned char *str; if (s->gzhead->extra != NULL) { @@ -639,7 +639,7 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long break; #endif default: /* for compiler happiness */ - wraplen = 6; + wraplen = ZLIB_WRAPLEN; } /* if not default parameters, return conservative bound */ @@ -647,8 +647,14 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long s->w_bits != 15 || HASH_BITS < 15) return complen + wraplen; - /* default settings: return tight bound for that case */ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; +#ifndef NO_QUICK_STRATEGY + return sourceLen /* The source size itself */ + + DEFLATE_QUICK_OVERHEAD(sourceLen) /* Source encoding overhead, padded to next full byte */ + + DEFLATE_BLOCK_OVERHEAD /* Deflate block overhead bytes */ + + wraplen; /* none, zlib or gzip wrapper */ +#else + return sourceLen + (sourceLen >> 4) + 7 + wraplen; +#endif } /* ========================================================================= diff --git a/test/switchlevels.c b/test/switchlevels.c index a4ec4b7c76..1e1fb00a5c 100644 --- a/test/switchlevels.c +++ b/test/switchlevels.c @@ -68,7 +68,7 @@ static int compress_chunk(PREFIX3(stream) *strm, int level, int size, int last) goto done; } - compsize = 100 + 2 * PREFIX(deflateBound)(strm, size); + compsize = PREFIX(deflateBound)(strm, size); buf = malloc(size + compsize); if (buf == NULL) { fprintf(stderr, "Out of memory\n"); diff --git a/zutil.h b/zutil.h index e7cb9ad3e4..f25556f946 100644 --- a/zutil.h +++ b/zutil.h @@ -78,7 +78,19 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ #define ADLER32_INITIAL_VALUE 1 /* initial adler-32 hash value */ #define CRC32_INITIAL_VALUE 0 /* initial crc-32 hash value */ -#define ZLIB_WRAPLEN 6 /* zlib format overhead */ +#define ZLIB_WRAPLEN 6 /* zlib format overhead */ +#define GZIP_WRAPLEN 18 /* gzip format overhead */ + +#define DEFLATE_HEADER_BITS 3 +#define DEFLATE_EOBS_BITS 15 +#define DEFLATE_PAD_BITS 6 +#define DEFLATE_BLOCK_OVERHEAD ((DEFLATE_HEADER_BITS + DEFLATE_EOBS_BITS + DEFLATE_PAD_BITS) >> 3) +/* deflate block overhead: 3 bits for block start + 15 bits for block end + padding to nearest byte */ + +#define DEFLATE_QUICK_LIT_MAX_BITS 9 +#define DEFLATE_QUICK_OVERHEAD(x) ((x * (DEFLATE_QUICK_LIT_MAX_BITS - 8) + 7) >> 3) +/* deflate_quick worst-case overhead: 9 bits per literal, round up to next byte (+7) */ + /* target dependencies */ From 0b74d3c4a5bd857ff846c93b02fc10f6895fa076 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 20 Dec 2021 08:15:40 -0800 Subject: [PATCH 172/798] Upgrade version of GitHub checkout actions. #1078 --- .github/workflows/libpng.yml | 2 +- .github/workflows/nmake.yml | 2 +- .github/workflows/pkgcheck.yml | 2 +- .github/workflows/release.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index fe970dd155..b3d989f7be 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -7,7 +7,7 @@ jobs: steps: - name: Checkout repository (zlib-ng) - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Generate project files (zlib-ng) run: | diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index da6d99d202..27c76a06dc 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -48,7 +48,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Compile source code shell: cmd diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 2cc4bdbca4..fa9dbdfa11 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -66,7 +66,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Install packages (Ubuntu) if: runner.os == 'Linux' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f07f431811..e52d6a6d8c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,7 +61,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v2 - name: Set environment variables shell: bash From 63bc287e4db74a62940876143c3c6f9058f401de Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 20 Dec 2021 08:23:44 -0800 Subject: [PATCH 173/798] Fixed crc32_combine_gen declaration warning in zlib-ng API. --- crc32_comb.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crc32_comb.c b/crc32_comb.c index fa11b9b222..7a6b68a90c 100644 --- a/crc32_comb.c +++ b/crc32_comb.c @@ -18,7 +18,7 @@ /* Local functions for crc concatenation */ static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2); -static void crc32_combine_gen_(uint32_t *op, z_off64_t len2); +static void crc32_combine_gen_(uint32_t op[GF2_DIM], z_off64_t len2); /* ========================================================================= */ static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) { @@ -49,7 +49,7 @@ uint32_t Z_EXPORT PREFIX4(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off64_t /* ========================================================================= */ -static void crc32_combine_gen_(uint32_t *op, z_off64_t len2) { +static void crc32_combine_gen_(uint32_t op[GF2_DIM], z_off64_t len2) { uint32_t row; int j; unsigned i; @@ -96,11 +96,14 @@ static void crc32_combine_gen_(uint32_t *op, z_off64_t len2) { void Z_EXPORT PREFIX(crc32_combine_gen)(uint32_t *op, z_off_t len2) { crc32_combine_gen_(op, len2); } -#endif - void Z_EXPORT PREFIX4(crc32_combine_gen)(uint32_t *op, z_off64_t len2) { crc32_combine_gen_(op, len2); } +#else +void Z_EXPORT PREFIX4(crc32_combine_gen)(uint32_t op[GF2_DIM], z_off64_t len2) { + crc32_combine_gen_(op, len2); +} +#endif /* ========================================================================= */ uint32_t Z_EXPORT PREFIX(crc32_combine_op)(uint32_t crc1, uint32_t crc2, const uint32_t *op) { From 3adbc36c8aa1ddaeab1f8d2fd7122106d3221889 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 3 Jan 2022 19:48:06 -0800 Subject: [PATCH 174/798] Remove double check for SSE4 in configure. --- configure | 3 --- 1 file changed, 3 deletions(-) diff --git a/configure b/configure index af1c7c431d..7564891c72 100755 --- a/configure +++ b/configure @@ -1330,9 +1330,6 @@ case "${ARCH}" in ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} insert_string_sse.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse.lo" fi - - check_sse4_intrinsics - if test ${HAVE_SSE42CMPSTR_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42_CMP_STR" SFLAGS="${SFLAGS} -DX86_SSE42_CMP_STR" From ff52d467148cab56904ffe3a1aa8ebd65ee93ded Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 4 Jan 2022 14:57:18 -0800 Subject: [PATCH 175/798] Remove old win32 readme. --- win32/README-WIN32.txt | 103 ----------------------------------------- 1 file changed, 103 deletions(-) delete mode 100644 win32/README-WIN32.txt diff --git a/win32/README-WIN32.txt b/win32/README-WIN32.txt deleted file mode 100644 index 905ace6b89..0000000000 --- a/win32/README-WIN32.txt +++ /dev/null @@ -1,103 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.11 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -https://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) -and rfc1952.txt (gzip format). - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled -examples are distributed in this package, example and minigzip. The example_d -and minigzip_d flavors validate that the zlib1.dll file is working correctly. - -Questions about zlib should be sent to . The zlib home page -is https://zlib.net/ . Before reporting a problem, please check this site to -verify that you have the latest version of zlib; otherwise get the latest -version and check whether the problem still exists or not. - -PLEASE read DLL_FAQ.txt, and the the zlib FAQ https://zlib.net/zlib_faq.html -before asking for help. - - -Manifest: - -The package zlib-1.2.11-win32-x86.zip will contain the following files: - - README-WIN32.txt This document - ChangeLog Changes since previous zlib packages - DLL_FAQ.txt Frequently asked questions about zlib1.dll - zlib.3.pdf Documentation of this library in Adobe Acrobat format - - example.exe A statically-bound example (using zlib.lib, not the dll) - example.pdb Symbolic information for debugging example.exe - - example_d.exe A zlib1.dll bound example (using zdll.lib) - example_d.pdb Symbolic information for debugging example_d.exe - - minigzip.exe A statically-bound test program (using zlib.lib, not the dll) - minigzip.pdb Symbolic information for debugging minigzip.exe - - minigzip_d.exe A zlib1.dll bound test program (using zdll.lib) - minigzip_d.pdb Symbolic information for debugging minigzip_d.exe - - zlib.h Install these files into the compilers' INCLUDE path to - zconf.h compile programs which use zlib.lib or zdll.lib - - zdll.lib Install these files into the compilers' LIB path if linking - zdll.exp a compiled program to the zlib1.dll binary - - zlib.lib Install these files into the compilers' LIB path to link zlib - zlib.pdb into compiled programs, without zlib1.dll runtime dependency - (zlib.pdb provides debugging info to the compile time linker) - - zlib1.dll Install this binary shared library into the system PATH, or - the program's runtime directory (where the .exe resides) - zlib1.pdb Install in the same directory as zlib1.dll, in order to debug - an application crash using WinDbg or similar tools. - -All .pdb files above are entirely optional, but are very useful to a developer -attempting to diagnose program misbehavior or a crash. Many additional -important files for developers can be found in the zlib127.zip source package -available from https://zlib.net/ - review that package's README file for details. - - -Acknowledgments: - -The deflate format used by zlib was defined by Phil Katz. The deflate and -zlib specifications were written by L. Peter Deutsch. Thanks to all the -people who reported problems and suggested various improvements in zlib; they -are too numerous to cite here. - - -Copyright notice: - - (C) 1995-2012 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - -If you use the zlib library in a product, we would appreciate *not* receiving -lengthy legal documents to sign. The sources are provided for free but without -warranty of any kind. The library has been entirely written by Jean-loup -Gailly and Mark Adler; it does not include third-party code. - -If you redistribute modified sources, we would appreciate that you include in -the file ChangeLog history information documenting your changes. Please read -the FAQ for more information on the distribution of modified source versions. From 4cc2da7d73d9d2085e5e3a5ad682528ee40f5296 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Thu, 6 Jan 2022 17:29:19 +0200 Subject: [PATCH 176/798] Fix building shared tests * Don't add non-PIC gz sources to shared executables if they are already included in shared library as PIC sources --- Makefile.in | 13 +++++++------ configure | 4 ++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Makefile.in b/Makefile.in index 928805fc58..3b037302c5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -143,6 +143,7 @@ PIC_OBJG = \ gzread.lo \ gzwrite.lo +PIC_TESTOBJG = PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) OBJS = $(OBJC) @@ -332,8 +333,8 @@ ifneq ($(STRIP),) $(STRIP) $@ endif -adler32_testsh$(EXE): adler32_test.o $(OBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ adler32_test.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) +adler32_testsh$(EXE): adler32_test.o $(PIC_TESTOBJG) $(SHAREDTARGET) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ adler32_test.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif @@ -344,14 +345,14 @@ ifneq ($(STRIP),) $(STRIP) $@ endif -examplesh$(EXE): example.o $(OBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) +examplesh$(EXE): example.o $(PIC_TESTOBJG) $(SHAREDTARGET) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -minigzipsh$(EXE): minigzip.o $(OBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) +minigzipsh$(EXE): minigzip.o $(PIC_TESTOBJG) $(SHAREDTARGET) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif diff --git a/configure b/configure index 7564891c72..3f145a6d48 100755 --- a/configure +++ b/configure @@ -890,6 +890,8 @@ if test $gzfileops -eq 1; then SFLAGS="${SFLAGS} -DWITH_GZFILEOP" OBJC="${OBJC} \$(OBJG)" PIC_OBJC="${PIC_OBJC} \$(PIC_OBJG)" +else + PIC_TESTOBJG="\$(OBJG)" fi # enable reduced memory configuration @@ -1747,6 +1749,7 @@ echo RCFLAGS = $RCFLAGS >> configure.log echo RCOBJS = $RCOBJS >> configure.log echo STRIP = $STRIP >> configure.log echo OBJC = $OBJC >> configure.log +echo PIC_TESTOBJG = $PIC_TESTOBJG >> configure.log echo PIC_OBJC = $PIC_OBJC >> configure.log echo RANLIB = $RANLIB >> configure.log echo SFLAGS = $SFLAGS >> configure.log @@ -1836,6 +1839,7 @@ sed < $SRCDIR/Makefile.in " /^SRCDIR *=/s#=.*#=$SRCDIR# /^INCLUDES *=/s#=.*#=$INCLUDES# /^OBJC *=/s#=.*#= $OBJC# +/^PIC_TESTOBJG *=/s#=.*#= $PIC_TESTOBJG# /^PIC_OBJC *=/s#=.*#= $PIC_OBJC# /^all: */s#:.*#: $ALL# /^install-libs: */s#:.*#: $INSTALLTARGETS# From cf5fe97d0ff154d1b381832e86533e9db1f070af Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 24 Dec 2021 12:33:15 -0800 Subject: [PATCH 177/798] Fixed wrong alignment definition used when compiling with ClangCl. --- zutil.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/zutil.h b/zutil.h index f25556f946..660fabdacd 100644 --- a/zutil.h +++ b/zutil.h @@ -253,12 +253,10 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr); # define PREFETCH_RW(addr) addr #endif /* (un)likely */ -#if defined(_MSC_VER) +#if defined(__clang__) || defined(__GNUC__) +# define ALIGNED_(x) __attribute__ ((aligned(x))) +#elif defined(_MSC_VER) # define ALIGNED_(x) __declspec(align(x)) -#else -# if defined(__GNUC__) -# define ALIGNED_(x) __attribute__ ((aligned(x))) -# endif #endif #if defined(X86_FEATURES) From ac733b3bdab01a831a2055ac43ce6ebe0143f82d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 24 Dec 2021 13:08:32 -0800 Subject: [PATCH 178/798] Fixed implicit declaration of _mm_extract_epi32 when compiling with ClangCl. --- arch/x86/crc32_fold_pclmulqdq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 0e261d4069..d07ffb4085 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -22,6 +22,7 @@ #include #include #include +#include // _mm_extract_epi32 #include "../../crc32_fold.h" From 34bbd9c6e3d0a240fa6f2dc79132a7a7d6e3b5a1 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 24 Dec 2021 16:42:23 -0800 Subject: [PATCH 179/798] Fixed incorrect flag used for SSE 4.2 support with ClangCl. --- cmake/detect-intrinsics.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index c6085018a6..39ae19ae96 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -221,7 +221,7 @@ macro(check_sse4_intrinsics) endif() elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) - set(SSE4FLAG "-msse4") + set(SSE4FLAG "-msse4.2") endif() endif() # Check whether compiler supports SSE4 CRC inline asm From 080243069430969d4ae1754a56ad5bb5a66bfc00 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 24 Dec 2021 17:02:13 -0800 Subject: [PATCH 180/798] Move stdint.h below zconf include to prevent unexpected characters warning on ClangCl. --- zlib-ng.h.in | 3 ++- zlib.h.in | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 2603707816..30deabf1d4 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -33,9 +33,10 @@ # error Include zlib-ng.h for zlib-ng API or zlib.h for zlib-compat API but not both #endif -#include #include "zconf-ng.h" +#include + #ifndef ZCONFNG_H # error Missing zconf-ng.h add binary output directory to include directories #endif diff --git a/zlib.h.in b/zlib.h.in index 40d1f73e2e..1c2944cef4 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -34,9 +34,10 @@ # error Include zlib-ng.h for zlib-ng API or zlib.h for zlib-compat API but not both #endif +#include "zconf.h" + #include #include -#include "zconf.h" #ifndef ZCONF_H # error Missing zconf.h add binary output directory to include directories From 99913c9cd9d55c1211669406aeac2b5f61e79333 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 24 Dec 2021 20:19:03 -0800 Subject: [PATCH 181/798] Fixed duplicate symbol zng_inflate_table and zng_inflate_copyright when BUILD_SHARED_LIBS=OFF. --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3befedb71..9acf18df69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1158,7 +1158,9 @@ if(ZLIB_ENABLE_TESTS) target_link_libraries(switchlevels zlib) add_simple_test_executable(infcover) - target_sources(infcover PRIVATE inftrees.c) + if(NOT BUILD_SHARED_LIBS) + target_sources(infcover PRIVATE inftrees.c) + endif() add_executable(makefixed tools/makefixed.c inftrees.c) target_include_directories(makefixed PUBLIC From a080c6af1181f8463e265193ab5bd9a7cf6cfb3d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 24 Dec 2021 20:18:05 -0800 Subject: [PATCH 182/798] Don't build DLL sources if BUILD_SHARED_LIBS=OFF. --- CMakeLists.txt | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9acf18df69..fc0f44935a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -920,43 +920,45 @@ set(ZLIB_GZFILE_SRCS gzwrite.c ) -if(NOT MINGW AND NOT MSYS AND NOT CYGWIN) - set(ZLIB_DLL_SRCS - win32/zlib${SUFFIX}1.rc # If present will override custom build rule below. - ) +set(ZLIB_ALL_SRCS ${ZLIB_SRCS} ${ZLIB_ARCH_HDRS} ${ZLIB_ARCH_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +if(WITH_GZFILEOP) + list(APPEND ZLIB_ALL_SRCS ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) endif() -if(MINGW OR MSYS OR CYGWIN) - # This gets us DLL resource information when compiling on MinGW. - if(NOT CMAKE_RC_COMPILER) - set(CMAKE_RC_COMPILER windres.exe) +if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) + if(NOT MINGW AND NOT MSYS AND NOT CYGWIN) + # If present will override custom build rule below. + set(ZLIB_DLL_SRCS win32/zlib${SUFFIX}1.rc) endif() - add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - COMMAND ${CMAKE_RC_COMPILER} - -D GCC_WINDRES - -I ${CMAKE_CURRENT_SOURCE_DIR} - -I ${CMAKE_CURRENT_BINARY_DIR} - -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj - -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib${SUFFIX}1.rc) - set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) -endif() + if(MINGW OR MSYS OR CYGWIN) + # This gets us DLL resource information when compiling on MinGW. + if(NOT CMAKE_RC_COMPILER) + set(CMAKE_RC_COMPILER windres.exe) + endif() -set(ZLIB_ALL_SRCS ${ZLIB_SRCS} ${ZLIB_ARCH_HDRS} ${ZLIB_ARCH_SRCS} ${ZLIB_DLL_SRCS} - ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) -if(WITH_GZFILEOP) - list(APPEND ZLIB_ALL_SRCS ${ZLIB_GZFILE_PRIVATE_HDRS} ${ZLIB_GZFILE_SRCS}) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + COMMAND ${CMAKE_RC_COMPILER} + -D GCC_WINDRES + -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib${SUFFIX}1.rc) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) + endif() endif() if(NOT DEFINED BUILD_SHARED_LIBS) - add_library(zlib SHARED ${ZLIB_ALL_SRCS}) + add_library(zlib SHARED ${ZLIB_ALL_SRCS} ${ZLIB_DLL_SRCS}) add_library(zlibstatic STATIC ${ZLIB_ALL_SRCS}) set(ZLIB_INSTALL_LIBRARIES zlib zlibstatic) else() add_library(zlib ${ZLIB_ALL_SRCS}) - if(NOT BUILD_SHARED_LIBS) + if(BUILD_SHARED_LIBS) + target_sources(zlib PRIVATE ${ZLIB_DLL_SRCS}) + else() add_library(zlibstatic ALIAS zlib) endif() From 5f14bffab8bbb17c577f6fae61a47b0a94f0486c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 29 Dec 2021 15:51:00 -0800 Subject: [PATCH 183/798] Fixed crc32 assembly not returning hash value to correct variable. --- arch/x86/insert_string_sse.c | 2 +- cmake/detect-intrinsics.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/insert_string_sse.c b/arch/x86/insert_string_sse.c index 7a63b2a7bf..b33a2c7ccb 100644 --- a/arch/x86/insert_string_sse.c +++ b/arch/x86/insert_string_sse.c @@ -26,7 +26,7 @@ __asm mov edx, h\ __asm mov eax, val\ __asm crc32 eax, edx\ - __asm mov val, eax\ + __asm mov h, eax\ } # else # define HASH_CALC(s, h, val) \ diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 39ae19ae96..e03daaa136 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -230,7 +230,7 @@ macro(check_sse4_intrinsics) "int main(void) { unsigned val = 0, h = 0; #if defined(_MSC_VER) - { __asm mov edx, h __asm mov eax, val __asm crc32 eax, edx __asm mov val, eax } + { __asm mov edx, h __asm mov eax, val __asm crc32 eax, edx __asm mov h, eax } #else __asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) ); #endif From 29b10f995f7fc0c15a5ac592bc4244b1a574216b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 29 Dec 2021 20:33:08 -0800 Subject: [PATCH 184/798] Fixed part of conditional expression is always true since size is always greater than 0. --- gzwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gzwrite.c b/gzwrite.c index c4e178f9ad..b3e93e8d08 100644 --- a/gzwrite.c +++ b/gzwrite.c @@ -274,7 +274,7 @@ size_t Z_EXPORT PREFIX(gzfwrite)(void const *buf, size_t size, size_t nitems, gz /* compute bytes to read -- error on overflow */ len = nitems * size; - if (size && len / size != nitems) { + if (len / size != nitems) { gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); return 0; } From a5655bcb64b50d991bc15466d6b30a17ea14440a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 29 Dec 2021 20:45:12 -0800 Subject: [PATCH 185/798] Fixed main function does not return value which may indicated unintended behavior. --- test/deflate_quick_bi_valid.c | 1 + test/deflate_quick_block_open.c | 1 + 2 files changed, 2 insertions(+) diff --git a/test/deflate_quick_bi_valid.c b/test/deflate_quick_bi_valid.c index 9366bf4877..0a60081f4e 100644 --- a/test/deflate_quick_bi_valid.c +++ b/test/deflate_quick_bi_valid.c @@ -82,4 +82,5 @@ int main() { fprintf(stderr, "deflateEnd() failed with code %d\n", ret); return EXIT_FAILURE; } + return 0; } diff --git a/test/deflate_quick_block_open.c b/test/deflate_quick_block_open.c index 9526533d0b..9df9212000 100644 --- a/test/deflate_quick_block_open.c +++ b/test/deflate_quick_block_open.c @@ -107,4 +107,5 @@ int main() { fprintf(stderr, "Uncompressed data differs from the original\n"); return EXIT_FAILURE; } + return 0; } From fe2211ba4cf7bc253353f8c3082c7a179d2624e2 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 29 Dec 2021 20:48:47 -0800 Subject: [PATCH 186/798] Check for err == Z_OK is always true in minideflate loops. --- test/minideflate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index 36c27f9046..f82cfcc302 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -111,7 +111,7 @@ void deflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ err = PREFIX(deflate)(&c_stream, Z_FINISH); if (err == Z_STREAM_END) break; CHECK_ERR(err, "deflate"); - } while (err == Z_OK); + } while (1); } /* Output remaining data in write buffer */ @@ -197,7 +197,7 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ err = PREFIX(inflate)(&d_stream, Z_FINISH); if (err == Z_STREAM_END) break; CHECK_ERR(err, "inflate"); - } while (err == Z_OK); + } while (1); } /* Output remaining data in write buffer */ From 46031f5cdea1d48577490ce60bb921e78b76277e Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Fri, 7 Jan 2022 15:51:09 -0500 Subject: [PATCH 187/798] Have functioning avx512{,_vnni} adler32 The new adler32 checksum uses the VNNI instructions with appreciable gains when possible. Otherwise, a pure avx512f variant exists which still gives appreciable gains. --- CMakeLists.txt | 31 ++++++++ README.md | 4 +- arch/x86/Makefile.in | 18 ++++- arch/x86/adler32_avx512.c | 85 +++++++++++++++++++++ arch/x86/adler32_avx512_vnni.c | 135 +++++++++++++++++++++++++++++++++ arch/x86/x86.c | 49 ++++++++++++ arch/x86/x86.h | 3 + cmake/detect-intrinsics.cmake | 82 ++++++++++++++++++++ configure | 102 +++++++++++++++++++++++++ functable.c | 15 ++++ 10 files changed, 522 insertions(+), 2 deletions(-) create mode 100644 arch/x86/adler32_avx512.c create mode 100644 arch/x86/adler32_avx512_vnni.c diff --git a/CMakeLists.txt b/CMakeLists.txt index fc0f44935a..526065f320 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,8 @@ elseif(BASEARCH_S360_FOUND) option(WITH_CRC32_VX "Build with vectorized CRC32 on IBM Z" ON) elseif(BASEARCH_X86_FOUND) option(WITH_AVX2 "Build with AVX2" ON) + option(WITH_AVX512 "Build with AVX512" ON) + option(WITH_AVX512VNNI "Build with AVX512 VNNI extensions" ON) option(WITH_SSE2 "Build with SSE2" ON) option(WITH_SSSE3 "Build with SSSE3" ON) option(WITH_SSE4 "Build with SSE4" ON) @@ -724,6 +726,33 @@ if(WITH_OPTIM) set(WITH_AVX2 OFF) endif() endif() + if(WITH_AVX512) + check_avx512_intrinsics() + if(HAVE_AVX512_INTRIN) + add_definitions(-DX86_AVX512 -DX86_AVX512_ADLER32) + list(APPEND AVX512_SRCS ${ARCHDIR}/adler32_avx512.c) + add_feature_info(AVX512_ADLER32 1 "Support AVX512-accelerated adler32, using \"${AVX512FLAG}\"") + list(APPEND ZLIB_ARCH_SRCS ${AVX512_SRCS}) + if(HAVE_MASK_INTRIN) + add_definitions(-DX86_MASK_INTRIN) + endif() + set_property(SOURCE ${AVX512_SRCS} PROPERTY COMPILE_FLAGS "${AVX512FLAG} ${NOLTOFLAG}") + else() + set(WITH_AVX512 OFF) + endif() + endif() + if(WITH_AVX512VNNI) + check_avx512vnni_intrinsics() + if(HAVE_AVX512VNNI_INTRIN) + add_definitions(-DX86_AVX512VNNI -DX86_AVX512VNNI_ADLER32) + add_feature_info(AVX512VNNI_ADLER32 1 "Support AVX512VNNI adler32, using \"${AVX512VNNIFLAG}\"") + list(APPEND AVX512VNNI_SRCS ${ARCHDIR}/adler32_avx512_vnni.c) + list(APPEND ZLIB_ARCH_SRCS ${AVX512VNNI_SRCS}) + set_property(SOURCE ${AVX512VNNI_SRCS} PROPERTY COMPILE_FLAGS "${AVX512VNNIFLAG} ${NOLTOFLAG}") + else() + set(WITH_AVX512VNNI OFF) + endif() + endif() if(WITH_SSE4) check_sse4_intrinsics() if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) @@ -1408,6 +1437,8 @@ elseif(BASEARCH_S360_FOUND) add_feature_info(WITH_CRC32_VX WITH_CRC32_VX "Build with vectorized CRC32 on IBM Z") elseif(BASEARCH_X86_FOUND) add_feature_info(WITH_AVX2 WITH_AVX2 "Build with AVX2") + add_feature_info(WITH_AVX512 WITH_AVX512 "Build with AVX512") + add_feature_info(WITH_AVX512VNNI WITH_AVX512VNNI "Build with AVX512 VNNI") add_feature_info(WITH_SSE2 WITH_SSE2 "Build with SSE2") add_feature_info(WITH_SSSE3 WITH_SSSE3 "Build with SSSE3") add_feature_info(WITH_SSE4 WITH_SSE4 "Build with SSE4") diff --git a/README.md b/README.md index 541ffb94fc..0da19e4077 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Features * Modern C11 syntax and a clean code layout * Deflate medium and quick algorithms based on Intels zlib fork * Support for CPU intrinsics when available - * Adler32 implementation using SSSE3, AVX2, Neon, VMX & VSX + * Adler32 implementation using SSSE3, AVX2, AVX512, AVX512-VNNI, Neon, VMX & VSX * CRC32-B implementation using PCLMULQDQ & ACLE * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX @@ -197,6 +197,8 @@ Advanced Build Options | UNALIGNED_OK | | Allow unaligned reads | ON (x86, arm) | | | --force-sse2 | Skip runtime check for SSE2 instructions (Always on for x86_64) | OFF (x86) | | WITH_AVX2 | | Build with AVX2 intrinsics | ON | +| WITH_AVX512 | | Build with AVX512 intrinsics | ON | +| WITH_AVX512VNNI | | Build with AVX512VNNI intrinsics | ON | | WITH_SSE2 | | Build with SSE2 intrinsics | ON | | WITH_SSE4 | | Build with SSE4 intrinsics | ON | | WITH_PCLMULQDQ | | Build with PCLMULQDQ intrinsics | ON | diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index c5e588e70d..3e92738eee 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -8,6 +8,8 @@ SFLAGS= INCLUDES= SUFFIX= +AVX512FLAG=-mavx512f -mavx512dq -mavx512vl -mavx512bw +AVX512VNNIFLAG=-mavx512vnni AVX2FLAG=-mavx2 SSE2FLAG=-msse2 SSSE3FLAG=-mssse3 @@ -21,7 +23,9 @@ TOPDIR=$(SRCTOP) all: \ x86.o x86.lo \ - adler32_avx.o adler32.lo \ + adler32_avx.o adler32_avx.lo \ + adler32_avx512.o adler32_avx512.lo \ + adler32_avx512_vnni.o adler32_avx512_vnni.lo \ adler32_ssse3.o adler32_ssse3.lo \ chunkset_avx.o chunkset_avx.lo \ chunkset_sse.o chunkset_sse.lo \ @@ -92,6 +96,18 @@ adler32_avx.o: $(SRCDIR)/adler32_avx.c adler32_avx.lo: $(SRCDIR)/adler32_avx.c $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c +adler32_avx512.o: $(SRCDIR)/adler32_avx512.c + $(CC) $(CFLAGS) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512.c + +adler32_avx512.lo: $(SRCDIR)/adler32_avx512.c + $(CC) $(SFLAGS) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512.c + +adler32_avx512_vnni.o: $(SRCDIR)/adler32_avx512_vnni.c + $(CC) $(CFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c + +adler32_avx512_vnni.lo: $(SRCDIR)/adler32_avx512_vnni.c + $(CC) $(SFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c + adler32_ssse3.o: $(SRCDIR)/adler32_ssse3.c $(CC) $(CFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c new file mode 100644 index 0000000000..f73ceccef1 --- /dev/null +++ b/arch/x86/adler32_avx512.c @@ -0,0 +1,85 @@ +/* adler32_avx512.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Authors: + * Adam Stylinski + * Brian Bockelman + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" +#include "../../zutil.h" + +#include "../../adler32_p.h" + +#include + +#ifdef X86_AVX512_ADLER32 + +Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len) { + uint32_t sum2; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) + return adler32_len_1(adler, buf, sum2); + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (UNLIKELY(buf == NULL)) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (UNLIKELY(len < 16)) + return adler32_len_16(adler, buf, len, sum2); + + const __mmask16 vs_mask = 1U << 15; + __m512i vs1 = _mm512_maskz_set1_epi32(vs_mask, adler); + __m512i vs2 = _mm512_maskz_set1_epi32(vs_mask, sum2); + + const __m512i dot1v = _mm512_set1_epi8(1); + const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + const __m512i dot3v = _mm512_set1_epi16(1); + + while (len >= 64) { + __m512i vs1_0 = vs1; + + int k = (len < NMAX ? (int)len : NMAX); + k -= k % 64; + len -= k; + + while (k >= 64) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + __m512i vbuf = _mm512_loadu_si512(buf); + buf += 64; + k -= 64; + + __m512i v_short_sum1 = _mm512_maddubs_epi16(vbuf, dot1v); // multiply-add, resulting in 16 shorts. + __m512i vsum1 = _mm512_madd_epi16(v_short_sum1, dot3v); // sum 16 shorts to 8 int32_t; + __m512i v_short_sum2 = _mm512_maddubs_epi16(vbuf, dot2v); + vs1 = _mm512_add_epi32(vsum1, vs1); + __m512i vsum2 = _mm512_madd_epi16(v_short_sum2, dot3v); + vs1_0 = _mm512_slli_epi32(vs1_0, 6); + vsum2 = _mm512_add_epi32(vsum2, vs2); + vs2 = _mm512_add_epi32(vsum2, vs1_0); + vs1_0 = vs1; + } + + adler = _mm512_reduce_add_epi32(vs1) % BASE; + vs1 = _mm512_maskz_set1_epi32(vs_mask, adler); + sum2 = _mm512_reduce_add_epi32(vs2) % BASE; + vs2 = _mm512_maskz_set1_epi32(vs_mask, sum2); + } + + /* Process tail (len < 16). */ + return adler32_len_16(adler, buf, len, sum2); +} + +#endif diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c new file mode 100644 index 0000000000..f4e2c33edc --- /dev/null +++ b/arch/x86/adler32_avx512_vnni.c @@ -0,0 +1,135 @@ +/* adler32_avx512_vnni.c -- compute the Adler-32 checksum of a data stream + * Based on Brian Bockelman's AVX2 version + * Copyright (C) 1995-2011 Mark Adler + * Authors: + * Adam Stylinski + * Brian Bockelman + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" +#include "../../zutil.h" + +#include "../../adler32_p.h" + +#include + +#ifdef X86_AVX512VNNI_ADLER32 + +static inline uint32_t partial_hsum(__m512i x) +{ + /* We need a permutation vector to extract every other integer. The + * rest are going to be zeros. Marking this const so the compiler stands + * a better chance of keeping this resident in a register through entire + * loop execution. We certainly have enough zmm registers (32) */ + const __m512i perm_vec = _mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, + 1, 1, 1, 1, 1, 1, 1, 1); + __m512i non_zero = _mm512_permutexvar_epi32(perm_vec, x); + + /* From here, it's a simple 256 bit wide reduction sum */ + __m256i non_zero_avx = _mm512_castsi512_si256(non_zero); + + /* See Agner Fog's vectorclass for a decent reference. Essentially, phadd is + * pretty slow, much slower than the longer instruction sequence below */ + __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(non_zero_avx, 1), + _mm256_castsi256_si128(non_zero_avx)); + __m128i sum2 = _mm_add_epi32(sum1,_mm_unpackhi_epi64(sum1, sum1)); + __m128i sum3 = _mm_add_epi32(sum2,_mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} + +Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len) { + uint32_t sum2; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) + return adler32_len_1(adler, buf, sum2); + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (UNLIKELY(buf == NULL)) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (UNLIKELY(len < 16)) + return adler32_len_16(adler, buf, len, sum2); + + const __mmask16 vs_mask = 1U << 15; + /* We want to place initial adler sum at vector position 0, as it is one of the lanes that line up + * with the sum of absolute differences' reduction sum. If we do this, we can get away with a partial, + * less expensive horizontal sum for the vs1 component at the end. It also happens to be marginally better + * (by a single cycle) to do this with the ancient vmovd insruction, and simply allow the register to be + * aliased up to a 512 bit wide zmm */ + __m512i vs1 = _mm512_castsi128_si512(_mm_cvtsi32_si128(adler)); + __m512i vs2 = _mm512_maskz_set1_epi32(vs_mask, sum2); + + const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + + const __m512i zero = _mm512_setzero_si512(); + + while (len >= 64) { + int k = (len < NMAX ? (int)len : NMAX); + k -= k % 64; + len -= k; + __m512i vs1_0 = vs1; + __m512i vs3 = _mm512_setzero_si512(); + + /* Manually unrolled this loop by 2 for an decent amount of ILP */ + while (k >= 128) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + __m512i vbuf0 = _mm512_loadu_si512(buf); + __m512i vbuf1 = _mm512_loadu_si512(buf+64); + buf += 128; + k -= 128; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf0, zero); + vs1 = _mm512_add_epi32(vs1, vs1_sad); + vs3 = _mm512_add_epi32(vs3, vs1_0); + /* multiply-add, resulting in 16 ints. Fuse with sum stage from prior versions, as we now have the dp + * instructions to eliminate them */ + vs2 = _mm512_dpbusd_epi32(vs2, vbuf0, dot2v); + vs1_0 = vs1; + + vs1_sad = _mm512_sad_epu8(vbuf1, zero); + vs1 = _mm512_add_epi32(vs1, vs1_sad); + vs3 = _mm512_add_epi32(vs3, vs1_0); + vs2 = _mm512_dpbusd_epi32(vs2, vbuf1, dot2v); + vs1_0 = vs1; + } + + /* Remainder peeling */ + while (k >= 64) { + __m512i vbuf = _mm512_loadu_si512(buf); + buf += 64; + k -= 64; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf, zero); + vs1 = _mm512_add_epi32(vs1, vs1_sad); + vs3 = _mm512_add_epi32(vs3, vs1_0); + vs2 = _mm512_dpbusd_epi32(vs2, vbuf, dot2v); + vs1_0 = vs1; + } + + vs3 = _mm512_slli_epi32(vs3, 6); + vs2 = _mm512_add_epi32(vs2, vs3); + + adler = partial_hsum(vs1) % BASE; + vs1 = _mm512_castsi128_si512(_mm_cvtsi32_si128(adler)); + sum2 = _mm512_reduce_add_epi32(vs2) % BASE; + vs2 = _mm512_maskz_set1_epi32(vs_mask, sum2); + } + + /* Process tail (len < 16). */ + return adler32_len_16(adler, buf, len, sum2); +} + +#endif diff --git a/arch/x86/x86.c b/arch/x86/x86.c index e782cb8ee3..f02e1a3491 100644 --- a/arch/x86/x86.c +++ b/arch/x86/x86.c @@ -17,12 +17,17 @@ # include #endif +#include + Z_INTERNAL int x86_cpu_has_avx2; +Z_INTERNAL int x86_cpu_has_avx512; +Z_INTERNAL int x86_cpu_has_avx512vnni; Z_INTERNAL int x86_cpu_has_sse2; Z_INTERNAL int x86_cpu_has_ssse3; Z_INTERNAL int x86_cpu_has_sse42; Z_INTERNAL int x86_cpu_has_pclmulqdq; Z_INTERNAL int x86_cpu_has_tzcnt; +Z_INTERNAL int x86_cpu_well_suited_avx512; static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { #ifdef _MSC_VER @@ -55,15 +60,31 @@ static void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigne void Z_INTERNAL x86_check_features(void) { unsigned eax, ebx, ecx, edx; unsigned maxbasic; + unsigned family, model, extended_model; + int intel_cpu; + char cpu_identity[13]; cpuid(0, &maxbasic, &ebx, &ecx, &edx); + /* NULL terminate the string */ + memset(cpu_identity, 0, 13); + memcpy(cpu_identity, (char*)&ebx, sizeof(int)); + memcpy(cpu_identity + 4, (char*)&edx, sizeof(int)); + memcpy(cpu_identity + 8, (char*)&ecx, sizeof(int)); + + intel_cpu = strncmp(cpu_identity, "GenuineIntel", 12) == 0; + cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx); x86_cpu_has_sse2 = edx & 0x4000000; x86_cpu_has_ssse3 = ecx & 0x200; x86_cpu_has_sse42 = ecx & 0x100000; x86_cpu_has_pclmulqdq = ecx & 0x2; + x86_cpu_well_suited_avx512 = 0; + + model = (eax & 0xf0) >> 4; + family = (eax & 0xf00) >> 8; + extended_model = (eax & 0xf0000) >> 16; if (maxbasic >= 7) { cpuidex(7, 0, &eax, &ebx, &ecx, &edx); @@ -73,8 +94,36 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_has_tzcnt = ebx & 0x8; // check AVX2 bit x86_cpu_has_avx2 = ebx & 0x20; + x86_cpu_has_avx512 = ebx & 0x00010000; + x86_cpu_has_avx512vnni = ecx & 0x800; } else { x86_cpu_has_tzcnt = 0; x86_cpu_has_avx2 = 0; } + + + if (intel_cpu) { + /* All of the Knights Landing and Knights Ferry _likely_ benefit + * from the AVX512 adler checksum implementation */ + if (family == 0xb) { + x86_cpu_well_suited_avx512 = 1; + } else if (family == 0x6) { + if (model == 0x5 && extended_model == 0x5) { + /* Experimentally, on skylake-x and cascadelake-x, it has been + * unwaiveringly faster to use avx512 and avx512 vnni */ + x86_cpu_well_suited_avx512 = 1; + } else if (model == 0xa && extended_model == 0x6) { + /* Icelake server */ + x86_cpu_well_suited_avx512 = 1; + } else if (model == 0xf && extended_model == 0x8) { + /* Saphire rapids */ + x86_cpu_well_suited_avx512 = 1; + } + + /* Still need to check whether Rocket Lake and/or AlderLake + * benefit from the AVX512VNNI accelerated adler32 implementations. + * For now this working list is probably safe */ + } + } + } diff --git a/arch/x86/x86.h b/arch/x86/x86.h index 8471e155cd..4274ed09f6 100644 --- a/arch/x86/x86.h +++ b/arch/x86/x86.h @@ -7,11 +7,14 @@ #define CPU_H_ extern int x86_cpu_has_avx2; +extern int x86_cpu_has_avx512; +extern int x86_cpu_has_avx512vnni; extern int x86_cpu_has_sse2; extern int x86_cpu_has_ssse3; extern int x86_cpu_has_sse42; extern int x86_cpu_has_pclmulqdq; extern int x86_cpu_has_tzcnt; +extern int x86_cpu_well_suited_avx512; void Z_INTERNAL x86_check_features(void); diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index e03daaa136..9f7a971907 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -13,6 +13,88 @@ macro(check_acle_intrinsics) set(CMAKE_REQUIRED_FLAGS) endmacro() +macro(check_avx512_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl") + else() + set(AVX512FLAG "/arch:AVX512") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal + # instruction scheduling unless you specify a reasonable -mtune= target + set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mtune=cascadelake") + endif() + elseif(MSVC) + set(AVX512FLAG "/ARCH:AVX512") + endif() + # Check whether compiler supports AVX512 intrinsics + set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG}") + check_c_source_compile_or_run( + "#include + int main(void) { + __m512i x = _mm512_set1_epi8(2); + const __m512i y = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + x = _mm512_sub_epi8(x, y); + (void)x; + return 0; + }" + HAVE_AVX512_INTRIN + ) + + # Evidently both GCC and clang were late to implementing these + check_c_source_compile_or_run( + "#include + int main(void) { + __mmask16 a = 0xFF; + a = _knot_mask16(a); + (void)a; + return 0; + }" + HAVE_MASK_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + +macro(check_avx512vnni_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(AVX512VNNIFLAG "-mavx512f -mavx512bw -mavx512dq -mavx512vl -mavx512vnni") + else() + set(AVX512FLAG "/ARCH:AVX512") + endif() + elseif(MSVC) + set(AVX512FLAG "/ARCH:AVX512") + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(AVX512VNNIFLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx512vnni -mtune=cascadelake") + endif() + endif() + + # Check whether compiler supports AVX512vnni intrinsics + set(CMAKE_REQUIRED_FLAGS "${AVX512VNNIFLAG}") + check_c_source_compile_or_run( + "#include + int main(void) { + __m512i x = _mm512_set1_epi8(2); + const __m512i y = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + __m512i z = _mm512_setzero_epi32(); + z = _mm512_dpbusd_epi32(z, x, y); + (void)z; + return 0; + }" + HAVE_AVX512VNNI_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + macro(check_avx2_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "Intel") if(CMAKE_HOST_UNIX OR APPLE) diff --git a/configure b/configure index 3f145a6d48..0d79bca50e 100755 --- a/configure +++ b/configure @@ -102,6 +102,10 @@ with_fuzzers=0 floatabi= native=0 forcesse2=0 +# For CPUs that can benefit from AVX512, it seems GCC generates suboptimal +# instruction scheduling unless you specify a reasonable -mtune= target +avx512flag="-mavx512f -mavx512dq -mavx512bw -mavx512vl -mtune=cascadelake" +avx512vnniflag="-mavx512vnni ${avx512flag}" avx2flag="-mavx2" sse2flag="-msse2" ssse3flag="-mssse3" @@ -250,6 +254,8 @@ case $($cc -v 2>&1) in esac if test $native -eq 1; then + avx512flag="" + avx512vnniflag="" avx2flag="" sse2flag="" ssse3flag="" @@ -1050,6 +1056,75 @@ EOF fi } +check_avx512_intrinsics() { + # Check whether compiler supports AVX512 intrinsics + cat > $test.c << EOF +#include +int main(void) { + __m512i x = _mm512_set1_epi8(2); + const __m512i y = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + x = _mm512_sub_epi8(x, y); + (void)x; + return 0; +} +EOF + if try ${CC} ${CFLAGS} ${avx512flag} $test.c; then + echo "Checking for AVX512 intrinsics ... Yes." | tee -a configure.log + HAVE_AVX512_INTRIN=1 + else + echo "Checking for AVX512 intrinsics ... No." | tee -a configure.log + HAVE_AVX512_INTRIN=0 + fi +} + +check_avx512vnni_intrinsics() { + # Check whether compiler supports AVX512-VNNI intrinsics + cat > $test.c << EOF +#include +int main(void) { + __m512i x = _mm512_set1_epi8(2); + const __m512i y = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + __m512i z = _mm512_setzero_epi32(); + z = _mm512_dpbusd_epi32(z, x, y); + (void)z; + return 0; +} +EOF + if try ${CC} ${CFLAGS} ${avx512vnniflag} $test.c; then + echo "Checking for AVX512VNNI intrinsics ... Yes." | tee -a configure.log + HAVE_AVX512VNNI_INTRIN=1 + else + echo "Checking for AVX512VNNI intrinsics ... No." | tee -a configure.log + HAVE_AVX512VNNI_INTRIN=0 + fi +} + +check_mask_intrinsics() { + # Check whether compiler supports AVX512 k-mask intrinsics + cat > $test.c << EOF +#include +int main(void) { + __mmask16 a = 0xFF; + a = _knot_mask16(a); + (void)a; + return 0; +} +EOF + if try ${CC} ${CFLAGS} ${avx512flag} $test.c; then + echo "Checking for k-mask intrinsics ... Yes." | tee -a configure.log + HAVE_MASK_INTRIN=1 + else + echo "Checking for k-mask intrinsics ... No." | tee -a configure.log + HAVE_MASK_INTRIN=0 + fi +} + check_neon_intrinsics() { # Check whether -mfpu=neon is available on ARM processors. cat > $test.c << EOF @@ -1318,6 +1393,31 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx.lo chunkset_avx.lo compare258_avx.lo adler32_avx.lo" fi + check_avx512_intrinsics + + if test ${HAVE_AVX512_INTRIN} -eq 1; then + CFLAGS="${CFLAGS} -DX86_AVX512 -DX86_AVX512_ADLER32" + SFLAGS="${SFLAGS} -DX86_AVX512 -DX86_AVX512_ADLER32" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_avx512.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_avx512.lo" + + check_mask_intrinsics + + if test ${HAVE_MASK_INTRIN} -eq 1; then + CFLAGS="${CFLAGS} -DX86_MASK_INTRIN" + SFLAGS="${SFLAGS} -DX86_MASK_INTRIN" + fi + fi + + check_avx512vnni_intrinsics + + if test ${HAVE_AVX512VNNI_INTRIN} -eq 1; then + CFLAGS="${CFLAGS} -DX86_AVX512VNNI -DX86_AVX512VNNI_ADLER32" + SFLAGS="${SFLAGS} -DX86_AVX512VNNI -DX86_AVX512VNNI_ADLER32" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_avx512_vnni.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_avx512_vnni.lo" + fi + check_sse4_intrinsics if test ${HAVE_SSE42CRC_INTRIN} -eq 1 || test ${HAVE_SSE42CRC_INLINE_ASM} -eq 1; then @@ -1908,6 +2008,8 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^SRCTOP *=/s#=.*#=$SRCDIR# /^BUILDDIR *=/s#=.*#=$BUILDDIR# /^AVX2FLAG *=/s#=.*#=$avx2flag# +/^AVX512FLAG *=/s#=.*#=$avx512flag# +/^AVX512VNNIFLAG *=/s#=.*#=$avx512vnniflag# /^SSE2FLAG *=/s#=.*#=$sse2flag# /^SSSE3FLAG *=/s#=.*#=$ssse3flag# /^SSE4FLAG *=/s#=.*#=$sse4flag# diff --git a/functable.c b/functable.c index d8b561b5a9..da21a808b2 100644 --- a/functable.c +++ b/functable.c @@ -69,6 +69,12 @@ extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t l #ifdef X86_AVX2_ADLER32 extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); #endif +#ifdef X86_AVX512_ADLER32 +extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len); +#endif +#ifdef X86_AVX512VNNI_ADLER32 +extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len); +#endif #ifdef POWER8_VSX_ADLER32 extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len); #endif @@ -303,6 +309,15 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ if (x86_cpu_has_avx2) functable.adler32 = &adler32_avx2; #endif +#ifdef X86_AVX512_ADLER32 + if (x86_cpu_has_avx512 && x86_cpu_well_suited_avx512) + functable.adler32 = &adler32_avx512; +#endif +#ifdef X86_AVX512VNNI_ADLER32 + if (x86_cpu_has_avx512vnni && x86_cpu_well_suited_avx512) { + functable.adler32 = &adler32_avx512_vnni; + } +#endif #ifdef PPC_VMX_ADLER32 if (power_cpu_has_altivec) functable.adler32 = &adler32_vmx; From a5cc4257c9de2c6b50b4238b9008e0fe4d11422c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 31 Dec 2021 08:15:34 -0800 Subject: [PATCH 188/798] Don't assign C versions of compare258 and longest_match if we don't use them. --- functable.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/functable.c b/functable.c index da21a808b2..c2e23f55e7 100644 --- a/functable.c +++ b/functable.c @@ -555,8 +555,6 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t Z_INTERNAL uint32_t compare258_stub(const unsigned char *src0, const unsigned char *src1) { - functable.compare258 = &compare258_c; - #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) functable.compare258 = &compare258_unaligned_64; @@ -573,6 +571,8 @@ Z_INTERNAL uint32_t compare258_stub(const unsigned char *src0, const unsigned ch if (x86_cpu_has_avx2) functable.compare258 = &compare258_unaligned_avx2; # endif +#else + functable.compare258 = &compare258_c; #endif return functable.compare258(src0, src1); @@ -580,8 +580,6 @@ Z_INTERNAL uint32_t compare258_stub(const unsigned char *src0, const unsigned ch Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { - functable.longest_match = &longest_match_c; - #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) functable.longest_match = &longest_match_unaligned_64; @@ -598,6 +596,8 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { if (x86_cpu_has_avx2) functable.longest_match = &longest_match_unaligned_avx2; # endif +#else + functable.longest_match = &longest_match_c; #endif return functable.longest_match(s, cur_match); @@ -605,8 +605,6 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_match) { - functable.longest_match_slow = &longest_match_slow_c; - #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) functable.longest_match_slow = &longest_match_slow_unaligned_64; @@ -623,6 +621,8 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc if (x86_cpu_has_avx2) functable.longest_match_slow = &longest_match_slow_unaligned_avx2; # endif +#else + functable.longest_match_slow = &longest_match_slow_c; #endif return functable.longest_match_slow(s, cur_match); From 18f6c95d504f643b69b63d86cff5efe669143cac Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 31 Dec 2021 08:22:35 -0800 Subject: [PATCH 189/798] Move generic crc32 assignment to else statement so it can be optimized away if use_byfour is true. --- functable.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/functable.c b/functable.c index c2e23f55e7..0118dc5b74 100644 --- a/functable.c +++ b/functable.c @@ -523,31 +523,28 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t Assert(sizeof(uint64_t) >= sizeof(size_t), "crc32_z takes size_t but internally we have a uint64_t len"); - /* return a function pointer for optimized arches here after a capability test */ - - functable.crc32 = &crc32_generic; - cpu_check_features(); if (use_byfour) { #if BYTE_ORDER == LITTLE_ENDIAN functable.crc32 = crc32_little; -# if defined(ARM_ACLE_CRC_HASH) - if (arm_cpu_has_crc32) - functable.crc32 = crc32_acle; -# endif #elif BYTE_ORDER == BIG_ENDIAN functable.crc32 = crc32_big; -# if defined(S390_CRC32_VX) - if (s390_cpu_has_vx) - functable.crc32 = s390_crc32_vx; -# endif #else # error No endian defined #endif + } else { + functable.crc32 = &crc32_generic; } -#if defined(POWER8_VSX_CRC32) + cpu_check_features(); +#ifdef ARM_ACLE_CRC_HASH + if (arm_cpu_has_crc32) + functable.crc32 = crc32_acle; +#elif defined(POWER8_VSX_CRC32) if (power_cpu_has_arch_2_07) functable.crc32 = crc32_power8; +#elif defined(S390_CRC32_VX) + if (s390_cpu_has_vx) + functable.crc32 = s390_crc32_vx; #endif return functable.crc32(crc, buf, len); From 5c082d926cb7c7a939a8bd3fb760a33659d2ee58 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 4 Jan 2022 08:30:39 -0800 Subject: [PATCH 190/798] Remove use_byfour compile time detection of the existence of four byte integer types since we are targeting newer systems. --- functable.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/functable.c b/functable.c index 0118dc5b74..5d0005a985 100644 --- a/functable.c +++ b/functable.c @@ -519,22 +519,16 @@ Z_INTERNAL uint8_t* chunkmemset_safe_stub(uint8_t *out, unsigned dist, unsigned } Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t len) { - int32_t use_byfour = sizeof(void *) == sizeof(ptrdiff_t); - Assert(sizeof(uint64_t) >= sizeof(size_t), "crc32_z takes size_t but internally we have a uint64_t len"); - if (use_byfour) { #if BYTE_ORDER == LITTLE_ENDIAN - functable.crc32 = crc32_little; + functable.crc32 = crc32_little; #elif BYTE_ORDER == BIG_ENDIAN - functable.crc32 = crc32_big; + functable.crc32 = crc32_big; #else -# error No endian defined + functable.crc32 = &crc32_generic; #endif - } else { - functable.crc32 = &crc32_generic; - } cpu_check_features(); #ifdef ARM_ACLE_CRC_HASH if (arm_cpu_has_crc32) From 23bfa39921fe71788edd02e537726c0fe6f67153 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 31 Dec 2021 09:28:34 -0800 Subject: [PATCH 191/798] Clean up crc32 extern using #elif same as in crc32_stub. --- functable.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/functable.c b/functable.c index 5d0005a985..5fbb22efd8 100644 --- a/functable.c +++ b/functable.c @@ -137,8 +137,7 @@ Z_INTERNAL uint32_t crc32_generic(uint32_t, const unsigned char *, uint64_t); extern uint32_t crc32_acle(uint32_t, const unsigned char *, uint64_t); #elif defined(POWER8_VSX_CRC32) extern uint32_t crc32_power8(uint32_t, const unsigned char *, uint64_t); -#endif -#ifdef S390_CRC32_VX +#elif defined(S390_CRC32_VX) extern uint32_t s390_crc32_vx(uint32_t, const unsigned char *, uint64_t); #endif From faf34c76a43b3d40c11265d2b31ed826f6a84cdb Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 7 Jan 2022 09:44:12 -0800 Subject: [PATCH 192/798] Fixed missing pointers to functions when assigning to functable. --- functable.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/functable.c b/functable.c index 5fbb22efd8..5a607beb2d 100644 --- a/functable.c +++ b/functable.c @@ -330,31 +330,31 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ } Z_INTERNAL uint32_t crc32_fold_reset_stub(crc32_fold *crc) { - functable.crc32_fold_reset = crc32_fold_reset_c; + functable.crc32_fold_reset = &crc32_fold_reset_c; cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_reset = crc32_fold_reset_pclmulqdq; + functable.crc32_fold_reset = &crc32_fold_reset_pclmulqdq; #endif return functable.crc32_fold_reset(crc); } Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len) { - functable.crc32_fold_copy = crc32_fold_copy_c; + functable.crc32_fold_copy = &crc32_fold_copy_c; cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_copy = crc32_fold_copy_pclmulqdq; + functable.crc32_fold_copy = &crc32_fold_copy_pclmulqdq; #endif functable.crc32_fold_copy(crc, dst, src, len); } Z_INTERNAL uint32_t crc32_fold_final_stub(crc32_fold *crc) { - functable.crc32_fold_final = crc32_fold_final_c; + functable.crc32_fold_final = &crc32_fold_final_c; cpu_check_features(); #ifdef X86_PCLMULQDQ_CRC if (x86_cpu_has_pclmulqdq) - functable.crc32_fold_final = crc32_fold_final_pclmulqdq; + functable.crc32_fold_final = &crc32_fold_final_pclmulqdq; #endif return functable.crc32_fold_final(crc); } @@ -522,22 +522,22 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t "crc32_z takes size_t but internally we have a uint64_t len"); #if BYTE_ORDER == LITTLE_ENDIAN - functable.crc32 = crc32_little; + functable.crc32 = &crc32_little; #elif BYTE_ORDER == BIG_ENDIAN - functable.crc32 = crc32_big; + functable.crc32 = &crc32_big; #else functable.crc32 = &crc32_generic; #endif cpu_check_features(); #ifdef ARM_ACLE_CRC_HASH if (arm_cpu_has_crc32) - functable.crc32 = crc32_acle; + functable.crc32 = &crc32_acle; #elif defined(POWER8_VSX_CRC32) if (power_cpu_has_arch_2_07) - functable.crc32 = crc32_power8; + functable.crc32 = &crc32_power8; #elif defined(S390_CRC32_VX) if (s390_cpu_has_vx) - functable.crc32 = s390_crc32_vx; + functable.crc32 = &s390_crc32_vx; #endif return functable.crc32(crc, buf, len); From 5bc87f1581c4475669427a57b1a3b60bf9d145f2 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 26 Dec 2021 19:56:12 -0800 Subject: [PATCH 193/798] Use memcpy for unaligned reads. Co-authored-by: Matija Skala --- chunkset.c | 30 ++++++++-------------- compare258.c | 16 +++++++----- deflate.h | 62 +++++++++++++++------------------------------ insert_string_tpl.h | 2 +- match_tpl.h | 10 ++++---- 5 files changed, 47 insertions(+), 73 deletions(-) diff --git a/chunkset.c b/chunkset.c index b07e6f4827..48cdd9df6f 100644 --- a/chunkset.c +++ b/chunkset.c @@ -5,7 +5,7 @@ #include "zbuild.h" #include "zutil.h" -// We need sizeof(chunk_t) to be 8, no matter what. +/* Define 8 byte chunks differently depending on unaligned support */ #if defined(UNALIGNED64_OK) typedef uint64_t chunk_t; #elif defined(UNALIGNED_OK) @@ -34,27 +34,24 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { #if defined(UNALIGNED64_OK) uint32_t half_chunk; - half_chunk = *(uint32_t *)from; + memcpy(&half_chunk, from, sizeof(half_chunk)); *chunk = 0x0000000100000001 * (uint64_t)half_chunk; #elif defined(UNALIGNED_OK) - chunk->u32[0] = *(uint32_t *)from; + memcpy(&chunk->u32[0], from, sizeof(chunk->u32[0])); chunk->u32[1] = chunk->u32[0]; #else uint8_t *chunkptr = (uint8_t *)chunk; - memcpy(chunkptr, from, 4); - memcpy(chunkptr+4, from, 4); + memcpy(chunkptr, from, sizeof(uint32_t)); + memcpy(chunkptr+4, from, sizeof(uint32_t)); #endif } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - *chunk = *(uint64_t *)from; -#elif defined(UNALIGNED_OK) - uint32_t* p = (uint32_t *)from; - chunk->u32[0] = p[0]; - chunk->u32[1] = p[1]; +#if defined(UNALIGNED_OK) && !defined(UNALIGNED64_OK) + memcpy(&chunk->u32[0], from, sizeof(chunk->u32[0])); + memcpy(&chunk->u32[1], from+4, sizeof(chunk->u32[1])); #else - memcpy(chunk, from, sizeof(chunk_t)); + memcpy(chunk, from, sizeof(uint64_t)); #endif } @@ -63,14 +60,7 @@ static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { } static inline void storechunk(uint8_t *out, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - *(uint64_t *)out = *chunk; -#elif defined(UNALIGNED_OK) - ((uint32_t *)out)[0] = chunk->u32[0]; - ((uint32_t *)out)[1] = chunk->u32[1]; -#else - memcpy(out, chunk, sizeof(chunk_t)); -#endif + memcpy(out, chunk, sizeof(uint64_t)); } #define CHUNKSIZE chunksize_c diff --git a/compare258.c b/compare258.c index f4f1936c45..e6e63f249e 100644 --- a/compare258.c +++ b/compare258.c @@ -123,10 +123,12 @@ static inline uint32_t compare256_unaligned_32_static(const unsigned char *src0, uint32_t len = 0; do { - uint32_t sv = *(uint32_t *)src0; - uint32_t mv = *(uint32_t *)src1; - uint32_t diff = sv ^ mv; + uint32_t sv, mv, diff; + memcpy(&sv, src0, sizeof(sv)); + memcpy(&mv, src1, sizeof(mv)); + + diff = sv ^ mv; if (diff) { uint32_t match_byte = __builtin_ctz(diff) / 8; return len + match_byte; @@ -170,10 +172,12 @@ static inline uint32_t compare256_unaligned_64_static(const unsigned char *src0, uint32_t len = 0; do { - uint64_t sv = *(uint64_t *)src0; - uint64_t mv = *(uint64_t *)src1; - uint64_t diff = sv ^ mv; + uint64_t sv, mv, diff; + + memcpy(&sv, src0, sizeof(sv)); + memcpy(&mv, src1, sizeof(mv)); + diff = sv ^ mv; if (diff) { uint64_t match_byte = __builtin_ctzll(diff) / 8; return len + (uint32_t)match_byte; diff --git a/deflate.h b/deflate.h index 94ff239ce4..030db4f098 100644 --- a/deflate.h +++ b/deflate.h @@ -302,13 +302,11 @@ typedef enum { * IN assertion: there is enough room in pending_buf. */ static inline void put_short(deflate_state *s, uint16_t w) { -#if defined(UNALIGNED_OK) - *(uint16_t *)(&s->pending_buf[s->pending]) = w; - s->pending += 2; -#else - put_byte(s, (w & 0xff)); - put_byte(s, ((w >> 8) & 0xff)); +#if BYTE_ORDER == BIG_ENDIAN + w = ZSWAP16(w); #endif + memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); + s->pending += 2; } /* =========================================================================== @@ -316,8 +314,11 @@ static inline void put_short(deflate_state *s, uint16_t w) { * IN assertion: there is enough room in pending_buf. */ static inline void put_short_msb(deflate_state *s, uint16_t w) { - put_byte(s, ((w >> 8) & 0xff)); - put_byte(s, (w & 0xff)); +#if BYTE_ORDER == LITTLE_ENDIAN + w = ZSWAP16(w); +#endif + memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); + s->pending += 2; } /* =========================================================================== @@ -325,15 +326,11 @@ static inline void put_short_msb(deflate_state *s, uint16_t w) { * IN assertion: there is enough room in pending_buf. */ static inline void put_uint32(deflate_state *s, uint32_t dw) { -#if defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = dw; - s->pending += 4; -#else - put_byte(s, (dw & 0xff)); - put_byte(s, ((dw >> 8) & 0xff)); - put_byte(s, ((dw >> 16) & 0xff)); - put_byte(s, ((dw >> 24) & 0xff)); +#if BYTE_ORDER == BIG_ENDIAN + dw = ZSWAP32(dw); #endif + memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); + s->pending += 4; } /* =========================================================================== @@ -341,15 +338,11 @@ static inline void put_uint32(deflate_state *s, uint32_t dw) { * IN assertion: there is enough room in pending_buf. */ static inline void put_uint32_msb(deflate_state *s, uint32_t dw) { -#if defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = ZSWAP32(dw); - s->pending += 4; -#else - put_byte(s, ((dw >> 24) & 0xff)); - put_byte(s, ((dw >> 16) & 0xff)); - put_byte(s, ((dw >> 8) & 0xff)); - put_byte(s, (dw & 0xff)); +#if BYTE_ORDER == LITTLE_ENDIAN + dw = ZSWAP32(dw); #endif + memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); + s->pending += 4; } /* =========================================================================== @@ -357,24 +350,11 @@ static inline void put_uint32_msb(deflate_state *s, uint32_t dw) { * IN assertion: there is enough room in pending_buf. */ static inline void put_uint64(deflate_state *s, uint64_t lld) { -#if defined(UNALIGNED64_OK) - *(uint64_t *)(&s->pending_buf[s->pending]) = lld; - s->pending += 8; -#elif defined(UNALIGNED_OK) - *(uint32_t *)(&s->pending_buf[s->pending]) = lld & 0xffffffff; - s->pending += 4; - *(uint32_t *)(&s->pending_buf[s->pending]) = (lld >> 32) & 0xffffffff; - s->pending += 4; -#else - put_byte(s, (lld & 0xff)); - put_byte(s, ((lld >> 8) & 0xff)); - put_byte(s, ((lld >> 16) & 0xff)); - put_byte(s, ((lld >> 24) & 0xff)); - put_byte(s, ((lld >> 32) & 0xff)); - put_byte(s, ((lld >> 40) & 0xff)); - put_byte(s, ((lld >> 48) & 0xff)); - put_byte(s, ((lld >> 56) & 0xff)); +#if BYTE_ORDER == BIG_ENDIAN + lld = ZSWAP64(lld); #endif + memcpy(&s->pending_buf[s->pending], &lld, sizeof(lld)); + s->pending += 8; } #define MIN_LOOKAHEAD (STD_MAX_MATCH + STD_MIN_MATCH + 1) diff --git a/insert_string_tpl.h b/insert_string_tpl.h index ad88275bfc..7d3e46c897 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -31,7 +31,7 @@ #ifndef HASH_CALC_READ # ifdef UNALIGNED_OK # define HASH_CALC_READ \ - val = *(uint32_t *)(strstart); + memcpy(&val, strstart, sizeof(val)); # else # define HASH_CALC_READ \ val = ((uint32_t)(strstart[0])); \ diff --git a/match_tpl.h b/match_tpl.h index e4e31e9819..e11abfbb72 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -85,11 +85,11 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { } #endif - scan_end = *(bestcmp_t *)(scan+offset); + memcpy(&scan_end, scan+offset, sizeof(bestcmp_t)); #ifndef UNALIGNED_OK - scan_end0 = *(bestcmp_t *)(scan+offset+1); + memcpy(&scan_end0, scan+offset+1, sizeof(bestcmp_t)); #else - scan_start = *(bestcmp_t *)(scan); + memcpy(&scan_start, scan, sizeof(bestcmp_t)); #endif mbase_end = (mbase_start+offset); @@ -207,9 +207,9 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif } #endif - scan_end = *(bestcmp_t *)(scan+offset); + memcpy(&scan_end, scan+offset, sizeof(bestcmp_t)); #ifndef UNALIGNED_OK - scan_end0 = *(bestcmp_t *)(scan+offset+1); + memcpy(&scan_end0, scan+offset+1, sizeof(bestcmp_t)); #endif #ifdef LONGEST_MATCH_SLOW /* Look for a better string offset */ From 5ef8e3b979065c04b863b71065323c2635cdbf02 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 4 Jan 2022 10:37:24 -0500 Subject: [PATCH 194/798] Add SSE4.1 detection Code leveraging this for the adler checksum is forthcoming --- arch/x86/x86.c | 2 ++ arch/x86/x86.h | 1 + cmake/detect-intrinsics.cmake | 38 +++++++++++++++++++++++++---- configure | 45 +++++++++++++++++++++++++++++++---- 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/arch/x86/x86.c b/arch/x86/x86.c index f02e1a3491..065a717032 100644 --- a/arch/x86/x86.c +++ b/arch/x86/x86.c @@ -24,6 +24,7 @@ Z_INTERNAL int x86_cpu_has_avx512; Z_INTERNAL int x86_cpu_has_avx512vnni; Z_INTERNAL int x86_cpu_has_sse2; Z_INTERNAL int x86_cpu_has_ssse3; +Z_INTERNAL int x86_cpu_has_sse41; Z_INTERNAL int x86_cpu_has_sse42; Z_INTERNAL int x86_cpu_has_pclmulqdq; Z_INTERNAL int x86_cpu_has_tzcnt; @@ -78,6 +79,7 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_has_sse2 = edx & 0x4000000; x86_cpu_has_ssse3 = ecx & 0x200; + x86_cpu_has_sse41 = ecx & 0x80000; x86_cpu_has_sse42 = ecx & 0x100000; x86_cpu_has_pclmulqdq = ecx & 0x2; x86_cpu_well_suited_avx512 = 0; diff --git a/arch/x86/x86.h b/arch/x86/x86.h index 4274ed09f6..80da6f32aa 100644 --- a/arch/x86/x86.h +++ b/arch/x86/x86.h @@ -11,6 +11,7 @@ extern int x86_cpu_has_avx512; extern int x86_cpu_has_avx512vnni; extern int x86_cpu_has_sse2; extern int x86_cpu_has_ssse3; +extern int x86_cpu_has_sse41; extern int x86_cpu_has_sse42; extern int x86_cpu_has_pclmulqdq; extern int x86_cpu_has_tzcnt; diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 9f7a971907..2facf50513 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -294,20 +294,48 @@ macro(check_ssse3_intrinsics) ) endmacro() -macro(check_sse4_intrinsics) +macro(check_sse41_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "Intel") if(CMAKE_HOST_UNIX OR APPLE) - set(SSE4FLAG "-msse4.2") + set(SSE41FLAG "-msse4.1") else() - set(SSE4FLAG "/arch:SSE4.2") + set(SSE41FLAG "/arch:SSE4.1") endif() elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) - set(SSE4FLAG "-msse4.2") + set(SSE41FLAG "-msse4.1") + endif() + endif() + # Check whether compiler supports SSE4.1 intrinsics + set(CMAKE_REQUIRED_FLAGS "${SSE41FLAG}") + check_c_source_compile_or_run( + "#include + int main(void) { + __m128i u, v, w; + u = _mm_set1_epi8(1); + v = _mm_set1_epi8(2); + w = _mm_sad_epu8(u, v); + (void)w; + return 0; + }" + HAVE_SSE41_INTRIN + ) +endmacro() + +macro(check_sse42_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "Intel") + if(CMAKE_HOST_UNIX OR APPLE) + set(SSE42FLAG "-msse4.2") + else() + set(SSE42FLAG "/arch:SSE4.2") + endif() + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(SSE42FLAG "-msse4.2") endif() endif() # Check whether compiler supports SSE4 CRC inline asm - set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG}") + set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG}") check_c_source_compile_or_run( "int main(void) { unsigned val = 0, h = 0; diff --git a/configure b/configure index 0d79bca50e..5b1c5e65b2 100755 --- a/configure +++ b/configure @@ -109,7 +109,7 @@ avx512vnniflag="-mavx512vnni ${avx512flag}" avx2flag="-mavx2" sse2flag="-msse2" ssse3flag="-mssse3" -sse4flag="-msse4" +sse41flag="-msse4.1" sse42flag="-msse4.2" pclmulflag="-mpclmul" acleflag= @@ -1232,7 +1232,30 @@ EOF fi } -check_sse4_intrinsics() { +check_sse41_intrinsics() { + # Check whether compiler supports SSE4.1 intrinsics + cat > $test.c << EOF +#include +int main(void) +{ + __m128i u, v, w; + u = _mm_set1_epi8(1); + v = _mm_set1_epi8(2); + w = _mm_sad_epu8(u, v); + (void)w; + return 0; +} +EOF + if try ${CC} ${CFLAGS} ${sse41flag} $test.c; then + echo "Checking for SSE4.1 intrinsics ... Yes." | tee -a configure.log + HAVE_SSE41_INTRIN=1 + else + echo "Checking for SSE4.1 intrinsics ... No." | tee -a configure.log + HAVE_SSE41_INTRIN=0 + fi +} + +check_sse42_intrinsics() { # Check whether compiler supports SSE4 CRC inline asm cat > $test.c << EOF int main(void) { @@ -1418,7 +1441,16 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_avx512_vnni.lo" fi - check_sse4_intrinsics + check_sse41_intrinsics + + if test ${HAVE_SSE41_INTRIN} -eq 1; then + CFLAGS="${CFLAGS} -DX86_SSE41_ADLER32" + SFLAGS="${SFLAGS} -DX86_SSE41_ADLER32" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_sse41.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_sse41.o" + fi + + check_sse42_intrinsics if test ${HAVE_SSE42CRC_INTRIN} -eq 1 || test ${HAVE_SSE42CRC_INLINE_ASM} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42_CRC_HASH" @@ -1432,6 +1464,7 @@ case "${ARCH}" in ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} insert_string_sse.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse.lo" fi + if test ${HAVE_SSE42CMPSTR_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42_CMP_STR" SFLAGS="${SFLAGS} -DX86_SSE42_CMP_STR" @@ -1876,7 +1909,8 @@ echo sharedlibdir = $sharedlibdir >> configure.log echo uname = $uname >> configure.log echo sse2flag = $sse2flag >> configure.log echo ssse3flag = $ssse3flag >> configure.log -echo sse4flag = $sse4flag >> configure.log +echo sse41flag = $sse41flag >> configure.log +echo sse42flag = $sse42flag >> configure.log echo pclmulflag = $pclmulflag >> configure.log echo acleflag = $acleflag >> configure.log echo neonflag = $neonflag >> configure.log @@ -2012,7 +2046,8 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^AVX512VNNIFLAG *=/s#=.*#=$avx512vnniflag# /^SSE2FLAG *=/s#=.*#=$sse2flag# /^SSSE3FLAG *=/s#=.*#=$ssse3flag# -/^SSE4FLAG *=/s#=.*#=$sse4flag# +/^SSE41FLAG *=/s#=.*#=$sse41flag# +/^SSE42FLAG *=/s#=.*#=$sse42flag# /^PCLMULFLAG *=/s#=.*#=$pclmulflag# /^ACLEFLAG *=/s#=.*#=$acleflag# /^NEONFLAG *=/s#=.*#=$neonflag# From 49d1704a1800c0b01241f13dee1dafe2961d1541 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 4 Jan 2022 10:38:39 -0500 Subject: [PATCH 195/798] Added an SSE4 optimized adler32 checksum This variant uses the lower number of cycles psadw insruction in place of pmaddubsw for the running sum that does not need multiplication. This allows this sum to be done independently, partially overlapping the running "sum2" half of the checksum. We also have moved the shift outside of the loop, breaking a small data dependency chain. The code also now does a vectorized horizontal sum without having to rebase to the adler32 base, as NMAX is defined as the maximum number of scalar sums that can be peformed, so we're actually safe in doing this without upgrading to higher precision. We can do a partial horizontal sum because psadw only ends up accumulating 16 bit words in 2 vector lanes, the other two can safely be assumed as 0. --- CMakeLists.txt | 39 +++++++++---- README.md | 3 +- arch/x86/Makefile.in | 22 +++++--- arch/x86/adler32_sse41.c | 118 +++++++++++++++++++++++++++++++++++++++ configure | 2 +- functable.c | 7 +++ 6 files changed, 170 insertions(+), 21 deletions(-) create mode 100644 arch/x86/adler32_sse41.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 526065f320..956f735634 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,7 +110,8 @@ elseif(BASEARCH_X86_FOUND) option(WITH_AVX512VNNI "Build with AVX512 VNNI extensions" ON) option(WITH_SSE2 "Build with SSE2" ON) option(WITH_SSSE3 "Build with SSSE3" ON) - option(WITH_SSE4 "Build with SSE4" ON) + option(WITH_SSE41 "Build with SSE41" ON) + option(WITH_SSE42 "Build with SSE42" ON) option(WITH_PCLMULQDQ "Build with PCLMULQDQ" ON) endif() @@ -125,7 +126,8 @@ mark_as_advanced(FORCE WITH_DFLTCC_INFLATE WITH_CRC32_VX WITH_AVX2 WITH_SSE2 - WITH_SSSE3 WITH_SSE4 + WITH_SSSE3 WITH_SSE41 + WITH_SSE42 WITH_PCLMULQDQ WITH_ALTIVEC WITH_POWER8 @@ -753,14 +755,26 @@ if(WITH_OPTIM) set(WITH_AVX512VNNI OFF) endif() endif() - if(WITH_SSE4) - check_sse4_intrinsics() + if(WITH_SSE41) + check_sse41_intrinsics() + if(HAVE_SSE41_INTRIN) + add_definitions(-DX86_SSE41 -DX86_SSE41_ADLER32) + set(SSE41_SRCS ${ARCHDIR}/adler32_sse41.c) + add_feature_info(SSE4_ADLER32 1 "Support SSE41-accelerated adler32, using \"${SSE41FLAG}\"") + list(APPEND ZLIB_ARCH_SRCS ${SSE41_SRCS}) + set_property(SOURCE ${SSE41_SRCS} PROPERTY COMPILE_FLAGS "${SSE41FLAG} ${NOLTOFLAG}") + else() + set(WITH_SSE41 OFF) + endif() + endif() + if(WITH_SSE42) + check_sse42_intrinsics() if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) add_definitions(-DX86_SSE42_CRC_HASH) set(SSE42_SRCS ${ARCHDIR}/insert_string_sse.c) - add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE4FLAG}\"") + add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE42FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") + set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") if(HAVE_SSE42CRC_INTRIN) add_definitions(-DX86_SSE42_CRC_INTRIN) endif() @@ -768,9 +782,9 @@ if(WITH_OPTIM) if(HAVE_SSE42CMPSTR_INTRIN) add_definitions(-DX86_SSE42_CMP_STR) set(SSE42_SRCS ${ARCHDIR}/compare258_sse.c) - add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE4FLAG}\"") + add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE42FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE4FLAG} ${NOLTOFLAG}") + set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") endif() if(NOT HAVE_SSE42CRC_INLINE_ASM AND NOT HAVE_SSE42CRC_INTRIN AND NOT HAVE_SSE42CMPSTR_INTRIN) set(WITH_SSE4 OFF) @@ -805,14 +819,14 @@ if(WITH_OPTIM) set(WITH_SSSE3 OFF) endif() endif() - if(WITH_PCLMULQDQ AND WITH_SSSE3 AND WITH_SSE4) + if(WITH_PCLMULQDQ AND WITH_SSSE3 AND WITH_SSE42) check_pclmulqdq_intrinsics() if(HAVE_PCLMULQDQ_INTRIN AND HAVE_SSSE3_INTRIN) add_definitions(-DX86_PCLMULQDQ_CRC) set(PCLMULQDQ_SRCS ${ARCHDIR}/crc32_fold_pclmulqdq.c) - add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG}\"") + add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) - set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE4FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") + set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") else() set(WITH_PCLMULQDQ OFF) endif() @@ -1441,7 +1455,8 @@ elseif(BASEARCH_X86_FOUND) add_feature_info(WITH_AVX512VNNI WITH_AVX512VNNI "Build with AVX512 VNNI") add_feature_info(WITH_SSE2 WITH_SSE2 "Build with SSE2") add_feature_info(WITH_SSSE3 WITH_SSSE3 "Build with SSSE3") - add_feature_info(WITH_SSE4 WITH_SSE4 "Build with SSE4") + add_feature_info(WITH_SSE41 WITH_SSE41 "Build with SSE41") + add_feature_info(WITH_SSE42 WITH_SSE42 "Build with SSE42") add_feature_info(WITH_PCLMULQDQ WITH_PCLMULQDQ "Build with PCLMULQDQ") endif() diff --git a/README.md b/README.md index 0da19e4077..44e63db302 100644 --- a/README.md +++ b/README.md @@ -200,7 +200,8 @@ Advanced Build Options | WITH_AVX512 | | Build with AVX512 intrinsics | ON | | WITH_AVX512VNNI | | Build with AVX512VNNI intrinsics | ON | | WITH_SSE2 | | Build with SSE2 intrinsics | ON | -| WITH_SSE4 | | Build with SSE4 intrinsics | ON | +| WITH_SSE41 | | Build with SSE41 intrinsics | ON | +| WITH_SSE42 | | Build with SSE42 intrinsics | ON | | WITH_PCLMULQDQ | | Build with PCLMULQDQ intrinsics | ON | | WITH_ACLE | --without-acle | Build with ACLE intrinsics | ON | | WITH_NEON | --without-neon | Build with NEON intrinsics | ON | diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 3e92738eee..f54a695c22 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -13,7 +13,8 @@ AVX512VNNIFLAG=-mavx512vnni AVX2FLAG=-mavx2 SSE2FLAG=-msse2 SSSE3FLAG=-mssse3 -SSE4FLAG=-msse4 +SSE41FLAG=-msse4.1 +SSE42FLAG=-msse4.2 PCLMULFLAG=-mpclmul NOLTOFLAG= @@ -26,6 +27,7 @@ all: \ adler32_avx.o adler32_avx.lo \ adler32_avx512.o adler32_avx512.lo \ adler32_avx512_vnni.o adler32_avx512_vnni.lo \ + adler32_sse41.o adler32_sse41.lo \ adler32_ssse3.o adler32_ssse3.lo \ chunkset_avx.o chunkset_avx.lo \ chunkset_sse.o chunkset_sse.lo \ @@ -61,22 +63,22 @@ compare258_avx.lo: $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c compare258_sse.o: - $(CC) $(CFLAGS) $(SSE4FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c + $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c compare258_sse.lo: - $(CC) $(SFLAGS) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c + $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c insert_string_sse.o: - $(CC) $(CFLAGS) $(SSE4FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c + $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c insert_string_sse.lo: - $(CC) $(SFLAGS) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c + $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c crc32_fold_pclmulqdq.o: - $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c + $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c crc32_fold_pclmulqdq.lo: - $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE4FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c + $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c slide_hash_avx.o: $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx.c @@ -108,6 +110,12 @@ adler32_avx512_vnni.o: $(SRCDIR)/adler32_avx512_vnni.c adler32_avx512_vnni.lo: $(SRCDIR)/adler32_avx512_vnni.c $(CC) $(SFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c +adler32_sse41.o: $(SRCDIR)/adler32_sse41.c + $(CC) $(CFLAGS) $(SSE41FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_sse41.c + +adler32_sse41.lo: $(SRCDIR)/adler32_sse41.c + $(CC) $(SFLAGS) $(SSE41FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_sse41.c + adler32_ssse3.o: $(SRCDIR)/adler32_ssse3.c $(CC) $(CFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c diff --git a/arch/x86/adler32_sse41.c b/arch/x86/adler32_sse41.c new file mode 100644 index 0000000000..1e0f0ca463 --- /dev/null +++ b/arch/x86/adler32_sse41.c @@ -0,0 +1,118 @@ +/* adler32_sse41.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Authors: + * Adam Stylinski + * Brian Bockelman + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" +#include "../../zutil.h" + +#include "../../adler32_p.h" + +#ifdef X86_SSE41_ADLER32 + +#include + +static inline uint32_t partial_hsum(__m128i x) { + __m128i second_int = _mm_bsrli_si128(x, 8); + __m128i sum = _mm_add_epi32(x, second_int); + return _mm_cvtsi128_si32(sum); +} + +static inline uint32_t hsum(__m128i x) { + __m128i sum1 = _mm_unpackhi_epi64(x, x); + __m128i sum2 = _mm_add_epi32(x, sum1); + __m128i sum3 = _mm_shuffle_epi32(sum2, 0x01); + __m128i sum4 = _mm_add_epi32(sum2, sum3); + return _mm_cvtsi128_si32(sum4); +} + +Z_INTERNAL uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size_t len) { + uint32_t sum2; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) + return adler32_len_1(adler, buf, sum2); + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (UNLIKELY(buf == NULL)) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (UNLIKELY(len < 16)) + return adler32_len_16(adler, buf, len, sum2); + + const __m128i dot2v = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i dot3v = _mm_set1_epi16(1); + const __m128i zero = _mm_setzero_si128(); + + __m128i vs1 = _mm_cvtsi32_si128(adler); + __m128i vs2 = _mm_cvtsi32_si128(sum2); + + while (len >= 16) { + __m128i vs1_0 = vs1; + __m128i vs3 = _mm_setzero_si128(); + + int k = (len < NMAX ? (int)len : NMAX); + k -= k % 16; + len -= k; + + /* Aligned version of the loop */ + if (((uintptr_t)buf & 15) == 0) { + while (k >= 16) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + __m128i vbuf = _mm_load_si128((__m128i*)buf); + buf += 16; + k -= 16; + + __m128i v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + __m128i v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + __m128i vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + } else { + while (k >= 16) { + __m128i vbuf = _mm_loadu_si128((__m128i*)buf); + buf += 16; + k -= 16; + + __m128i v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + __m128i v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + __m128i vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + } + + vs3 = _mm_slli_epi32(vs3, 4); + vs2 = _mm_add_epi32(vs2, vs3); + + /* We don't actually need to do a full horizontal sum, since psadbw is actually doing + * a partial reduction sum implicitly and only summing to integers in vector positions + * 0 and 2. This saves us some contention on the shuffle port(s) */ + adler = partial_hsum(vs1) % BASE; + sum2 = hsum(vs2) % BASE; + + vs1 = _mm_cvtsi32_si128(adler); + vs2 = _mm_cvtsi32_si128(sum2); + } + + /* Process tail (len < 16). */ + return adler32_len_16(adler, buf, len, sum2); +} + +#endif diff --git a/configure b/configure index 5b1c5e65b2..2c17507a86 100755 --- a/configure +++ b/configure @@ -1447,7 +1447,7 @@ case "${ARCH}" in CFLAGS="${CFLAGS} -DX86_SSE41_ADLER32" SFLAGS="${SFLAGS} -DX86_SSE41_ADLER32" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_sse41.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_sse41.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_sse41.lo" fi check_sse42_intrinsics diff --git a/functable.c b/functable.c index 5a607beb2d..ccb0b69a30 100644 --- a/functable.c +++ b/functable.c @@ -63,6 +63,9 @@ extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t le #ifdef PPC_VMX_ADLER32 extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len); #endif +#ifdef X86_SSE41_ADLER32 +extern uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size_t len); +#endif #ifdef X86_SSSE3_ADLER32 extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); #endif @@ -304,6 +307,10 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ if (x86_cpu_has_ssse3) functable.adler32 = &adler32_ssse3; #endif +#ifdef X86_SSE41_ADLER32 + if (x86_cpu_has_sse41) + functable.adler32 = &adler32_sse41; +#endif #ifdef X86_AVX2_ADLER32 if (x86_cpu_has_avx2) functable.adler32 = &adler32_avx2; From f20f9b610c286fe55e309c8ff24ac9ac795c78e5 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 15 Dec 2021 14:21:58 -0800 Subject: [PATCH 196/798] VPCLMULQDQ implementation for Intel's CRC32 folding. Based on PR https://github.com/jtkukunas/zlib/pull/28. Co-authored-by: Wangyang Guo --- CMakeLists.txt | 19 ++++++ README.md | 3 +- arch/x86/INDEX.md | 1 + arch/x86/Makefile.in | 8 +++ arch/x86/crc32_fold_pclmulqdq.c | 15 +++++ arch/x86/crc32_fold_vpclmulqdq.c | 108 +++++++++++++++++++++++++++++++ arch/x86/x86.c | 3 + arch/x86/x86.h | 1 + cmake/detect-intrinsics.cmake | 26 ++++++++ configure | 39 +++++++++++ 10 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 arch/x86/crc32_fold_vpclmulqdq.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 956f735634..ecb9ac6b27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,7 @@ elseif(BASEARCH_X86_FOUND) option(WITH_SSE41 "Build with SSE41" ON) option(WITH_SSE42 "Build with SSE42" ON) option(WITH_PCLMULQDQ "Build with PCLMULQDQ" ON) + option(WITH_VPCLMULQDQ "Build with VPCLMULQDQ" ON) endif() option(INSTALL_UTILS "Copy minigzip and minideflate during install" OFF) @@ -827,11 +828,28 @@ if(WITH_OPTIM) add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${PCLMULQDQ_SRCS}) set_property(SOURCE ${PCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${SSSE3FLAG} ${SSE42FLAG} ${PCLMULFLAG} ${NOLTOFLAG}") + + if(WITH_VPCLMULQDQ AND WITH_AVX512) + check_vpclmulqdq_intrinsics() + if(HAVE_VPCLMULQDQ_INTRIN AND HAVE_AVX512_INTRIN) + add_definitions(-DX86_VPCLMULQDQ_CRC) + set(VPCLMULQDQ_SRCS ${ARCHDIR}/crc32_fold_vpclmulqdq.c) + add_feature_info(VPCLMUL_CRC 1 "Support CRC hash generation using VPCLMULQDQ, using \"${VPCLMULFLAG} ${AVX512FLAG}\"") + list(APPEND ZLIB_ARCH_SRCS ${VPCLMULQDQ_SRCS}) + set_property(SOURCE ${VPCLMULQDQ_SRCS} PROPERTY COMPILE_FLAGS "${VPCLMULFLAG} ${AVX512FLAG} ${NOLTOFLAG}") + else() + set(WITH_VPCLMULQDQ OFF) + endif() + else() + set(WITH_VPCLMULQDQ OFF) + endif() else() set(WITH_PCLMULQDQ OFF) + set(WITH_VPCLMULQDQ OFF) endif() else() set(WITH_PCLMULQDQ OFF) + set(WITH_VPCLMULQDQ OFF) endif() endif() endif() @@ -1458,6 +1476,7 @@ elseif(BASEARCH_X86_FOUND) add_feature_info(WITH_SSE41 WITH_SSE41 "Build with SSE41") add_feature_info(WITH_SSE42 WITH_SSE42 "Build with SSE42") add_feature_info(WITH_PCLMULQDQ WITH_PCLMULQDQ "Build with PCLMULQDQ") + add_feature_info(WITH_VPCLMULQDQ WITH_VPCLMULQDQ "Build with VPCLMULQDQ") endif() add_feature_info(INSTALL_UTILS INSTALL_UTILS "Copy minigzip and minideflate during install") diff --git a/README.md b/README.md index 44e63db302..79d6648bdb 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Features * Deflate medium and quick algorithms based on Intels zlib fork * Support for CPU intrinsics when available * Adler32 implementation using SSSE3, AVX2, AVX512, AVX512-VNNI, Neon, VMX & VSX - * CRC32-B implementation using PCLMULQDQ & ACLE + * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, & ACLE * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX * Compare256/258 implementations using SSE4.2 & AVX2 @@ -203,6 +203,7 @@ Advanced Build Options | WITH_SSE41 | | Build with SSE41 intrinsics | ON | | WITH_SSE42 | | Build with SSE42 intrinsics | ON | | WITH_PCLMULQDQ | | Build with PCLMULQDQ intrinsics | ON | +| WITH_VPCLMULQDQ | --without-vpclmulqdq | Build with VPCLMULQDQ intrinsics | ON | | WITH_ACLE | --without-acle | Build with ACLE intrinsics | ON | | WITH_NEON | --without-neon | Build with NEON intrinsics | ON | | WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | ON | diff --git a/arch/x86/INDEX.md b/arch/x86/INDEX.md index e20245a5e1..af987a25c4 100644 --- a/arch/x86/INDEX.md +++ b/arch/x86/INDEX.md @@ -5,4 +5,5 @@ Contents |:-|:-| |deflate_quick.c|SSE4 optimized deflate strategy for use as level 1| |crc32_fold_pclmulqdq.c|SSE4 + PCLMULQDQ optimized CRC folding implementation| +|crc32_fold_vpclmulqdq.c|VPCLMULQDQ optimized CRC folding implementation| |slide_hash_sse2.c|SSE2 optimized slide_hash| diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index f54a695c22..0a1dc07662 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -16,6 +16,7 @@ SSSE3FLAG=-mssse3 SSE41FLAG=-msse4.1 SSE42FLAG=-msse4.2 PCLMULFLAG=-mpclmul +VPCLMULFLAG=-mvpclmulqdq NOLTOFLAG= SRCDIR=. @@ -35,6 +36,7 @@ all: \ compare258_sse.o compare258_sse.lo \ insert_string_sse.o insert_string_sse.lo \ crc32_fold_pclmulqdq.o crc32_fold_pclmulqdq.lo \ + crc32_fold_vpclmulqdq.o crc32_fold_vpclmulqdq.lo \ slide_hash_avx.o slide_hash_avx.lo \ slide_hash_sse.o slide_hash_sse.lo @@ -80,6 +82,12 @@ crc32_fold_pclmulqdq.o: crc32_fold_pclmulqdq.lo: $(CC) $(SFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c +crc32_fold_vpclmulqdq.o: + $(CC) $(CFLAGS) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_vpclmulqdq.c + +crc32_fold_vpclmulqdq.lo: + $(CC) $(SFLAGS) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_vpclmulqdq.c + slide_hash_avx.o: $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx.c diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index d07ffb4085..1434357a87 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -26,6 +26,11 @@ #include "../../crc32_fold.h" +#ifdef X86_VPCLMULQDQ_CRC +extern size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len); +#endif + static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { const __m128i xmm_fold4 = _mm_set_epi32( 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); @@ -275,6 +280,16 @@ Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const u xmm_crc_part = _mm_setzero_si128(); } +#ifdef X86_VPCLMULQDQ_CRC + if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { + size_t n = fold_16_vpclmulqdq(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, dst, src, len); + + len -= n; + src += n; + dst += n; + } +#endif + while (len >= 64) { crc32_fold_load((__m128i *)src, &xmm_t0, &xmm_t1, &xmm_t2, &xmm_t3); diff --git a/arch/x86/crc32_fold_vpclmulqdq.c b/arch/x86/crc32_fold_vpclmulqdq.c new file mode 100644 index 0000000000..9ed54b37e3 --- /dev/null +++ b/arch/x86/crc32_fold_vpclmulqdq.c @@ -0,0 +1,108 @@ +/* crc32_fold_vpclmulqdq.c -- VPCMULQDQ-based CRC32 folding implementation. + * Copyright Wangyang Guo (wangyang.guo@intel.com) + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef X86_VPCLMULQDQ_CRC +#include "../../zutil.h" + +#include + +size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len) { + size_t len_tmp = len; + __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; + __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; + __m512i z0, z1, z2, z3; + z_const __m512i zmm_fold4 = _mm512_set4_epi32( + 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); + z_const __m512i zmm_fold16 = _mm512_set4_epi32( + 0x00000001, 0x1542778a, 0x00000001, 0x322d1430); + + // zmm register init + zmm_crc0 = _mm512_setzero_si512(); + zmm_t0 = _mm512_loadu_si512((__m512i *)src); + zmm_crc1 = _mm512_loadu_si512((__m512i *)src + 1); + zmm_crc2 = _mm512_loadu_si512((__m512i *)src + 2); + zmm_crc3 = _mm512_loadu_si512((__m512i *)src + 3); + + /* already have intermediate CRC in xmm registers + * fold4 with 4 xmm_crc to get zmm_crc0 + */ + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc0, 0); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc1, 1); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc2, 2); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc3, 3); + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); + + _mm512_storeu_si512((__m512i *)dst, zmm_t0); + _mm512_storeu_si512((__m512i *)dst + 1, zmm_crc1); + _mm512_storeu_si512((__m512i *)dst + 2, zmm_crc2); + _mm512_storeu_si512((__m512i *)dst + 3, zmm_crc3); + len -= 256; + src += 256; + dst += 256; + + // fold-16 loops + while (len >= 256) { + zmm_t0 = _mm512_loadu_si512((__m512i *)src); + zmm_t1 = _mm512_loadu_si512((__m512i *)src + 1); + zmm_t2 = _mm512_loadu_si512((__m512i *)src + 2); + zmm_t3 = _mm512_loadu_si512((__m512i *)src + 3); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x01); + z1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x01); + z2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x01); + z3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x01); + + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x10); + zmm_crc1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x10); + zmm_crc2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x10); + zmm_crc3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x10); + + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc1 = _mm512_xor_si512(z1, zmm_crc1); + zmm_crc2 = _mm512_xor_si512(z2, zmm_crc2); + zmm_crc3 = _mm512_xor_si512(z3, zmm_crc3); + + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); + zmm_crc1 = _mm512_xor_si512(zmm_crc1, zmm_t1); + zmm_crc2 = _mm512_xor_si512(zmm_crc2, zmm_t2); + zmm_crc3 = _mm512_xor_si512(zmm_crc3, zmm_t3); + + _mm512_storeu_si512((__m512i *)dst, zmm_t0); + _mm512_storeu_si512((__m512i *)dst + 1, zmm_t1); + _mm512_storeu_si512((__m512i *)dst + 2, zmm_t2); + _mm512_storeu_si512((__m512i *)dst + 3, zmm_t3); + len -= 256; + src += 256; + dst += 256; + } + // zmm_crc[0,1,2,3] -> zmm_crc0 + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc1); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc2); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc3); + + // zmm_crc0 -> xmm_crc[0, 1, 2, 3] + *xmm_crc0 = _mm512_extracti32x4_epi32(zmm_crc0, 0); + *xmm_crc1 = _mm512_extracti32x4_epi32(zmm_crc0, 1); + *xmm_crc2 = _mm512_extracti32x4_epi32(zmm_crc0, 2); + *xmm_crc3 = _mm512_extracti32x4_epi32(zmm_crc0, 3); + + return (len_tmp - len); // return n bytes processed +} +#endif diff --git a/arch/x86/x86.c b/arch/x86/x86.c index 065a717032..32baf8a749 100644 --- a/arch/x86/x86.c +++ b/arch/x86/x86.c @@ -27,6 +27,7 @@ Z_INTERNAL int x86_cpu_has_ssse3; Z_INTERNAL int x86_cpu_has_sse41; Z_INTERNAL int x86_cpu_has_sse42; Z_INTERNAL int x86_cpu_has_pclmulqdq; +Z_INTERNAL int x86_cpu_has_vpclmulqdq; Z_INTERNAL int x86_cpu_has_tzcnt; Z_INTERNAL int x86_cpu_well_suited_avx512; @@ -98,9 +99,11 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_has_avx2 = ebx & 0x20; x86_cpu_has_avx512 = ebx & 0x00010000; x86_cpu_has_avx512vnni = ecx & 0x800; + x86_cpu_has_vpclmulqdq = ecx & 0x400; } else { x86_cpu_has_tzcnt = 0; x86_cpu_has_avx2 = 0; + x86_cpu_has_vpclmulqdq = 0; } diff --git a/arch/x86/x86.h b/arch/x86/x86.h index 80da6f32aa..00f8d9efc7 100644 --- a/arch/x86/x86.h +++ b/arch/x86/x86.h @@ -14,6 +14,7 @@ extern int x86_cpu_has_ssse3; extern int x86_cpu_has_sse41; extern int x86_cpu_has_sse42; extern int x86_cpu_has_pclmulqdq; +extern int x86_cpu_has_vpclmulqdq; extern int x86_cpu_has_tzcnt; extern int x86_cpu_well_suited_avx512; diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 2facf50513..47d93d0c15 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -168,6 +168,32 @@ macro(check_pclmulqdq_intrinsics) endif() endmacro() +macro(check_vpclmulqdq_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(VPCLMULFLAG "-mvpclmulqdq") + endif() + endif() + # Check whether compiler supports VPCLMULQDQ intrinsics + if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) + set(CMAKE_REQUIRED_FLAGS "${VPCLMULFLAG}") + check_c_source_compile_or_run( + "#include + int main(void) { + __m512i a = _mm512_setzero_si512(); + __m512i b = _mm512_setzero_si512(); + __m512i c = _mm512_clmulepi64_epi128(a, b, 0x10); + (void)c; + return 0; + }" + HAVE_VPCLMULQDQ_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) + else() + set(HAVE_VPCLMULQDQ_INTRIN OFF) + endif() +endmacro() + macro(check_ppc_intrinsics) # Check if compiler supports AltiVec set(CMAKE_REQUIRED_FLAGS "-maltivec") diff --git a/configure b/configure index 2c17507a86..143d6e4e67 100755 --- a/configure +++ b/configure @@ -90,6 +90,7 @@ compat=0 cover=0 build32=0 build64=0 +buildvpclmulqdq=1 buildacle=1 buildaltivec=1 buildpower8=1 @@ -112,6 +113,7 @@ ssse3flag="-mssse3" sse41flag="-msse4.1" sse42flag="-msse4.2" pclmulflag="-mpclmul" +vpclmulflag="-mvpclmulqdq" acleflag= neonflag= noltoflag="-fno-lto" @@ -194,6 +196,7 @@ case "$1" in --cover) cover=1; shift ;; -3* | --32) build32=1; shift ;; -6* | --64) build64=1; shift ;; + --without-vpclmulqdq) buildvpclmulqdq=0; shift ;; --without-acle) buildacle=0; shift ;; --without-neon) buildneon=0; shift ;; --without-altivec) buildaltivec=0 ; shift ;; @@ -262,6 +265,7 @@ if test $native -eq 1; then sse4flag="" sse42flag="" pclmulflag="" + vpclmulflag="" noltoflag="" fi @@ -1161,6 +1165,28 @@ EOF fi } +check_vpclmulqdq_intrinsics() { + # Check whether compiler supports VPCLMULQDQ intrinsics + cat > $test.c << EOF +#include +#include +int main(void) { + __m512i a = _mm512_setzero_si512(); + __m512i b = _mm512_setzero_si512(); + __m512i c = _mm512_clmulepi64_epi128(a, b, 0x10); + (void)c; + return 0; +} +EOF + if try ${CC} ${CFLAGS} ${vpclmulflag} $test.c; then + echo "Checking for VPCLMULQDQ intrinsics ... Yes." | tee -a configure.log + HAVE_VPCLMULQDQ_INTRIN=1 + else + echo "Checking for VPCLMULQDQ intrinsics ... No." | tee -a configure.log + HAVE_VPCLMULQDQ_INTRIN=0 + fi +} + check_ppc_intrinsics() { cat > $test.c << EOF #include @@ -1503,6 +1529,17 @@ case "${ARCH}" in SFLAGS="${SFLAGS} -DX86_PCLMULQDQ_CRC" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_fold_pclmulqdq.o" ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_fold_pclmulqdq.lo" + + if test $buildvpclmulqdq -eq 1; then + check_vpclmulqdq_intrinsics + + if test ${HAVE_VPCLMULQDQ_INTRIN} -eq 1 && test ${HAVE_AVX512_INTRIN} -eq 1; then + CFLAGS="${CFLAGS} -DX86_VPCLMULQDQ_CRC" + SFLAGS="${SFLAGS} -DX86_VPCLMULQDQ_CRC" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_fold_vpclmulqdq.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_fold_vpclmulqdq.lo" + fi + fi fi fi ;; @@ -1912,6 +1949,7 @@ echo ssse3flag = $ssse3flag >> configure.log echo sse41flag = $sse41flag >> configure.log echo sse42flag = $sse42flag >> configure.log echo pclmulflag = $pclmulflag >> configure.log +echo vpclmulflag = $vpclmulflag >> configure.log echo acleflag = $acleflag >> configure.log echo neonflag = $neonflag >> configure.log echo ARCHDIR = ${ARCHDIR} >> configure.log @@ -2049,6 +2087,7 @@ sed < $SRCDIR/$ARCHDIR/Makefile.in " /^SSE41FLAG *=/s#=.*#=$sse41flag# /^SSE42FLAG *=/s#=.*#=$sse42flag# /^PCLMULFLAG *=/s#=.*#=$pclmulflag# +/^VPCLMULFLAG *=/s#=.*#=$vpclmulflag# /^ACLEFLAG *=/s#=.*#=$acleflag# /^NEONFLAG *=/s#=.*#=$neonflag# /^NOLTOFLAG *=/s#=.*#=$noltoflag# From a7229aa6c0123068579cef013550d826ec55f228 Mon Sep 17 00:00:00 2001 From: merceyz Date: Sat, 1 Jan 2022 15:57:31 +0100 Subject: [PATCH 197/798] build: fix check for SSSE3 when using Emscripten --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 143d6e4e67..143bc6bf3f 100755 --- a/configure +++ b/configure @@ -1341,7 +1341,7 @@ EOF check_ssse3_intrinsics() { # Check whether compiler supports SSSE3 intrinsics cat > $test.c << EOF -#include +#include int main(void) { __m128i u, v, w; From b2ef108051610dc435939ebabaedf36ffd053984 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 8 Jan 2022 13:28:41 -0800 Subject: [PATCH 198/798] Remove unused COMPARE258 macro since longest_match only uses COMPARE256. --- arch/x86/compare258_avx.c | 2 -- arch/x86/compare258_sse.c | 2 -- compare258.c | 8 -------- match_tpl.h | 1 - 4 files changed, 13 deletions(-) diff --git a/arch/x86/compare258_avx.c b/arch/x86/compare258_avx.c index 3452127f5a..4fafc4c6d6 100644 --- a/arch/x86/compare258_avx.c +++ b/arch/x86/compare258_avx.c @@ -60,14 +60,12 @@ Z_INTERNAL uint32_t compare258_unaligned_avx2(const unsigned char *src0, const u #define LONGEST_MATCH longest_match_unaligned_avx2 #define COMPARE256 compare256_unaligned_avx2_static -#define COMPARE258 compare258_unaligned_avx2_static #include "match_tpl.h" #define LONGEST_MATCH_SLOW #define LONGEST_MATCH longest_match_slow_unaligned_avx2 #define COMPARE256 compare256_unaligned_avx2_static -#define COMPARE258 compare258_unaligned_avx2_static #include "match_tpl.h" diff --git a/arch/x86/compare258_sse.c b/arch/x86/compare258_sse.c index 1bea2e95bd..f0accfd831 100644 --- a/arch/x86/compare258_sse.c +++ b/arch/x86/compare258_sse.c @@ -67,14 +67,12 @@ Z_INTERNAL uint32_t compare258_unaligned_sse4(const unsigned char *src0, const u #define LONGEST_MATCH longest_match_unaligned_sse4 #define COMPARE256 compare256_unaligned_sse4_static -#define COMPARE258 compare258_unaligned_sse4_static #include "match_tpl.h" #define LONGEST_MATCH_SLOW #define LONGEST_MATCH longest_match_slow_unaligned_sse4 #define COMPARE256 compare256_unaligned_sse4_static -#define COMPARE258 compare258_unaligned_sse4_static #include "match_tpl.h" diff --git a/compare258.c b/compare258.c index e6e63f249e..8260f332b1 100644 --- a/compare258.c +++ b/compare258.c @@ -59,14 +59,12 @@ Z_INTERNAL uint32_t compare258_c(const unsigned char *src0, const unsigned char #define LONGEST_MATCH longest_match_c #define COMPARE256 compare256_c_static -#define COMPARE258 compare258_c_static #include "match_tpl.h" #define LONGEST_MATCH_SLOW #define LONGEST_MATCH longest_match_slow_c #define COMPARE256 compare256_c_static -#define COMPARE258 compare258_c_staticc #include "match_tpl.h" @@ -106,14 +104,12 @@ Z_INTERNAL uint32_t compare258_unaligned_16(const unsigned char *src0, const uns #define LONGEST_MATCH longest_match_unaligned_16 #define COMPARE256 compare256_unaligned_16_static -#define COMPARE258 compare258_unaligned_16_static #include "match_tpl.h" #define LONGEST_MATCH_SLOW #define LONGEST_MATCH longest_match_slow_unaligned_16 #define COMPARE256 compare256_unaligned_16_static -#define COMPARE258 compare258_unaligned_16_static #include "match_tpl.h" @@ -153,14 +149,12 @@ Z_INTERNAL uint32_t compare258_unaligned_32(const unsigned char *src0, const uns #define LONGEST_MATCH longest_match_unaligned_32 #define COMPARE256 compare256_unaligned_32_static -#define COMPARE258 compare258_unaligned_32_static #include "match_tpl.h" #define LONGEST_MATCH_SLOW #define LONGEST_MATCH longest_match_slow_unaligned_32 #define COMPARE256 compare256_unaligned_32_static -#define COMPARE258 compare258_unaligned_32_static #include "match_tpl.h" @@ -202,14 +196,12 @@ Z_INTERNAL uint32_t compare258_unaligned_64(const unsigned char *src0, const uns #define LONGEST_MATCH longest_match_unaligned_64 #define COMPARE256 compare256_unaligned_64_static -#define COMPARE258 compare258_unaligned_64_static #include "match_tpl.h" #define LONGEST_MATCH_SLOW #define LONGEST_MATCH longest_match_slow_unaligned_64 #define COMPARE256 compare256_unaligned_64_static -#define COMPARE258 compare258_unaligned_64_static #include "match_tpl.h" diff --git a/match_tpl.h b/match_tpl.h index e11abfbb72..75181bf851 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -288,4 +288,3 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #undef LONGEST_MATCH_SLOW #undef LONGEST_MATCH #undef COMPARE256 -#undef COMPARE258 From 2af7ead293969b2a4c409e10b7f4e1a59de43ca4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 2 Jan 2022 13:19:47 -0800 Subject: [PATCH 199/798] Rename x86 source files with instruction set version. --- CMakeLists.txt | 12 ++-- arch/x86/Makefile.in | 70 +++++++++---------- arch/x86/{adler32_avx.c => adler32_avx2.c} | 2 +- arch/x86/{chunkset_sse.c => chunkset_sse2.c} | 2 +- .../{compare258_avx.c => compare258_avx2.c} | 2 +- .../{compare258_sse.c => compare258_sse42.c} | 2 +- ...ert_string_sse.c => insert_string_sse42.c} | 2 +- .../{slide_hash_avx.c => slide_hash_avx2.c} | 0 .../{slide_hash_sse.c => slide_hash_sse2.c} | 0 configure | 16 ++--- win32/Makefile.msc | 18 ++--- 11 files changed, 63 insertions(+), 63 deletions(-) rename arch/x86/{adler32_avx.c => adler32_avx2.c} (98%) rename arch/x86/{chunkset_sse.c => chunkset_sse2.c} (94%) rename arch/x86/{compare258_avx.c => compare258_avx2.c} (97%) rename arch/x86/{compare258_sse.c => compare258_sse42.c} (97%) rename arch/x86/{insert_string_sse.c => insert_string_sse42.c} (92%) rename arch/x86/{slide_hash_avx.c => slide_hash_avx2.c} (100%) rename arch/x86/{slide_hash_sse.c => slide_hash_sse2.c} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ecb9ac6b27..911bcb3fe2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -715,13 +715,13 @@ if(WITH_OPTIM) check_avx2_intrinsics() if(HAVE_AVX2_INTRIN) add_definitions(-DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET) - set(AVX2_SRCS ${ARCHDIR}/slide_hash_avx.c) + set(AVX2_SRCS ${ARCHDIR}/slide_hash_avx2.c) add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx.c) add_feature_info(AVX_CHUNKSET 1 "Support AVX optimized chunkset, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/compare258_avx.c) + list(APPEND AVX2_SRCS ${ARCHDIR}/compare258_avx2.c) add_feature_info(AVX2_COMPARE258 1 "Support AVX2 optimized compare258, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx.c) + list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx2.c) add_feature_info(AVX2_ADLER32 1 "Support AVX2-accelerated adler32, using \"${AVX2FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) set_property(SOURCE ${AVX2_SRCS} PROPERTY COMPILE_FLAGS "${AVX2FLAG} ${NOLTOFLAG}") @@ -772,7 +772,7 @@ if(WITH_OPTIM) check_sse42_intrinsics() if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) add_definitions(-DX86_SSE42_CRC_HASH) - set(SSE42_SRCS ${ARCHDIR}/insert_string_sse.c) + set(SSE42_SRCS ${ARCHDIR}/insert_string_sse42.c) add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE42FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") @@ -782,7 +782,7 @@ if(WITH_OPTIM) endif() if(HAVE_SSE42CMPSTR_INTRIN) add_definitions(-DX86_SSE42_CMP_STR) - set(SSE42_SRCS ${ARCHDIR}/compare258_sse.c) + set(SSE42_SRCS ${ARCHDIR}/compare258_sse42.c) add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE42FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") @@ -795,7 +795,7 @@ if(WITH_OPTIM) check_sse2_intrinsics() if(HAVE_SSE2_INTRIN) add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) - set(SSE2_SRCS ${ARCHDIR}/chunkset_sse.c ${ARCHDIR}/slide_hash_sse.c) + set(SSE2_SRCS ${ARCHDIR}/chunkset_sse2.c ${ARCHDIR}/slide_hash_sse2.c) list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) if(NOT ${ARCH} MATCHES "x86_64") set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG} ${NOLTOFLAG}") diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 0a1dc07662..d481c0ee7d 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -25,20 +25,20 @@ TOPDIR=$(SRCTOP) all: \ x86.o x86.lo \ - adler32_avx.o adler32_avx.lo \ + adler32_avx2.o adler32_avx2.lo \ adler32_avx512.o adler32_avx512.lo \ adler32_avx512_vnni.o adler32_avx512_vnni.lo \ adler32_sse41.o adler32_sse41.lo \ adler32_ssse3.o adler32_ssse3.lo \ chunkset_avx.o chunkset_avx.lo \ - chunkset_sse.o chunkset_sse.lo \ - compare258_avx.o compare258_avx.lo \ - compare258_sse.o compare258_sse.lo \ - insert_string_sse.o insert_string_sse.lo \ + chunkset_sse2.o chunkset_sse2.lo \ + compare258_avx2.o compare258_avx2.lo \ + compare258_sse42.o compare258_sse42.lo \ + insert_string_sse42.o insert_string_sse42.lo \ crc32_fold_pclmulqdq.o crc32_fold_pclmulqdq.lo \ crc32_fold_vpclmulqdq.o crc32_fold_vpclmulqdq.lo \ - slide_hash_avx.o slide_hash_avx.lo \ - slide_hash_sse.o slide_hash_sse.lo + slide_hash_avx2.o slide_hash_avx2.lo \ + slide_hash_sse2.o slide_hash_sse2.lo x86.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c @@ -52,29 +52,29 @@ chunkset_avx.o: chunkset_avx.lo: $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c -chunkset_sse.o: - $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse.c +chunkset_sse2.o: + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse2.c -chunkset_sse.lo: - $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse.c +chunkset_sse2.lo: + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse2.c -compare258_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c +compare258_avx2.o: + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx2.c -compare258_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx.c +compare258_avx2.lo: + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx2.c -compare258_sse.o: - $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c +compare258_sse42.o: + $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse42.c -compare258_sse.lo: - $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse.c +compare258_sse42.lo: + $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse42.c -insert_string_sse.o: - $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c +insert_string_sse42.o: + $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse42.c -insert_string_sse.lo: - $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse.c +insert_string_sse42.lo: + $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse42.c crc32_fold_pclmulqdq.o: $(CC) $(CFLAGS) $(PCLMULFLAG) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_pclmulqdq.c @@ -88,23 +88,23 @@ crc32_fold_vpclmulqdq.o: crc32_fold_vpclmulqdq.lo: $(CC) $(SFLAGS) $(VPCLMULFLAG) $(AVX512FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_fold_vpclmulqdq.c -slide_hash_avx.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx.c +slide_hash_avx2.o: + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx2.c -slide_hash_avx.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx.c +slide_hash_avx2.lo: + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_avx2.c -slide_hash_sse.o: - $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_sse.c +slide_hash_sse2.o: + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_sse2.c -slide_hash_sse.lo: - $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_sse.c +slide_hash_sse2.lo: + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/slide_hash_sse2.c -adler32_avx.o: $(SRCDIR)/adler32_avx.c - $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c +adler32_avx2.o: $(SRCDIR)/adler32_avx2.c + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx2.c -adler32_avx.lo: $(SRCDIR)/adler32_avx.c - $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx.c +adler32_avx2.lo: $(SRCDIR)/adler32_avx2.c + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx2.c adler32_avx512.o: $(SRCDIR)/adler32_avx512.c $(CC) $(CFLAGS) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512.c diff --git a/arch/x86/adler32_avx.c b/arch/x86/adler32_avx2.c similarity index 98% rename from arch/x86/adler32_avx.c rename to arch/x86/adler32_avx2.c index f22730bb1b..4068523470 100644 --- a/arch/x86/adler32_avx.c +++ b/arch/x86/adler32_avx2.c @@ -1,4 +1,4 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream +/* adler32_avx2.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011 Mark Adler * Authors: * Brian Bockelman diff --git a/arch/x86/chunkset_sse.c b/arch/x86/chunkset_sse2.c similarity index 94% rename from arch/x86/chunkset_sse.c rename to arch/x86/chunkset_sse2.c index d38e99dad6..577b0e2ef4 100644 --- a/arch/x86/chunkset_sse.c +++ b/arch/x86/chunkset_sse2.c @@ -1,4 +1,4 @@ -/* chunkset_sse.c -- SSE inline functions to copy small data chunks. +/* chunkset_sse2.c -- SSE2 inline functions to copy small data chunks. * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/arch/x86/compare258_avx.c b/arch/x86/compare258_avx2.c similarity index 97% rename from arch/x86/compare258_avx.c rename to arch/x86/compare258_avx2.c index 4fafc4c6d6..9aefde16a3 100644 --- a/arch/x86/compare258_avx.c +++ b/arch/x86/compare258_avx2.c @@ -1,4 +1,4 @@ -/* compare258_avx.c -- AVX2 version of compare258 +/* compare258_avx2.c -- AVX2 version of compare258 * Copyright Mika T. Lindqvist * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/arch/x86/compare258_sse.c b/arch/x86/compare258_sse42.c similarity index 97% rename from arch/x86/compare258_sse.c rename to arch/x86/compare258_sse42.c index f0accfd831..a5d568ff4f 100644 --- a/arch/x86/compare258_sse.c +++ b/arch/x86/compare258_sse42.c @@ -1,4 +1,4 @@ -/* compare258_sse.c -- SSE4.2 version of compare258 +/* compare258_sse42.c -- SSE4.2 version of compare258 * * Copyright (C) 2013 Intel Corporation. All rights reserved. * Authors: diff --git a/arch/x86/insert_string_sse.c b/arch/x86/insert_string_sse42.c similarity index 92% rename from arch/x86/insert_string_sse.c rename to arch/x86/insert_string_sse42.c index b33a2c7ccb..6fe4c81e08 100644 --- a/arch/x86/insert_string_sse.c +++ b/arch/x86/insert_string_sse42.c @@ -1,4 +1,4 @@ -/* insert_string_sse.c -- insert_string integer hash variant using SSE4.2's CRC instructions +/* insert_string_sse42.c -- insert_string integer hash variant using SSE4.2's CRC instructions * * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h diff --git a/arch/x86/slide_hash_avx.c b/arch/x86/slide_hash_avx2.c similarity index 100% rename from arch/x86/slide_hash_avx.c rename to arch/x86/slide_hash_avx2.c diff --git a/arch/x86/slide_hash_sse.c b/arch/x86/slide_hash_sse2.c similarity index 100% rename from arch/x86/slide_hash_sse.c rename to arch/x86/slide_hash_sse2.c diff --git a/configure b/configure index 143bc6bf3f..f5fe81cbc7 100755 --- a/configure +++ b/configure @@ -1438,8 +1438,8 @@ case "${ARCH}" in if test ${HAVE_AVX2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" SFLAGS="${SFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_hash_avx.o chunkset_avx.o compare258_avx.o adler32_avx.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx.lo chunkset_avx.lo compare258_avx.lo adler32_avx.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_hash_avx2.o chunkset_avx.o compare258_avx2.o adler32_avx2.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx2.lo chunkset_avx.lo compare258_avx2.lo adler32_avx2.lo" fi check_avx512_intrinsics @@ -1487,16 +1487,16 @@ case "${ARCH}" in SFLAGS="${SFLAGS} -DX86_SSE42_CRC_INTRIN" fi - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} insert_string_sse.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} insert_string_sse42.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse42.lo" fi if test ${HAVE_SSE42CMPSTR_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42_CMP_STR" SFLAGS="${SFLAGS} -DX86_SSE42_CMP_STR" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} compare258_sse.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} compare258_sse.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} compare258_sse42.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} compare258_sse42.lo" fi check_sse2_intrinsics @@ -1504,8 +1504,8 @@ case "${ARCH}" in if test ${HAVE_SSE2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" SFLAGS="${SFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse.o slide_hash_sse.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse.lo slide_hash_sse.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse2.o slide_hash_sse2.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse2.lo slide_hash_sse2.lo" if test $forcesse2 -eq 1; then CFLAGS="${CFLAGS} -DX86_NOCHECK_SSE2" diff --git a/win32/Makefile.msc b/win32/Makefile.msc index ef3f237ffc..ff6c6963c9 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -52,10 +52,10 @@ OBJS = \ adler32.obj \ chunkset.obj \ chunkset_avx.obj \ - chunkset_sse.obj \ + chunkset_sse2.obj \ compare258.obj \ - compare258_avx.obj \ - compare258_sse.obj \ + compare258_avx2.obj \ + compare258_sse42.obj \ compress.obj \ crc32.obj \ crc32_comb.obj \ @@ -76,10 +76,10 @@ OBJS = \ inffast.obj \ insert_string.obj \ insert_string_roll.obj \ - insert_string_sse.obj \ + insert_string_sse42.obj \ slide_hash.obj \ - slide_hash_avx.obj \ - slide_hash_sse.obj \ + slide_hash_avx2.obj \ + slide_hash_sse2.obj \ trees.obj \ uncompr.obj \ zutil.obj \ @@ -190,7 +190,7 @@ compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_avx.obj: $(SRCDIR)/arch/x86/chunkset_avx.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -chunkset_sse.obj: $(SRCDIR)/arch/x86/chunkset_sse.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h +chunkset_sse2.obj: $(SRCDIR)/arch/x86/chunkset_sse2.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h @@ -208,8 +208,8 @@ inffast.obj: $(SRCDIR)/inffast.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/ inflate.obj: $(SRCDIR)/inflate.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h $(SRCDIR)/inflate.h $(SRCDIR)/inffast.h $(SRCDIR)/functable.h $(SRCDIR)/functable.h inftrees.obj: $(SRCDIR)/inftrees.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/inftrees.h slide_hash.obj: $(SRCDIR)/slide_hash.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h -slide_hash_avx.obj: $(SRCDIR)/arch/x86/slide_hash_avx.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h -slide_hash_sse.obj: $(SRCDIR)/arch/x86/slide_hash_sse.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h +slide_hash_avx2.obj: $(SRCDIR)/arch/x86/slide_hash_avx2.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h +slide_hash_sse2.obj: $(SRCDIR)/arch/x86/slide_hash_sse2.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h trees.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/trees_tbl.h zutil.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/zutil_p.h From 76c2ddf201d520dc3d41e5e4dafb0b344708148a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 13 Jan 2022 17:02:49 -0800 Subject: [PATCH 200/798] Remove unmaintained and out-dated DLL FAQ. --- win32/DLL_FAQ.txt | 397 ---------------------------------------------- 1 file changed, 397 deletions(-) delete mode 100644 win32/DLL_FAQ.txt diff --git a/win32/DLL_FAQ.txt b/win32/DLL_FAQ.txt deleted file mode 100644 index 7a57079673..0000000000 --- a/win32/DLL_FAQ.txt +++ /dev/null @@ -1,397 +0,0 @@ - - Frequently Asked Questions about ZLIB1.DLL - - -This document describes the design, the rationale, and the usage -of the official DLL build of zlib, named ZLIB1.DLL. If you have -general questions about zlib, you should see the file "FAQ" found -in the zlib distribution, or at the following location: - https://www.zlib.net/zlib_faq.html - - - 1. What is ZLIB1.DLL, and how can I get it? - - - ZLIB1.DLL is the official build of zlib as a DLL. - (Please remark the character '1' in the name.) - - Pointers to a precompiled ZLIB1.DLL can be found in the zlib - web site at: - https://www.zlib.net/ - - Applications that link to ZLIB1.DLL can rely on the following - specification: - - * The exported symbols are exclusively defined in the source - files "zlib.h" and "zlib.def", found in an official zlib - source distribution. - * The symbols are exported by name, not by ordinal. - * The exported names are undecorated. - * The calling convention of functions is "C" (CDECL). - * The ZLIB1.DLL binary is linked to MSVCRT.DLL. - - The archive in which ZLIB1.DLL is bundled contains compiled - test programs that must run with a valid build of ZLIB1.DLL. - It is recommended to download the prebuilt DLL from the zlib - web site, instead of building it yourself, to avoid potential - incompatibilities that could be introduced by your compiler - and build settings. If you do build the DLL yourself, please - make sure that it complies with all the above requirements, - and it runs with the precompiled test programs, bundled with - the original ZLIB1.DLL distribution. - - If, for any reason, you need to build an incompatible DLL, - please use a different file name. - - - 2. Why did you change the name of the DLL to ZLIB1.DLL? - What happened to the old ZLIB.DLL? - - - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required - compilation settings that were incompatible to those used by - a static build. The DLL settings were supposed to be enabled - by defining the macro ZLIB_DLL, before including "zlib.h". - Incorrect handling of this macro was silently accepted at - build time, resulting in two major problems: - - * ZLIB_DLL was missing from the old makefile. When building - the DLL, not all people added it to the build options. In - consequence, incompatible incarnations of ZLIB.DLL started - to circulate around the net. - - * When switching from using the static library to using the - DLL, applications had to define the ZLIB_DLL macro and - to recompile all the sources that contained calls to zlib - functions. Failure to do so resulted in creating binaries - that were unable to run with the official ZLIB.DLL build. - - The only possible solution that we could foresee was to make - a binary-incompatible change in the DLL interface, in order to - remove the dependency on the ZLIB_DLL macro, and to release - the new DLL under a different name. - - We chose the name ZLIB1.DLL, where '1' indicates the major - zlib version number. We hope that we will not have to break - the binary compatibility again, at least not as long as the - zlib-1.x series will last. - - There is still a ZLIB_DLL macro, that can trigger a more - efficient build and use of the DLL, but compatibility no - longer dependents on it. - - - 3. Can I build ZLIB.DLL from the new zlib sources, and replace - an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? - - - In principle, you can do it by assigning calling convention - keywords to the macros Z_EXPORT and Z_EXPORTVA. In practice, - it depends on what you mean by "an old ZLIB.DLL", because the - old DLL exists in several mutually-incompatible versions. - You have to find out first what kind of calling convention is - being used in your particular ZLIB.DLL build, and to use the - same one in the new build. If you don't know what this is all - about, you might be better off if you would just leave the old - DLL intact. - - - 4. Can I compile my application using the new zlib interface, and - link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or - earlier? - - - The official answer is "no"; the real answer depends again on - what kind of ZLIB.DLL you have. Even if you are lucky, this - course of action is unreliable. - - If you rebuild your application and you intend to use a newer - version of zlib (post- 1.1.4), it is strongly recommended to - link it to the new ZLIB1.DLL. - - - 5. Why are the zlib symbols exported by name, and not by ordinal? - - - Although exporting symbols by ordinal is a little faster, it - is risky. Any single glitch in the maintenance or use of the - DEF file that contains the ordinals can result in incompatible - builds and frustrating crashes. Simply put, the benefits of - exporting symbols by ordinal do not justify the risks. - - Technically, it should be possible to maintain ordinals in - the DEF file, and still export the symbols by name. Ordinals - exist in every DLL, and even if the dynamic linking performed - at the DLL startup is searching for names, ordinals serve as - hints, for a faster name lookup. However, if the DEF file - contains ordinals, the Microsoft linker automatically builds - an implib that will cause the executables linked to it to use - those ordinals, and not the names. It is interesting to - notice that the GNU linker for Win32 does not suffer from this - problem. - - It is possible to avoid the DEF file if the exported symbols - are accompanied by a "__declspec(dllexport)" attribute in the - source files. You can do this in zlib by predefining the - ZLIB_DLL macro. - - - 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling - convention. Why not use the STDCALL convention? - STDCALL is the standard convention in Win32, and I need it in - my Visual Basic project! - - (For readability, we use CDECL to refer to the convention - triggered by the "__cdecl" keyword, STDCALL to refer to - the convention triggered by "__stdcall", and FASTCALL to - refer to the convention triggered by "__fastcall".) - - - Most of the native Windows API functions (without varargs) use - indeed the WINAPI convention (which translates to STDCALL in - Win32), but the standard C functions use CDECL. If a user - application is intrinsically tied to the Windows API (e.g. - it calls native Windows API functions such as CreateFile()), - sometimes it makes sense to decorate its own functions with - WINAPI. But if ANSI C or POSIX portability is a goal (e.g. - it calls standard C functions such as fopen()), it is not a - sound decision to request the inclusion of , or to - use non-ANSI constructs, for the sole purpose to make the user - functions STDCALL-able. - - The functionality offered by zlib is not in the category of - "Windows functionality", but is more like "C functionality". - - Technically, STDCALL is not bad; in fact, it is slightly - faster than CDECL, and it works with variable-argument - functions, just like CDECL. It is unfortunate that, in spite - of using STDCALL in the Windows API, it is not the default - convention used by the C compilers that run under Windows. - The roots of the problem reside deep inside the unsafety of - the K&R-style function prototypes, where the argument types - are not specified; but that is another story for another day. - - The remaining fact is that CDECL is the default convention. - Even if an explicit convention is hard-coded into the function - prototypes inside C headers, problems may appear. The - necessity to expose the convention in users' callbacks is one - of these problems. - - The calling convention issues are also important when using - zlib in other programming languages. Some of them, like Ada - (GNAT) and Fortran (GNU G77), have C bindings implemented - initially on Unix, and relying on the C calling convention. - On the other hand, the pre- .NET versions of Microsoft Visual - Basic require STDCALL, while Borland Delphi prefers, although - it does not require, FASTCALL. - - In fairness to all possible uses of zlib outside the C - programming language, we choose the default "C" convention. - Anyone interested in different bindings or conventions is - encouraged to maintain specialized projects. The "contrib/" - directory from the zlib distribution already holds a couple - of foreign bindings, such as Ada, C++, and Delphi. - - - 7. I need a DLL for my Visual Basic project. What can I do? - - - Define the ZLIB_WINAPI macro before including "zlib.h", when - building both the DLL and the user application (except that - you don't need to define anything when using the DLL in Visual - Basic). The ZLIB_WINAPI macro will switch on the WINAPI - (STDCALL) convention. The name of this DLL must be different - than the official ZLIB1.DLL. - - Gilles Vollant has contributed a build named ZLIBWAPI.DLL, - with the ZLIB_WINAPI macro turned on, and with the minizip - functionality built in. For more information, please read - the notes inside "contrib/vstudio/readme.txt", found in the - zlib distribution. - - - 8. I need to use zlib in my Microsoft .NET project. What can I - do? - - - Henrik Ravn has contributed a .NET wrapper around zlib. Look - into contrib/dotzlib/, inside the zlib distribution. - - - 9. If my application uses ZLIB1.DLL, should I link it to - MSVCRT.DLL? Why? - - - It is not required, but it is recommended to link your - application to MSVCRT.DLL, if it uses ZLIB1.DLL. - - The executables (.EXE, .DLL, etc.) that are involved in the - same process and are using the C run-time library (i.e. they - are calling standard C functions), must link to the same - library. There are several libraries in the Win32 system: - CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc. - Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that - depend on it should also be linked to MSVCRT.DLL. - - -10. Why are you saying that ZLIB1.DLL and my application should - be linked to the same C run-time (CRT) library? I linked my - application and my DLLs to different C libraries (e.g. my - application to a static library, and my DLLs to MSVCRT.DLL), - and everything works fine. - - - If a user library invokes only pure Win32 API (accessible via - and the related headers), its DLL build will work - in any context. But if this library invokes standard C API, - things get more complicated. - - There is a single Win32 library in a Win32 system. Every - function in this library resides in a single DLL module, that - is safe to call from anywhere. On the other hand, there are - multiple versions of the C library, and each of them has its - own separate internal state. Standalone executables and user - DLLs that call standard C functions must link to a C run-time - (CRT) library, be it static or shared (DLL). Intermixing - occurs when an executable (not necessarily standalone) and a - DLL are linked to different CRTs, and both are running in the - same process. - - Intermixing multiple CRTs is possible, as long as their - internal states are kept intact. The Microsoft Knowledge Base - articles KB94248 "HOWTO: Use the C Run-Time" and KB140584 - "HOWTO: Link with the Correct C Run-Time (CRT) Library" - mention the potential problems raised by intermixing. - - If intermixing works for you, it's because your application - and DLLs are avoiding the corruption of each of the CRTs' - internal states, maybe by careful design, or maybe by fortune. - - Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such - as those provided by Borland, raises similar problems. - - -11. Why are you linking ZLIB1.DLL to MSVCRT.DLL? - - - MSVCRT.DLL exists on every Windows 95 with a new service pack - installed, or with Microsoft Internet Explorer 4 or later, and - on all other Windows 4.x or later (Windows 98, Windows NT 4, - or later). It is freely distributable; if not present in the - system, it can be downloaded from Microsoft or from other - software provider for free. - - The fact that MSVCRT.DLL does not exist on a virgin Windows 95 - is not so problematic. Windows 95 is scarcely found nowadays, - Microsoft ended its support a long time ago, and many recent - applications from various vendors, including Microsoft, do not - even run on it. Furthermore, no serious user should run - Windows 95 without a proper update installed. - - -12. Why are you not linking ZLIB1.DLL to - <> ? - - - We considered and abandoned the following alternatives: - - * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or - LIBCMT.LIB) is not a good option. People are using the DLL - mainly to save disk space. If you are linking your program - to a static C library, you may as well consider linking zlib - in statically, too. - - * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because - CRTDLL.DLL is present on every Win32 installation. - Unfortunately, it has a series of problems: it does not - work properly with Microsoft's C++ libraries, it does not - provide support for 64-bit file offsets, (and so on...), - and Microsoft discontinued its support a long time ago. - - * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied - with the Microsoft .NET platform, and Visual C++ 7.0/7.1, - raises problems related to the status of ZLIB1.DLL as a - system component. According to the Microsoft Knowledge Base - article KB326922 "INFO: Redistribution of the Shared C - Runtime Component in Visual C++ .NET", MSVCR70.DLL and - MSVCR71.DLL are not supposed to function as system DLLs, - because they may clash with MSVCRT.DLL. Instead, the - application's installer is supposed to put these DLLs - (if needed) in the application's private directory. - If ZLIB1.DLL depends on a non-system runtime, it cannot - function as a redistributable system component. - - * Linking ZLIB1.DLL to non-Microsoft runtimes, such as - Borland's, or Cygwin's, raises problems related to the - reliable presence of these runtimes on Win32 systems. - It's easier to let the DLL build of zlib up to the people - who distribute these runtimes, and who may proceed as - explained in the answer to Question 14. - - -13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL, - how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0 - (Visual Studio .NET) or newer? - - - Due to the problems explained in the Microsoft Knowledge Base - article KB326922 (see the previous answer), the C runtime that - comes with the VC7 environment is no longer considered a - system component. That is, it should not be assumed that this - runtime exists, or may be installed in a system directory. - Since ZLIB1.DLL is supposed to be a system component, it may - not depend on a non-system component. - - In order to link ZLIB1.DLL and your application to MSVCRT.DLL - in VC7, you need the library of Visual C++ 6.0 or older. If - you don't have this library at hand, it's probably best not to - use ZLIB1.DLL. - - We are hoping that, in the future, Microsoft will provide a - way to build applications linked to a proper system runtime, - from the Visual C++ environment. Until then, you have a - couple of alternatives, such as linking zlib in statically. - If your application requires dynamic linking, you may proceed - as explained in the answer to Question 14. - - -14. I need to link my own DLL build to a CRT different than - MSVCRT.DLL. What can I do? - - - Feel free to rebuild the DLL from the zlib sources, and link - it the way you want. You should, however, clearly state that - your build is unofficial. You should give it a different file - name, and/or install it in a private directory that can be - accessed by your application only, and is not visible to the - others (i.e. it's neither in the PATH, nor in the SYSTEM or - SYSTEM32 directories). Otherwise, your build may clash with - applications that link to the official build. - - For example, in Cygwin, zlib is linked to the Cygwin runtime - CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. - - -15. May I include additional pieces of code that I find useful, - link them in ZLIB1.DLL, and export them? - - - No. A legitimate build of ZLIB1.DLL must not include code - that does not originate from the official zlib source code. - But you can make your own private DLL build, under a different - file name, as suggested in the previous answer. - - For example, zlib is a part of the VCL library, distributed - with Borland Delphi and C++ Builder. The DLL build of VCL - is a redistributable file, named VCLxx.DLL. - - -16. May I remove some functionality out of ZLIB1.DLL, by enabling - macros like NO_GZCOMPRESS or NO_GZIP at compile time? - - - No. A legitimate build of ZLIB1.DLL must provide the complete - zlib functionality, as implemented in the official zlib source - code. But you can make your own private DLL build, under a - different file name, as suggested in the previous answer. - - -17. I made my own ZLIB1.DLL build. Can I test it for compliance? - - - We prefer that you download the official DLL from the zlib - web site. If you need something peculiar from this DLL, you - can send your suggestion to the zlib mailing list. - - However, in case you do rebuild the DLL yourself, you can run - it with the test programs found in the DLL distribution. - Running these test programs is not a guarantee of compliance, - but a failure can imply a detected problem. - -** - -This document is written and maintained by -Cosmin Truta From 42eefd44edb038b8674e7697b1adbb176ecd879b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 13 Jan 2022 17:05:16 -0800 Subject: [PATCH 201/798] Remove unmaintained index markdown in arch/x86. --- arch/x86/INDEX.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 arch/x86/INDEX.md diff --git a/arch/x86/INDEX.md b/arch/x86/INDEX.md deleted file mode 100644 index af987a25c4..0000000000 --- a/arch/x86/INDEX.md +++ /dev/null @@ -1,9 +0,0 @@ -Contents --------- - -|Name|Description| -|:-|:-| -|deflate_quick.c|SSE4 optimized deflate strategy for use as level 1| -|crc32_fold_pclmulqdq.c|SSE4 + PCLMULQDQ optimized CRC folding implementation| -|crc32_fold_vpclmulqdq.c|VPCLMULQDQ optimized CRC folding implementation| -|slide_hash_sse2.c|SSE2 optimized slide_hash| From 346ec9c42cdd2a4b369e1fc068038c66b5c6dc7f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 9 Jan 2022 07:35:10 -0800 Subject: [PATCH 202/798] Merge crc32_little and crc32_big with preprocessor macros for each endian. Removed crc32_generic since it is not being used. --- arch/s390/crc32-vx.c | 6 +-- crc32.c | 108 +++++++++++-------------------------------- crc32_p.h | 6 +-- functable.c | 8 +--- 4 files changed, 31 insertions(+), 97 deletions(-) diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index 18b8bb2235..3465a57323 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -202,12 +202,12 @@ uint32_t Z_INTERNAL s390_crc32_vx(uint32_t crc, const unsigned char *buf, uint64 uint64_t prealign, aligned, remaining; if (len < VX_MIN_LEN + VX_ALIGN_MASK) - return crc32_big(crc, buf, len); + return crc32_byfour(crc, buf, len); if ((uintptr_t)buf & VX_ALIGN_MASK) { prealign = VX_ALIGNMENT - ((uintptr_t)buf & VX_ALIGN_MASK); len -= prealign; - crc = crc32_big(crc, buf, prealign); + crc = crc32_byfour(crc, buf, prealign); buf += prealign; } aligned = len & ~VX_ALIGN_MASK; @@ -216,7 +216,7 @@ uint32_t Z_INTERNAL s390_crc32_vx(uint32_t crc, const unsigned char *buf, uint64 crc = crc32_le_vgfm_16(crc ^ 0xffffffff, buf, (size_t)aligned) ^ 0xffffffff; if (remaining) - crc = crc32_big(crc, buf + aligned, remaining); + crc = crc32_byfour(crc, buf + aligned, remaining); return crc; } diff --git a/crc32.c b/crc32.c index c9a81d37b0..b962fb6b50 100644 --- a/crc32.c +++ b/crc32.c @@ -16,9 +16,7 @@ #include "functable.h" #include "crc32_tbl.h" -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ +/* ========================================================================= */ const uint32_t * Z_EXPORT PREFIX(get_crc_table)(void) { return (const uint32_t *)crc_table; } @@ -35,34 +33,8 @@ uint32_t Z_EXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t return functable.crc32(crc, buf, len); } -#endif -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 -#define DO4 DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_generic(uint32_t crc, const unsigned char *buf, uint64_t len) { - crc = crc ^ 0xffffffff; - -#ifdef UNROLL_MORE - while (len >= 8) { - DO8; - len -= 8; - } -#else - while (len >= 4) { - DO4; - len -= 4; - } #endif - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffff; -} - #ifdef ZLIB_COMPAT unsigned long Z_EXPORT PREFIX(crc32)(unsigned long crc, const unsigned char *buf, unsigned int len) { return (unsigned long)PREFIX(crc32_z)((uint32_t)crc, buf, len); @@ -73,6 +45,8 @@ uint32_t Z_EXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t } #endif +/* ========================================================================= */ + /* This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit integer pointer type. This violates the strict aliasing rule, where a @@ -87,62 +61,33 @@ uint32_t Z_EXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t /* ========================================================================= */ #if BYTE_ORDER == LITTLE_ENDIAN -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_little(uint32_t crc, const unsigned char *buf, uint64_t len) { - Z_REGISTER uint32_t c; - Z_REGISTER const uint32_t *buf4; - - c = crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const uint32_t *)(const void *)buf; - -#ifdef UNROLL_MORE - while (len >= 32) { - DOLIT32; - len -= 32; - } +#define DOSWAP(crc) (crc) +#define DO1 \ + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8) +#define DO4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#elif BYTE_ORDER == BIG_ENDIAN +#define DOSWAP(crc) ZSWAP32(crc) +#define DO1 \ + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8) +#define DO4 c ^= *buf4++; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#else +# error "No endian defined" #endif - - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return c; -} -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - -/* ========================================================================= */ -#if BYTE_ORDER == BIG_ENDIAN -#define DOBIG4 c ^= *buf4++; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 +#define DO32 DO4; DO4; DO4; DO4; DO4; DO4; DO4; DO4 /* ========================================================================= */ -Z_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_t len) { +Z_INTERNAL uint32_t crc32_byfour(uint32_t crc, const unsigned char *buf, uint64_t len) { Z_REGISTER uint32_t c; Z_REGISTER const uint32_t *buf4; - c = ZSWAP32(crc); + c = DOSWAP(crc); c = ~c; while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + DO1; len--; } @@ -150,21 +95,20 @@ Z_INTERNAL uint32_t crc32_big(uint32_t crc, const unsigned char *buf, uint64_t l #ifdef UNROLL_MORE while (len >= 32) { - DOBIG32; + DO32; len -= 32; } #endif while (len >= 4) { - DOBIG4; + DO4; len -= 4; } buf = (const unsigned char *)buf4; if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + DO1; } while (--len); c = ~c; - return ZSWAP32(c); + return DOSWAP(c); } -#endif /* BYTE_ORDER == BIG_ENDIAN */ diff --git a/crc32_p.h b/crc32_p.h index fbaf8db88c..371ddf1374 100644 --- a/crc32_p.h +++ b/crc32_p.h @@ -19,10 +19,6 @@ static inline uint32_t gf2_matrix_times(const uint32_t *mat, uint32_t vec) { } -#if BYTE_ORDER == LITTLE_ENDIAN -extern uint32_t crc32_little(uint32_t, const unsigned char *, uint64_t); -#elif BYTE_ORDER == BIG_ENDIAN -extern uint32_t crc32_big(uint32_t, const unsigned char *, uint64_t); -#endif +extern uint32_t crc32_byfour(uint32_t, const unsigned char *, uint64_t); #endif /* CRC32_P_H_ */ diff --git a/functable.c b/functable.c index ccb0b69a30..1c113c8db8 100644 --- a/functable.c +++ b/functable.c @@ -528,13 +528,7 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t Assert(sizeof(uint64_t) >= sizeof(size_t), "crc32_z takes size_t but internally we have a uint64_t len"); -#if BYTE_ORDER == LITTLE_ENDIAN - functable.crc32 = &crc32_little; -#elif BYTE_ORDER == BIG_ENDIAN - functable.crc32 = &crc32_big; -#else - functable.crc32 = &crc32_generic; -#endif + functable.crc32 = &crc32_byfour; cpu_check_features(); #ifdef ARM_ACLE_CRC_HASH if (arm_cpu_has_crc32) From 66506ace8d1b1cbd9fd5d2cfbae1c4f0b54ca9b9 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 8 Jan 2022 14:42:09 -0800 Subject: [PATCH 203/798] Convert compare258 to compare256 and moved 2 byte check into deflate_quick. Prevents having multiple compare258 functions with 2 byte checks. --- CMakeLists.txt | 10 ++-- Makefile.in | 4 +- README.md | 2 +- arch/x86/Makefile.in | 20 ++++---- .../{compare258_avx2.c => compare256_avx2.c} | 13 ++--- ...{compare258_sse42.c => compare256_sse42.c} | 13 ++--- compare258.c => compare256.c | 50 ++++--------------- configure | 8 +-- deflate_quick.c | 23 +++++---- functable.c | 32 ++++++------ functable.h | 2 +- win32/Makefile.a64 | 2 +- win32/Makefile.arm | 2 +- win32/Makefile.msc | 6 +-- 14 files changed, 73 insertions(+), 114 deletions(-) rename arch/x86/{compare258_avx2.c => compare256_avx2.c} (81%) rename arch/x86/{compare258_sse42.c => compare256_sse42.c} (82%) rename compare258.c => compare256.c (73%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 911bcb3fe2..9e7e353590 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -719,8 +719,8 @@ if(WITH_OPTIM) add_feature_info(AVX2_SLIDEHASH 1 "Support AVX2 optimized slide_hash, using \"${AVX2FLAG}\"") list(APPEND AVX2_SRCS ${ARCHDIR}/chunkset_avx.c) add_feature_info(AVX_CHUNKSET 1 "Support AVX optimized chunkset, using \"${AVX2FLAG}\"") - list(APPEND AVX2_SRCS ${ARCHDIR}/compare258_avx2.c) - add_feature_info(AVX2_COMPARE258 1 "Support AVX2 optimized compare258, using \"${AVX2FLAG}\"") + list(APPEND AVX2_SRCS ${ARCHDIR}/compare256_avx2.c) + add_feature_info(AVX2_COMPARE256 1 "Support AVX2 optimized compare256, using \"${AVX2FLAG}\"") list(APPEND AVX2_SRCS ${ARCHDIR}/adler32_avx2.c) add_feature_info(AVX2_ADLER32 1 "Support AVX2-accelerated adler32, using \"${AVX2FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${AVX2_SRCS}) @@ -782,8 +782,8 @@ if(WITH_OPTIM) endif() if(HAVE_SSE42CMPSTR_INTRIN) add_definitions(-DX86_SSE42_CMP_STR) - set(SSE42_SRCS ${ARCHDIR}/compare258_sse42.c) - add_feature_info(SSE42_COMPARE258 1 "Support SSE4.2 optimized compare258, using \"${SSE42FLAG}\"") + set(SSE42_SRCS ${ARCHDIR}/compare256_sse42.c) + add_feature_info(SSE42_COMPARE256 1 "Support SSE4.2 optimized compare256, using \"${SSE42FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") endif() @@ -946,7 +946,7 @@ set(ZLIB_PRIVATE_HDRS set(ZLIB_SRCS adler32.c chunkset.c - compare258.c + compare256.c compress.c crc32.c crc32_comb.c diff --git a/Makefile.in b/Makefile.in index 3b037302c5..9f64dabab8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -76,7 +76,7 @@ pkgconfigdir = ${libdir}/pkgconfig OBJZ = \ adler32.o \ chunkset.o \ - compare258.o \ + compare256.o \ compress.o \ crc32.o \ crc32_comb.o \ @@ -112,7 +112,7 @@ OBJC = $(OBJZ) $(OBJG) PIC_OBJZ = \ adler32.lo \ chunkset.lo \ - compare258.lo \ + compare256.lo \ compress.lo \ crc32.lo \ crc32_comb.lo \ diff --git a/README.md b/README.md index 79d6648bdb..599fdd9571 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Features * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, & ACLE * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX - * Compare256/258 implementations using SSE4.2 & AVX2 + * Compare256 implementations using SSE4.2 & AVX2 * Inflate chunk copying using SSE2, AVX2, Neon & VSX * CRC32 implementation using IBM Z vector instructions * Support for hardware-accelerated deflate using IBM Z DFLTCC diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index d481c0ee7d..f0d7c38f9f 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -32,8 +32,8 @@ all: \ adler32_ssse3.o adler32_ssse3.lo \ chunkset_avx.o chunkset_avx.lo \ chunkset_sse2.o chunkset_sse2.lo \ - compare258_avx2.o compare258_avx2.lo \ - compare258_sse42.o compare258_sse42.lo \ + compare256_avx2.o compare256_avx2.lo \ + compare256_sse42.o compare256_sse42.lo \ insert_string_sse42.o insert_string_sse42.lo \ crc32_fold_pclmulqdq.o crc32_fold_pclmulqdq.lo \ crc32_fold_vpclmulqdq.o crc32_fold_vpclmulqdq.lo \ @@ -58,17 +58,17 @@ chunkset_sse2.o: chunkset_sse2.lo: $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse2.c -compare258_avx2.o: - $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx2.c +compare256_avx2.o: + $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_avx2.c -compare258_avx2.lo: - $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_avx2.c +compare256_avx2.lo: + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_avx2.c -compare258_sse42.o: - $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse42.c +compare256_sse42.o: + $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse42.c -compare258_sse42.lo: - $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare258_sse42.c +compare256_sse42.lo: + $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse42.c insert_string_sse42.o: $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse42.c diff --git a/arch/x86/compare258_avx2.c b/arch/x86/compare256_avx2.c similarity index 81% rename from arch/x86/compare258_avx2.c rename to arch/x86/compare256_avx2.c index 9aefde16a3..253976b5bf 100644 --- a/arch/x86/compare258_avx2.c +++ b/arch/x86/compare256_avx2.c @@ -1,4 +1,4 @@ -/* compare258_avx2.c -- AVX2 version of compare258 +/* compare256_avx2.c -- AVX2 version of compare256 * Copyright Mika T. Lindqvist * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -47,15 +47,8 @@ static inline uint32_t compare256_unaligned_avx2_static(const unsigned char *src return 256; } -static inline uint32_t compare258_unaligned_avx2_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_avx2_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_avx2(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_avx2_static(src0, src1); +Z_INTERNAL uint32_t compare256_unaligned_avx2(const unsigned char *src0, const unsigned char *src1) { + return compare256_unaligned_avx2_static(src0, src1); } #define LONGEST_MATCH longest_match_unaligned_avx2 diff --git a/arch/x86/compare258_sse42.c b/arch/x86/compare256_sse42.c similarity index 82% rename from arch/x86/compare258_sse42.c rename to arch/x86/compare256_sse42.c index a5d568ff4f..3e5f150566 100644 --- a/arch/x86/compare258_sse42.c +++ b/arch/x86/compare256_sse42.c @@ -1,4 +1,4 @@ -/* compare258_sse42.c -- SSE4.2 version of compare258 +/* compare256_sse42.c -- SSE4.2 version of compare256 * * Copyright (C) 2013 Intel Corporation. All rights reserved. * Authors: @@ -54,15 +54,8 @@ static inline uint32_t compare256_unaligned_sse4_static(const unsigned char *src return 256; } -static inline uint32_t compare258_unaligned_sse4_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_sse4_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_sse4(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_sse4_static(src0, src1); +Z_INTERNAL uint32_t compare256_unaligned_sse4(const unsigned char *src0, const unsigned char *src1) { + return compare256_unaligned_sse4_static(src0, src1); } #define LONGEST_MATCH longest_match_unaligned_sse4 diff --git a/compare258.c b/compare256.c similarity index 73% rename from compare258.c rename to compare256.c index 8260f332b1..20d967e8bd 100644 --- a/compare258.c +++ b/compare256.c @@ -1,4 +1,4 @@ -/* compare258.c -- aligned and unaligned versions of compare258 +/* compare256.c -- 256 byte memory comparison with match length return * Copyright (C) 2020 Nathan Moinvaziri * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -42,19 +42,8 @@ static inline uint32_t compare256_c_static(const unsigned char *src0, const unsi return 256; } -static inline uint32_t compare258_c_static(const unsigned char *src0, const unsigned char *src1) { - if (*src0 != *src1) - return 0; - src0 += 1, src1 += 1; - if (*src0 != *src1) - return 1; - src0 += 1, src1 += 1; - - return compare256_c_static(src0, src1) + 2; -} - -Z_INTERNAL uint32_t compare258_c(const unsigned char *src0, const unsigned char *src1) { - return compare258_c_static(src0, src1); +Z_INTERNAL uint32_t compare256_c(const unsigned char *src0, const unsigned char *src1) { + return compare256_c_static(src0, src1); } #define LONGEST_MATCH longest_match_c @@ -91,15 +80,8 @@ static inline uint32_t compare256_unaligned_16_static(const unsigned char *src0, return 256; } -static inline uint32_t compare258_unaligned_16_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_16_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_16(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_16_static(src0, src1); +Z_INTERNAL uint32_t compare256_unaligned_16(const unsigned char *src0, const unsigned char *src1) { + return compare256_unaligned_16_static(src0, src1); } #define LONGEST_MATCH longest_match_unaligned_16 @@ -136,15 +118,8 @@ static inline uint32_t compare256_unaligned_32_static(const unsigned char *src0, return 256; } -static inline uint32_t compare258_unaligned_32_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_32_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_32(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_32_static(src0, src1); +Z_INTERNAL uint32_t compare256_unaligned_32(const unsigned char *src0, const unsigned char *src1) { + return compare256_unaligned_32_static(src0, src1); } #define LONGEST_MATCH longest_match_unaligned_32 @@ -183,15 +158,8 @@ static inline uint32_t compare256_unaligned_64_static(const unsigned char *src0, return 256; } -static inline uint32_t compare258_unaligned_64_static(const unsigned char *src0, const unsigned char *src1) { - if (*(uint16_t *)src0 != *(uint16_t *)src1) - return (*src0 == *src1); - - return compare256_unaligned_64_static(src0+2, src1+2) + 2; -} - -Z_INTERNAL uint32_t compare258_unaligned_64(const unsigned char *src0, const unsigned char *src1) { - return compare258_unaligned_64_static(src0, src1); +Z_INTERNAL uint32_t compare256_unaligned_64(const unsigned char *src0, const unsigned char *src1) { + return compare256_unaligned_64_static(src0, src1); } #define LONGEST_MATCH longest_match_unaligned_64 diff --git a/configure b/configure index f5fe81cbc7..215d0f286f 100755 --- a/configure +++ b/configure @@ -1438,8 +1438,8 @@ case "${ARCH}" in if test ${HAVE_AVX2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" SFLAGS="${SFLAGS} -DX86_AVX2 -DX86_AVX2_ADLER32 -DX86_AVX_CHUNKSET" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_hash_avx2.o chunkset_avx.o compare258_avx2.o adler32_avx2.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx2.lo chunkset_avx.lo compare258_avx2.lo adler32_avx2.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} slide_hash_avx2.o chunkset_avx.o compare256_avx2.o adler32_avx2.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} slide_hash_avx2.lo chunkset_avx.lo compare256_avx2.lo adler32_avx2.lo" fi check_avx512_intrinsics @@ -1495,8 +1495,8 @@ case "${ARCH}" in CFLAGS="${CFLAGS} -DX86_SSE42_CMP_STR" SFLAGS="${SFLAGS} -DX86_SSE42_CMP_STR" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} compare258_sse42.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} compare258_sse42.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} compare256_sse42.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} compare256_sse42.lo" fi check_sse2_intrinsics diff --git a/deflate_quick.c b/deflate_quick.c index 8b98397161..a214a7fe13 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -89,18 +89,23 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { dist = (int64_t)s->strstart - hash_head; if (dist <= MAX_DIST(s) && dist > 0) { - match_len = functable.compare258(s->window + s->strstart, s->window + hash_head); + const uint8_t *str_start = s->window + s->strstart; + const uint8_t *match_start = s->window + hash_head; - if (match_len >= WANT_MIN_MATCH) { - if (UNLIKELY(match_len > s->lookahead)) - match_len = s->lookahead; + if (*(uint16_t *)str_start == *(uint16_t *)match_start) { + match_len = functable.compare256(str_start+2, match_start+2) + 2; - check_match(s, s->strstart, hash_head, match_len); + if (match_len >= WANT_MIN_MATCH) { + if (UNLIKELY(match_len > s->lookahead)) + match_len = s->lookahead; - zng_tr_emit_dist(s, static_ltree, static_dtree, match_len - STD_MIN_MATCH, (uint32_t)dist); - s->lookahead -= match_len; - s->strstart += match_len; - continue; + check_match(s, s->strstart, hash_head, match_len); + + zng_tr_emit_dist(s, static_ltree, static_dtree, match_len - STD_MIN_MATCH, (uint32_t)dist); + s->lookahead -= match_len; + s->strstart += match_len; + continue; + } } } } diff --git a/functable.c b/functable.c index 1c113c8db8..3cfa13ade3 100644 --- a/functable.c +++ b/functable.c @@ -144,19 +144,19 @@ extern uint32_t crc32_power8(uint32_t, const unsigned char *, uint64_t); extern uint32_t s390_crc32_vx(uint32_t, const unsigned char *, uint64_t); #endif -/* compare258 */ -extern uint32_t compare258_c(const unsigned char *src0, const unsigned char *src1); +/* compare256 */ +extern uint32_t compare256_c(const unsigned char *src0, const unsigned char *src1); #ifdef UNALIGNED_OK -extern uint32_t compare258_unaligned_16(const unsigned char *src0, const unsigned char *src1); -extern uint32_t compare258_unaligned_32(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_16(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_32(const unsigned char *src0, const unsigned char *src1); #ifdef UNALIGNED64_OK -extern uint32_t compare258_unaligned_64(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_64(const unsigned char *src0, const unsigned char *src1); #endif #ifdef X86_SSE42_CMP_STR -extern uint32_t compare258_unaligned_sse4(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_sse4(const unsigned char *src0, const unsigned char *src1); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t compare258_unaligned_avx2(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_avx2(const unsigned char *src0, const unsigned char *src1); #endif #endif @@ -544,29 +544,29 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t return functable.crc32(crc, buf, len); } -Z_INTERNAL uint32_t compare258_stub(const unsigned char *src0, const unsigned char *src1) { +Z_INTERNAL uint32_t compare256_stub(const unsigned char *src0, const unsigned char *src1) { #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.compare258 = &compare258_unaligned_64; + functable.compare256 = &compare256_unaligned_64; # elif defined(HAVE_BUILTIN_CTZ) - functable.compare258 = &compare258_unaligned_32; + functable.compare256 = &compare256_unaligned_32; # else - functable.compare258 = &compare258_unaligned_16; + functable.compare256 = &compare256_unaligned_16; # endif # ifdef X86_SSE42_CMP_STR if (x86_cpu_has_sse42) - functable.compare258 = &compare258_unaligned_sse4; + functable.compare256 = &compare256_unaligned_sse4; # endif # if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) - functable.compare258 = &compare258_unaligned_avx2; + functable.compare256 = &compare256_unaligned_avx2; # endif #else - functable.compare258 = &compare258_c; + functable.compare256 = &compare256_c; #endif - return functable.compare258(src0, src1); + return functable.compare256(src0, src1); } Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { @@ -630,7 +630,7 @@ Z_INTERNAL Z_TLS struct functable_s functable = { crc32_fold_copy_stub, crc32_fold_final_stub, slide_hash_stub, - compare258_stub, + compare256_stub, longest_match_stub, longest_match_slow_stub, chunksize_stub, diff --git a/functable.h b/functable.h index 36039fcb27..f029ed4d13 100644 --- a/functable.h +++ b/functable.h @@ -19,7 +19,7 @@ struct functable_s { void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); uint32_t (* crc32_fold_final) (crc32_fold *crc); void (* slide_hash) (deflate_state *s); - uint32_t (* compare258) (const unsigned char *src0, const unsigned char *src1); + uint32_t (* compare256) (const unsigned char *src0, const unsigned char *src1); uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); uint32_t (* chunksize) (void); diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 580b5bfb1d..82ca6c2dc1 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -46,7 +46,7 @@ OBJS = \ adler32.obj \ armfeature.obj \ chunkset.obj \ - compare258.obj \ + compare256.obj \ compress.obj \ crc32.obj \ crc32_comb.obj \ diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 12b08dc671..ace50794e2 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -49,7 +49,7 @@ OBJS = \ adler32.obj \ armfeature.obj \ chunkset.obj \ - compare258.obj \ + compare256.obj \ compress.obj \ crc32.obj \ crc32_comb.obj \ diff --git a/win32/Makefile.msc b/win32/Makefile.msc index ff6c6963c9..cfdfcca749 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -53,9 +53,9 @@ OBJS = \ chunkset.obj \ chunkset_avx.obj \ chunkset_sse2.obj \ - compare258.obj \ - compare258_avx2.obj \ - compare258_sse42.obj \ + compare256.obj \ + compare256_avx2.obj \ + compare256_sse42.obj \ compress.obj \ crc32.obj \ crc32_comb.obj \ From c92e70ccba6576462501f61d7afd86f0eae86fcf Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 9 Jan 2022 11:57:24 -0500 Subject: [PATCH 204/798] Improved AVX2 adler32 performance Did this by simply doing 32 bit horizontal sums and using the same sum of absolute difference instructions as done in the SSE4 and AVX512_VNNI versions. --- arch/x86/adler32_avx2.c | 103 ++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 58 deletions(-) diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index 4068523470..bc9156bb3d 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -14,19 +14,24 @@ #ifdef X86_AVX2_ADLER32 -/* 64 bit horizontal sum, adapted from Agner Fog's vector library. */ -static inline uint64_t hsum(__m256i x) { - __m256i sum1 = _mm256_shuffle_epi32(x, 0x0E); - __m256i sum2 = _mm256_add_epi64(x, sum1); - __m128i sum3 = _mm256_extracti128_si256(sum2, 1); -#if defined(__x86_64__) || defined(_M_X64) - return _mm_cvtsi128_si64(_mm_add_epi64(_mm256_castsi256_si128(sum2), sum3)); -#else - __m128i ret_vec = _mm_add_epi64(_mm256_castsi256_si128(sum2), sum3); - uint64_t ret_val; - _mm_storel_epi64((__m128i*)&ret_val, ret_vec); - return ret_val; -#endif +/* 32 bit horizontal sum, adapted from Agner Fog's vector library. */ +static inline uint32_t hsum(__m256i x) { + __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(x, 1), + _mm256_castsi256_si128(x)); + __m128i sum2 = _mm_add_epi32(sum1, _mm_unpackhi_epi64(sum1, sum1)); + __m128i sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} + +static inline uint32_t partial_hsum(__m256i x) { + /* We need a permutation vector to extract every other integer. The + * rest are going to be zeros */ + const __m256i perm_vec = _mm256_setr_epi32(0, 2, 4, 6, 1, 1, 1, 1); + __m256i non_zero = _mm256_permutevar8x32_epi32(x, perm_vec); + __m128i non_zero_sse = _mm256_castsi256_si128(non_zero); + __m128i sum2 = _mm_add_epi32(non_zero_sse,_mm_unpackhi_epi64(non_zero_sse, non_zero_sse)); + __m128i sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); } Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len) { @@ -48,19 +53,17 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); - const __m256i vs_mask = _mm256_setr_epi32(0, 0, 0, 0, 0, 0, 0, -1); - __m256i vs1 = _mm256_set1_epi32(adler); - __m256i vs2 = _mm256_set1_epi32(sum2); - vs1 = _mm256_and_si256(vs1, vs_mask); - vs2 = _mm256_and_si256(vs2, vs_mask); + __m256i vs1 = _mm256_castsi128_si256(_mm_cvtsi32_si128(adler)); + __m256i vs2 = _mm256_castsi128_si256(_mm_cvtsi32_si128(sum2)); - const __m256i dot1v = _mm256_set1_epi8(1); const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); const __m256i dot3v = _mm256_set1_epi16(1); + const __m256i zero = _mm256_setzero_si256(); while (len >= 32) { __m256i vs1_0 = vs1; + __m256i vs3 = _mm256_setzero_si256(); int k = (len < NMAX ? (int)len : NMAX); k -= k % 32; @@ -75,17 +78,19 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ buf += 32; k -= 32; - __m256i v_short_sum1 = _mm256_maddubs_epi16(vbuf, dot1v); // multiply-add, resulting in 8 shorts. - __m256i vsum1 = _mm256_madd_epi16(v_short_sum1, dot3v); // sum 8 shorts to 4 int32_t; - __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); - vs1 = _mm256_add_epi32(vsum1, vs1); - __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); - vs1_0 = _mm256_slli_epi32(vs1_0, 5); - vsum2 = _mm256_add_epi32(vsum2, vs2); - vs2 = _mm256_add_epi32(vsum2, vs1_0); + __m256i vs1_sad = _mm256_sad_epu8(vbuf, zero); // Sum of abs diff, resulting in 2 x int32's + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs3 = _mm256_add_epi32(vs3, vs1_0); + __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); // sum 32 uint8s to 16 shorts + __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); // sum 16 shorts to 8 uint32s + vs2 = _mm256_add_epi32(vsum2, vs2); vs1_0 = vs1; } + /* Defer the multiplication with 32 to outside of the loop */ + vs3 = _mm256_slli_epi32(vs3, 5); + vs2 = _mm256_add_epi32(vs2, vs3); + /* The compiler is generating the following sequence for this integer modulus * when done the scalar way, in GPRs: @@ -109,41 +114,23 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ back down to 32 bit precision later (there is in AVX512) 3.) Full width integer multiplications aren't cheap - We can, however, cast up to 64 bit precision on all 8 integers at once, and do a relatively - cheap sequence for horizontal sums. Then, we simply do the integer modulus on the resulting - 64 bit GPR, on a scalar value + We can, however, and do a relatively cheap sequence for horizontal sums. + Then, we simply do the integer modulus on the resulting 64 bit GPR, on a scalar value. It was + previously thought that casting to 64 bit precision was needed prior to the horizontal sum, but + that is simply not the case, as NMAX is defined as the maximum number of scalar sums that can be + performed on the maximum possible inputs before overflow */ - /* Will translate to nops */ - __m128i s1lo = _mm256_castsi256_si128(vs1); - __m128i s2lo = _mm256_castsi256_si128(vs2); - - /* Requires vextracti128 */ - __m128i s1hi = _mm256_extracti128_si256(vs1, 1); - __m128i s2hi = _mm256_extracti128_si256(vs2, 1); - - /* Convert up to 64 bit precision to prevent overflow */ - __m256i s1lo256 = _mm256_cvtepi32_epi64(s1lo); - __m256i s1hi256 = _mm256_cvtepi32_epi64(s1hi); - __m256i s2lo256 = _mm256_cvtepi32_epi64(s2lo); - __m256i s2hi256 = _mm256_cvtepi32_epi64(s2hi); - - /* Sum vectors in existing lanes */ - __m256i s1_sum = _mm256_add_epi64(s1lo256, s1hi256); - __m256i s2_sum = _mm256_add_epi64(s2lo256, s2hi256); - /* In AVX2-land, this trip through GPRs will probably be unvoidable, as there's no cheap and easy - * conversion from 64 bit integer to 32 bit. This casting to 32 bit is cheap through GPRs - * (just register aliasing), and safe, as our base is significantly smaller than UINT32_MAX */ - adler = (uint32_t)(hsum(s1_sum) % BASE); - sum2 = (uint32_t)(hsum(s2_sum) % BASE); - - vs1 = _mm256_set1_epi32(adler); - vs2 = _mm256_set1_epi32(sum2); - - vs1 = _mm256_and_si256(vs1, vs_mask); - vs2 = _mm256_and_si256(vs2, vs_mask); + * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). + * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly + * what the compiler is doing to avoid integer divisions. */ + adler = partial_hsum(vs1) % BASE; + sum2 = hsum(vs2) % BASE; + + vs1 = _mm256_castsi128_si256(_mm_cvtsi32_si128(adler)); + vs2 = _mm256_castsi128_si256(_mm_cvtsi32_si128(sum2)); } /* Process tail (len < 16). */ From b001d0917e7ec96ad36f626eb3e610555c5b3e43 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 3 Jan 2022 13:07:24 -0800 Subject: [PATCH 205/798] Change fuzzer binaries and solutions to prefix with fuzzer_. --- CMakeLists.txt | 10 ++-- Makefile.in | 48 +++++++++---------- test/Makefile.in | 14 +++--- .../{checksum_fuzzer.c => fuzzer_checksum.c} | 0 .../{compress_fuzzer.c => fuzzer_compress.c} | 0 ...le_dict_fuzzer.c => fuzzer_example_dict.c} | 0 ..._flush_fuzzer.c => fuzzer_example_flush.c} | 0 ..._large_fuzzer.c => fuzzer_example_large.c} | 0 ..._small_fuzzer.c => fuzzer_example_small.c} | 0 .../{minigzip_fuzzer.c => fuzzer_minigzip.c} | 0 10 files changed, 36 insertions(+), 36 deletions(-) rename test/fuzz/{checksum_fuzzer.c => fuzzer_checksum.c} (100%) rename test/fuzz/{compress_fuzzer.c => fuzzer_compress.c} (100%) rename test/fuzz/{example_dict_fuzzer.c => fuzzer_example_dict.c} (100%) rename test/fuzz/{example_flush_fuzzer.c => fuzzer_example_flush.c} (100%) rename test/fuzz/{example_large_fuzzer.c => fuzzer_example_large.c} (100%) rename test/fuzz/{example_small_fuzzer.c => fuzzer_example_small.c} (100%) rename test/fuzz/{minigzip_fuzzer.c => fuzzer_minigzip.c} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e7e353590..104ff163c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1280,11 +1280,11 @@ if(ZLIB_ENABLE_TESTS) set(FUZZERS checksum compress example_small example_large example_flush example_dict minigzip) file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*") foreach(FUZZER ${FUZZERS}) - add_executable(${FUZZER}_fuzzer test/fuzz/${FUZZER}_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c) - configure_test_executable(${FUZZER}_fuzzer) - target_link_libraries(${FUZZER}_fuzzer zlib) - set(FUZZER_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ ${ALL_SRC_FILES}) - add_test(NAME ${FUZZER}_fuzzer COMMAND ${FUZZER_COMMAND}) + add_executable(fuzzer_${FUZZER} test/fuzz/fuzzer_${FUZZER}.c test/fuzz/standalone_fuzz_target_runner.c) + configure_test_executable(fuzzer_${FUZZER}) + target_link_libraries(fuzzer_${FUZZER} zlib) + set(FUZZER_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ ${ALL_SRC_FILES}) + add_test(NAME fuzzer_${FUZZER} COMMAND ${FUZZER_COMMAND}) endforeach() endif() diff --git a/Makefile.in b/Makefile.in index 9f64dabab8..8f89d0a9c5 100644 --- a/Makefile.in +++ b/Makefile.in @@ -191,7 +191,7 @@ else endif ifeq (1,$(WITH_FUZZERS)) -fuzzers: checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE) +fuzzers: fuzzer_checksum$(EXE) fuzzer_compress$(EXE) fuzzer_example_small$(EXE) fuzzer_example_large$(EXE) fuzzer_example_flush$(EXE) fuzzer_example_dict$(EXE) fuzzer_minigzip$(EXE) else fuzzers: endif @@ -199,34 +199,34 @@ endif # The standalone fuzz target runner. standalone_fuzz_target_runner.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -checksum_fuzzer.o: +fuzzer_checksum.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -compress_fuzzer.o: +fuzzer_compress.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -example_small_fuzzer.o: +fuzzer_example_small.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -example_large_fuzzer.o: +fuzzer_example_large.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -example_flush_fuzzer.o: +fuzzer_example_flush.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -example_dict_fuzzer.o: +fuzzer_example_dict.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -minigzip_fuzzer.o: +fuzzer_minigzip.o: $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< -checksum_fuzzer$(EXE): checksum_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) checksum_fuzzer.o $(STATICLIB) -lpthread -compress_fuzzer$(EXE): compress_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) compress_fuzzer.o $(STATICLIB) -lpthread -example_small_fuzzer$(EXE): example_small_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_small_fuzzer.o $(STATICLIB) -lpthread -example_large_fuzzer$(EXE): example_large_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_large_fuzzer.o $(STATICLIB) -lpthread -example_flush_fuzzer$(EXE): example_flush_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_flush_fuzzer.o $(STATICLIB) -lpthread -example_dict_fuzzer$(EXE): example_dict_fuzzer.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) example_dict_fuzzer.o $(STATICLIB) -lpthread -minigzip_fuzzer$(EXE): minigzip_fuzzer.o standalone_fuzz_target_runner.o $(OBJG) $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) minigzip_fuzzer.o $(OBJG) $(STATICLIB) -lpthread +fuzzer_checksum$(EXE): fuzzer_checksum.o standalone_fuzz_target_runner.o $(STATICLIB) + $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_checksum.o $(STATICLIB) -lpthread +fuzzer_compress$(EXE): fuzzer_compress.o standalone_fuzz_target_runner.o $(STATICLIB) + $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_compress.o $(STATICLIB) -lpthread +fuzzer_example_small$(EXE): fuzzer_example_small.o standalone_fuzz_target_runner.o $(STATICLIB) + $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_example_small.o $(STATICLIB) -lpthread +fuzzer_example_large$(EXE): fuzzer_example_large.o standalone_fuzz_target_runner.o $(STATICLIB) + $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_example_large.o $(STATICLIB) -lpthread +fuzzer_example_flush$(EXE): fuzzer_example_flush.o standalone_fuzz_target_runner.o $(STATICLIB) + $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_example_flush.o $(STATICLIB) -lpthread +fuzzer_example_dict$(EXE): fuzzer_example_dict.o standalone_fuzz_target_runner.o $(STATICLIB) + $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_example_dict.o $(STATICLIB) -lpthread +fuzzer_minigzip$(EXE): fuzzer_minigzip.o standalone_fuzz_target_runner.o $(OBJG) $(STATICLIB) + $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_minigzip.o $(OBJG) $(STATICLIB) -lpthread infcover.o: $(SRCDIR)/test/infcover.c zlib$(SUFFIX).h zconf$(SUFFIX).h zlib_name_mangling$(SUFFIX).h $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c @@ -439,8 +439,8 @@ clean: rm -f *.o *.lo *~ \ adler32_test$(EXE) crc32_test$(EXE) example$(EXE) minigzip$(EXE) \ adler32_testsh$(EXE) crc32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ - checksum_fuzzer$(EXE) compress_fuzzer$(EXE) example_small_fuzzer$(EXE) example_large_fuzzer$(EXE) \ - example_flush_fuzzer$(EXE) example_dict_fuzzer$(EXE) minigzip_fuzzer$(EXE) \ + fuzzer_checksum$(EXE) fuzzer_compress$(EXE) fuzzer_example_small$(EXE) fuzzer_example_large$(EXE) \ + fuzzer_example_flush$(EXE) fuzzer_example_dict$(EXE) fuzzer_minigzip$(EXE) \ infcover makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) \ $(STATICLIB) $(IMPORTLIB) $(SHAREDLIB) $(SHAREDLIBV) $(SHAREDLIBM) \ foo.gz so_locations \ diff --git a/test/Makefile.in b/test/Makefile.in index 6a075d362e..ce6d06a35b 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -35,13 +35,13 @@ else fuzzer: else fuzzer: - @${QEMU_RUN} ../checksum_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../compress_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../example_small_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../example_large_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../example_flush_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../example_dict_fuzzer$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../minigzip_fuzzer$(EXE) $(ALL_SRC_FILES) + @${QEMU_RUN} ../fuzzer_checksumr$(EXE) $(ALL_SRC_FILES) && \ + ${QEMU_RUN} ../fuzzer_compress$(EXE) $(ALL_SRC_FILES) && \ + ${QEMU_RUN} ../fuzzer_example_small$(EXE) $(ALL_SRC_FILES) && \ + ${QEMU_RUN} ../fuzzer_example_large$(EXE) $(ALL_SRC_FILES) && \ + ${QEMU_RUN} ../fuzzer_example_flush$(EXE) $(ALL_SRC_FILES) && \ + ${QEMU_RUN} ../fuzzer_example_dict$(EXE) $(ALL_SRC_FILES) && \ + ${QEMU_RUN} ../fuzzer_minigzip$(EXE) $(ALL_SRC_FILES) endif endif diff --git a/test/fuzz/checksum_fuzzer.c b/test/fuzz/fuzzer_checksum.c similarity index 100% rename from test/fuzz/checksum_fuzzer.c rename to test/fuzz/fuzzer_checksum.c diff --git a/test/fuzz/compress_fuzzer.c b/test/fuzz/fuzzer_compress.c similarity index 100% rename from test/fuzz/compress_fuzzer.c rename to test/fuzz/fuzzer_compress.c diff --git a/test/fuzz/example_dict_fuzzer.c b/test/fuzz/fuzzer_example_dict.c similarity index 100% rename from test/fuzz/example_dict_fuzzer.c rename to test/fuzz/fuzzer_example_dict.c diff --git a/test/fuzz/example_flush_fuzzer.c b/test/fuzz/fuzzer_example_flush.c similarity index 100% rename from test/fuzz/example_flush_fuzzer.c rename to test/fuzz/fuzzer_example_flush.c diff --git a/test/fuzz/example_large_fuzzer.c b/test/fuzz/fuzzer_example_large.c similarity index 100% rename from test/fuzz/example_large_fuzzer.c rename to test/fuzz/fuzzer_example_large.c diff --git a/test/fuzz/example_small_fuzzer.c b/test/fuzz/fuzzer_example_small.c similarity index 100% rename from test/fuzz/example_small_fuzzer.c rename to test/fuzz/fuzzer_example_small.c diff --git a/test/fuzz/minigzip_fuzzer.c b/test/fuzz/fuzzer_minigzip.c similarity index 100% rename from test/fuzz/minigzip_fuzzer.c rename to test/fuzz/fuzzer_minigzip.c From 6f179fd3014b61e77bc22245026f6630b05a863d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 8 Jan 2022 13:28:41 -0800 Subject: [PATCH 206/798] Added adler32, compare256, crc32, and slide_hash benchmarks using Google Benchmark. Co-authored-by: Adam Stylinski --- .github/workflows/cmake.yml | 8 +- .github/workflows/configure.yml | 4 +- CMakeLists.txt | 8 + Makefile.in | 2 + README.md | 1 + arch/x86/x86.c | 5 +- arch/x86/x86.h | 2 +- cpu_features.c | 23 +++ cpu_features.h | 190 +++++++++++++++++++++++ functable.c | 198 +----------------------- test/benchmarks/CMakeLists.txt | 45 ++++++ test/benchmarks/README.md | 19 +++ test/benchmarks/benchmark_adler32.cc | 94 +++++++++++ test/benchmarks/benchmark_compare256.cc | 84 ++++++++++ test/benchmarks/benchmark_crc32.cc | 80 ++++++++++ test/benchmarks/benchmark_main.cc | 25 +++ test/benchmarks/benchmark_slidehash.cc | 91 +++++++++++ win32/Makefile.a64 | 2 + win32/Makefile.arm | 2 + win32/Makefile.msc | 2 + 20 files changed, 681 insertions(+), 204 deletions(-) create mode 100644 cpu_features.c create mode 100644 cpu_features.h create mode 100644 test/benchmarks/CMakeLists.txt create mode 100644 test/benchmarks/README.md create mode 100644 test/benchmarks/benchmark_adler32.cc create mode 100644 test/benchmarks/benchmark_compare256.cc create mode 100644 test/benchmarks/benchmark_crc32.cc create mode 100644 test/benchmarks/benchmark_main.cc create mode 100644 test/benchmarks/benchmark_slidehash.cc diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 5662ed5d8f..918be18b33 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -18,13 +18,19 @@ jobs: cmake-args: -DWITH_SANITIZER=Address codecov: ubuntu_gcc + - name: Ubuntu GCC Benchmark + os: ubuntu-latest + compiler: gcc + cmake-args: -DWITH_BENCHMARKS=ON + codecov: ubuntu_gcc_benchmark + - name: Ubuntu GCC Symbol Prefix os: ubuntu-latest compiler: gcc cmake-args: -DZLIB_SYMBOL_PREFIX=zTest_ codecov: ubuntu_gcc_sprefix - - name: Ubuntu GCC Compat SPrefix + - name: Ubuntu GCC Compat Symbol Prefix os: ubuntu-latest compiler: gcc cmake-args: -DZLIB_COMPAT=ON -DZLIB_SYMBOL_PREFIX=zTest_ diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 6458673a1e..2c72afb8aa 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -176,12 +176,12 @@ jobs: compiler: gcc configure-args: --warn --zlib-compat --static --with-dfltcc-deflate --with-dfltcc-inflate - - name: macOS GCC symbol prefix + - name: macOS GCC Symbol Prefix os: macOS-latest compiler: gcc configure-args: --sprefix=zTest_ - - name: macOS GCC symbol prefix & compat + - name: macOS GCC Symbol Prefix & Compat os: macOS-latest compiler: gcc configure-args: --zlib-compat --sprefix=zTest_ diff --git a/CMakeLists.txt b/CMakeLists.txt index 104ff163c3..5391fd5c59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ option(ZLIB_COMPAT "Compile with zlib compatible API" OFF) option(ZLIB_ENABLE_TESTS "Build test binaries" ON) option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) option(WITH_FUZZERS "Build test/fuzz" OFF) +option(WITH_BENCHMARKS "Build test/benchmarks" OFF) option(WITH_OPTIM "Build with optimisation" ON) option(WITH_REDUCED_MEM "Reduced memory usage for special cases (reduces performance)" OFF) option(WITH_NEW_STRATEGIES "Use new strategies" ON) @@ -922,6 +923,7 @@ set(ZLIB_PUBLIC_HDRS set(ZLIB_PRIVATE_HDRS adler32_p.h chunkset_tpl.h + cpu_features.h crc32_p.h crc32_tbl.h crc32_comb_tbl.h @@ -948,6 +950,7 @@ set(ZLIB_SRCS chunkset.c compare256.c compress.c + cpu_features.c crc32.c crc32_comb.c crc32_fold.c @@ -1288,6 +1291,10 @@ if(ZLIB_ENABLE_TESTS) endforeach() endif() + if(WITH_BENCHMARKS) + add_subdirectory(test/benchmarks) + endif() + macro(test_minigzip name path) # Construct compression arguments for minigzip set(compress_args -k -c) @@ -1446,6 +1453,7 @@ add_feature_info(ZLIB_ENABLE_TESTS ZLIB_ENABLE_TESTS "Build test binaries") add_feature_info(ZLIB_DUAL_LINK ZLIB_DUAL_LINK "Dual link tests against system zlib") add_feature_info(WITH_SANITIZER WITH_SANITIZER "Enable sanitizer support") add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz") +add_feature_info(WITH_BENCHMARKS WITH_BENCHMARKS "Build test/benchmarks") add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation") add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies") add_feature_info(WITH_NATIVE_INSTRUCTIONS WITH_NATIVE_INSTRUCTIONS diff --git a/Makefile.in b/Makefile.in index 8f89d0a9c5..ca2b1127f7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -78,6 +78,7 @@ OBJZ = \ chunkset.o \ compare256.o \ compress.o \ + cpu_features.o \ crc32.o \ crc32_comb.o \ crc32_fold.o \ @@ -114,6 +115,7 @@ PIC_OBJZ = \ chunkset.lo \ compare256.lo \ compress.lo \ + cpu_features.lo \ crc32.lo \ crc32_comb.lo \ crc32_fold.lo \ diff --git a/README.md b/README.md index 599fdd9571..5b4834d7b0 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ Build Options | WITH_NATIVE_INSTRUCTIONS | --native | Compiles with full instruction set supported on this host (gcc/clang -march=native) | OFF | | WITH_SANITIZER | --with-sanitizer | Build with sanitizer (memory, address, undefined) | OFF | | WITH_FUZZERS | --with-fuzzers | Build test/fuzz | OFF | +| WITH_BENCHMARKS | | Build test/benchmarks | OFF | | WITH_MAINTAINER_WARNINGS | | Build with project maintainer warnings | OFF | | WITH_CODE_COVERAGE | | Enable code coverage reporting | OFF | diff --git a/arch/x86/x86.c b/arch/x86/x86.c index 32baf8a749..66bfa4e284 100644 --- a/arch/x86/x86.c +++ b/arch/x86/x86.c @@ -1,5 +1,4 @@ -/* - * x86 feature check +/* x86.c - x86 feature check * * Copyright (C) 2013 Intel Corporation. All rights reserved. * Author: @@ -119,7 +118,7 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_well_suited_avx512 = 1; } else if (model == 0xa && extended_model == 0x6) { /* Icelake server */ - x86_cpu_well_suited_avx512 = 1; + x86_cpu_well_suited_avx512 = 1; } else if (model == 0xf && extended_model == 0x8) { /* Saphire rapids */ x86_cpu_well_suited_avx512 = 1; diff --git a/arch/x86/x86.h b/arch/x86/x86.h index 00f8d9efc7..0cb79e69a1 100644 --- a/arch/x86/x86.h +++ b/arch/x86/x86.h @@ -1,4 +1,4 @@ -/* cpu.h -- check for CPU features +/* x86.h -- check for CPU features * Copyright (C) 2013 Intel Corporation Jim Kukunas * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/cpu_features.c b/cpu_features.c new file mode 100644 index 0000000000..70bfcb698c --- /dev/null +++ b/cpu_features.c @@ -0,0 +1,23 @@ +/* cpu_features.c -- CPU architecture feature check + * Copyright (C) 2017 Hans Kristian Rosbach + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "zutil.h" + +Z_INTERNAL void cpu_check_features(void) { + static int features_checked = 0; + if (features_checked) + return; +#if defined(X86_FEATURES) + x86_check_features(); +#elif defined(ARM_FEATURES) + arm_check_features(); +#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) + power_check_features(); +#elif defined(S390_FEATURES) + s390_check_features(); +#endif + features_checked = 1; +} diff --git a/cpu_features.h b/cpu_features.h new file mode 100644 index 0000000000..4cd1ed7b26 --- /dev/null +++ b/cpu_features.h @@ -0,0 +1,190 @@ +/* cpu_features.h -- CPU architecture feature check + * Copyright (C) 2017 Hans Kristian Rosbach + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef CPU_FEATURES +#define CPU_FEATURES + +#include "deflate.h" +#include "crc32_fold.h" + +#ifdef X86_FEATURES +# include "fallback_builtins.h" +#endif + +extern void cpu_check_features(); + +/* update_hash */ +extern uint32_t update_hash_c(deflate_state *const s, uint32_t h, uint32_t val); +#ifdef X86_SSE42_CRC_HASH +extern uint32_t update_hash_sse4(deflate_state *const s, uint32_t h, uint32_t val); +#elif defined(ARM_ACLE_CRC_HASH) +extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); +#endif + +/* insert_string */ +extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); +#ifdef X86_SSE42_CRC_HASH +extern void insert_string_sse4(deflate_state *const s, const uint32_t str, uint32_t count); +#elif defined(ARM_ACLE_CRC_HASH) +extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint32_t count); +#endif + +/* quick_insert_string */ +extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); +#ifdef X86_SSE42_CRC_HASH +extern Pos quick_insert_string_sse4(deflate_state *const s, const uint32_t str); +#elif defined(ARM_ACLE_CRC_HASH) +extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); +#endif + +/* slide_hash */ +#ifdef X86_SSE2 +void slide_hash_sse2(deflate_state *s); +#elif defined(ARM_NEON_SLIDEHASH) +void slide_hash_neon(deflate_state *s); +#endif +#if defined(PPC_VMX_SLIDEHASH) +void slide_hash_vmx(deflate_state *s); +#endif +#if defined(POWER8_VSX_SLIDEHASH) +void slide_hash_power8(deflate_state *s); +#endif +#ifdef X86_AVX2 +void slide_hash_avx2(deflate_state *s); +#endif + +/* adler32 */ +extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len); +#ifdef ARM_NEON_ADLER32 +extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len); +#endif +#ifdef PPC_VMX_ADLER32 +extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len); +#endif +#ifdef X86_SSE41_ADLER32 +extern uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size_t len); +#endif +#ifdef X86_SSSE3_ADLER32 +extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); +#endif +#ifdef X86_AVX2_ADLER32 +extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); +#endif +#ifdef X86_AVX512_ADLER32 +extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len); +#endif +#ifdef X86_AVX512VNNI_ADLER32 +extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len); +#endif +#ifdef POWER8_VSX_ADLER32 +extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len); +#endif + +/* CRC32 folding */ +#ifdef X86_PCLMULQDQ_CRC +extern uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc); +extern void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc); +#endif + +/* memory chunking */ +extern uint32_t chunksize_c(void); +extern uint8_t* chunkcopy_c(uint8_t *out, uint8_t const *from, unsigned len); +extern uint8_t* chunkcopy_safe_c(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); +extern uint8_t* chunkunroll_c(uint8_t *out, unsigned *dist, unsigned *len); +extern uint8_t* chunkmemset_c(uint8_t *out, unsigned dist, unsigned len); +extern uint8_t* chunkmemset_safe_c(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#ifdef X86_SSE2_CHUNKSET +extern uint32_t chunksize_sse2(void); +extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); +extern uint8_t* chunkcopy_safe_sse2(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); +extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); +extern uint8_t* chunkmemset_sse2(uint8_t *out, unsigned dist, unsigned len); +extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif +#ifdef X86_AVX_CHUNKSET +extern uint32_t chunksize_avx(void); +extern uint8_t* chunkcopy_avx(uint8_t *out, uint8_t const *from, unsigned len); +extern uint8_t* chunkcopy_safe_avx(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); +extern uint8_t* chunkunroll_avx(uint8_t *out, unsigned *dist, unsigned *len); +extern uint8_t* chunkmemset_avx(uint8_t *out, unsigned dist, unsigned len); +extern uint8_t* chunkmemset_safe_avx(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif +#ifdef ARM_NEON_CHUNKSET +extern uint32_t chunksize_neon(void); +extern uint8_t* chunkcopy_neon(uint8_t *out, uint8_t const *from, unsigned len); +extern uint8_t* chunkcopy_safe_neon(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); +extern uint8_t* chunkunroll_neon(uint8_t *out, unsigned *dist, unsigned *len); +extern uint8_t* chunkmemset_neon(uint8_t *out, unsigned dist, unsigned len); +extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif +#ifdef POWER8_VSX_CHUNKSET +extern uint32_t chunksize_power8(void); +extern uint8_t* chunkcopy_power8(uint8_t *out, uint8_t const *from, unsigned len); +extern uint8_t* chunkcopy_safe_power8(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); +extern uint8_t* chunkunroll_power8(uint8_t *out, unsigned *dist, unsigned *len); +extern uint8_t* chunkmemset_power8(uint8_t *out, unsigned dist, unsigned len); +extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif + +/* CRC32 */ +extern uint32_t crc32_byfour(uint32_t crc, const unsigned char *buf, uint64_t len); +#ifdef ARM_ACLE_CRC_HASH +extern uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len); +#elif defined(POWER8_VSX_CRC32) +extern uint32_t crc32_power8(uint32_t crc, const unsigned char *buf, uint64_t len); +#elif defined(S390_CRC32_VX) +extern uint32_t s390_crc32_vx(uint32_t crc, const unsigned char *buf, uint64_t len); +#endif + +/* compare256 */ +extern uint32_t compare256_c(const unsigned char *src0, const unsigned char *src1); +#ifdef UNALIGNED_OK +extern uint32_t compare256_unaligned_16(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_32(const unsigned char *src0, const unsigned char *src1); +#ifdef UNALIGNED64_OK +extern uint32_t compare256_unaligned_64(const unsigned char *src0, const unsigned char *src1); +#endif +#ifdef X86_SSE42_CMP_STR +extern uint32_t compare256_unaligned_sse4(const unsigned char *src0, const unsigned char *src1); +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t compare256_unaligned_avx2(const unsigned char *src0, const unsigned char *src1); +#endif +#endif + +/* longest_match */ +extern uint32_t longest_match_c(deflate_state *const s, Pos cur_match); +#ifdef UNALIGNED_OK +extern uint32_t longest_match_unaligned_16(deflate_state *const s, Pos cur_match); +extern uint32_t longest_match_unaligned_32(deflate_state *const s, Pos cur_match); +#ifdef UNALIGNED64_OK +extern uint32_t longest_match_unaligned_64(deflate_state *const s, Pos cur_match); +#endif +#ifdef X86_SSE42_CMP_STR +extern uint32_t longest_match_unaligned_sse4(deflate_state *const s, Pos cur_match); +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_unaligned_avx2(deflate_state *const s, Pos cur_match); +#endif +#endif + +/* longest_match_slow */ +extern uint32_t longest_match_slow_c(deflate_state *const s, Pos cur_match); +#ifdef UNALIGNED_OK +extern uint32_t longest_match_slow_unaligned_16(deflate_state *const s, Pos cur_match); +extern uint32_t longest_match_slow_unaligned_32(deflate_state *const s, Pos cur_match); +#ifdef UNALIGNED64_OK +extern uint32_t longest_match_slow_unaligned_64(deflate_state *const s, Pos cur_match); +#endif +#ifdef X86_SSE42_CMP_STR +extern uint32_t longest_match_slow_unaligned_sse4(deflate_state *const s, Pos cur_match); +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_slow_unaligned_avx2(deflate_state *const s, Pos cur_match); +#endif +#endif + +#endif diff --git a/functable.c b/functable.c index 3cfa13ade3..96fbc98315 100644 --- a/functable.c +++ b/functable.c @@ -11,206 +11,10 @@ #include "functable.h" -#ifdef X86_FEATURES -# include "fallback_builtins.h" -#endif - -/* update_hash */ -extern uint32_t update_hash_c(deflate_state *const s, uint32_t h, uint32_t val); -#ifdef X86_SSE42_CRC_HASH -extern uint32_t update_hash_sse4(deflate_state *const s, uint32_t h, uint32_t val); -#elif defined(ARM_ACLE_CRC_HASH) -extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); -#endif - -/* insert_string */ -extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); -#ifdef X86_SSE42_CRC_HASH -extern void insert_string_sse4(deflate_state *const s, const uint32_t str, uint32_t count); -#elif defined(ARM_ACLE_CRC_HASH) -extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint32_t count); -#endif - -/* quick_insert_string */ -extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); -#ifdef X86_SSE42_CRC_HASH -extern Pos quick_insert_string_sse4(deflate_state *const s, const uint32_t str); -#elif defined(ARM_ACLE_CRC_HASH) -extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); -#endif - -/* slide_hash */ -#ifdef X86_SSE2 -void slide_hash_sse2(deflate_state *s); -#elif defined(ARM_NEON_SLIDEHASH) -void slide_hash_neon(deflate_state *s); -#endif -#if defined(PPC_VMX_SLIDEHASH) -void slide_hash_vmx(deflate_state *s); -#endif -#if defined(POWER8_VSX_SLIDEHASH) -void slide_hash_power8(deflate_state *s); -#endif -#ifdef X86_AVX2 -void slide_hash_avx2(deflate_state *s); -#endif - -/* adler32 */ -extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len); -#ifdef ARM_NEON_ADLER32 -extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef PPC_VMX_ADLER32 -extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef X86_SSE41_ADLER32 -extern uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef X86_SSSE3_ADLER32 -extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef X86_AVX2_ADLER32 -extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef X86_AVX512_ADLER32 -extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef X86_AVX512VNNI_ADLER32 -extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len); -#endif -#ifdef POWER8_VSX_ADLER32 -extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len); -#endif - -/* CRC32 folding */ -extern uint32_t crc32_fold_reset_c(crc32_fold *crc); -extern void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); -extern uint32_t crc32_fold_final_c(crc32_fold *crc); - -#ifdef X86_PCLMULQDQ_CRC -extern uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc); -extern void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); -extern uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc); -#endif - -/* memory chunking */ -extern uint32_t chunksize_c(void); -extern uint8_t* chunkcopy_c(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_c(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_c(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_c(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_c(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#ifdef X86_SSE2_CHUNKSET -extern uint32_t chunksize_sse2(void); -extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_sse2(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_sse2(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#endif -#ifdef X86_AVX_CHUNKSET -extern uint32_t chunksize_avx(void); -extern uint8_t* chunkcopy_avx(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_avx(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_avx(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_avx(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_avx(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#endif -#ifdef ARM_NEON_CHUNKSET -extern uint32_t chunksize_neon(void); -extern uint8_t* chunkcopy_neon(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_neon(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_neon(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_neon(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_neon(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#endif -#ifdef POWER8_VSX_CHUNKSET -extern uint32_t chunksize_power8(void); -extern uint8_t* chunkcopy_power8(uint8_t *out, uint8_t const *from, unsigned len); -extern uint8_t* chunkcopy_safe_power8(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); -extern uint8_t* chunkunroll_power8(uint8_t *out, unsigned *dist, unsigned *len); -extern uint8_t* chunkmemset_power8(uint8_t *out, unsigned dist, unsigned len); -extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned len, unsigned left); -#endif - -/* CRC32 */ -Z_INTERNAL uint32_t crc32_generic(uint32_t, const unsigned char *, uint64_t); - -#ifdef ARM_ACLE_CRC_HASH -extern uint32_t crc32_acle(uint32_t, const unsigned char *, uint64_t); -#elif defined(POWER8_VSX_CRC32) -extern uint32_t crc32_power8(uint32_t, const unsigned char *, uint64_t); -#elif defined(S390_CRC32_VX) -extern uint32_t s390_crc32_vx(uint32_t, const unsigned char *, uint64_t); -#endif - -/* compare256 */ -extern uint32_t compare256_c(const unsigned char *src0, const unsigned char *src1); -#ifdef UNALIGNED_OK -extern uint32_t compare256_unaligned_16(const unsigned char *src0, const unsigned char *src1); -extern uint32_t compare256_unaligned_32(const unsigned char *src0, const unsigned char *src1); -#ifdef UNALIGNED64_OK -extern uint32_t compare256_unaligned_64(const unsigned char *src0, const unsigned char *src1); -#endif -#ifdef X86_SSE42_CMP_STR -extern uint32_t compare256_unaligned_sse4(const unsigned char *src0, const unsigned char *src1); -#endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t compare256_unaligned_avx2(const unsigned char *src0, const unsigned char *src1); -#endif -#endif - -/* longest_match */ -extern uint32_t longest_match_c(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED_OK -extern uint32_t longest_match_unaligned_16(deflate_state *const s, Pos cur_match); -extern uint32_t longest_match_unaligned_32(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED64_OK -extern uint32_t longest_match_unaligned_64(deflate_state *const s, Pos cur_match); -#endif -#ifdef X86_SSE42_CMP_STR -extern uint32_t longest_match_unaligned_sse4(deflate_state *const s, Pos cur_match); -#endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t longest_match_unaligned_avx2(deflate_state *const s, Pos cur_match); -#endif -#endif - -/* longest_match_slow */ -extern uint32_t longest_match_slow_c(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED_OK -extern uint32_t longest_match_slow_unaligned_16(deflate_state *const s, Pos cur_match); -extern uint32_t longest_match_slow_unaligned_32(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED64_OK -extern uint32_t longest_match_slow_unaligned_64(deflate_state *const s, Pos cur_match); -#endif -#ifdef X86_SSE42_CMP_STR -extern uint32_t longest_match_slow_unaligned_sse4(deflate_state *const s, Pos cur_match); -#endif -#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t longest_match_slow_unaligned_avx2(deflate_state *const s, Pos cur_match); -#endif -#endif +#include "cpu_features.h" Z_INTERNAL Z_TLS struct functable_s functable; -Z_INTERNAL void cpu_check_features(void) -{ - static int features_checked = 0; - if (features_checked) - return; -#if defined(X86_FEATURES) - x86_check_features(); -#elif defined(ARM_FEATURES) - arm_check_features(); -#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) - power_check_features(); -#elif defined(S390_FEATURES) - s390_check_features(); -#endif - features_checked = 1; -} - /* stub functions */ Z_INTERNAL uint32_t update_hash_stub(deflate_state *const s, uint32_t h, uint32_t val) { // Initialize default diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt new file mode 100644 index 0000000000..c3d8410234 --- /dev/null +++ b/test/benchmarks/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.12) + +include(CheckCCompilerFlag) +include(FeatureSummary) +include(FetchContent) + +enable_language(CXX) + +# Search for Google benchmark package +find_package(benchmark QUIET) +if(NOT benchmark_FOUND) + # Fetch google benchmark source code from official repository + set(BENCHMARK_ENABLE_TESTING OFF) + FetchContent_Declare(benchmark + GIT_REPOSITORY https://github.com/google/benchmark.git) + FetchContent_MakeAvailable(benchmark) + FetchContent_GetProperties(benchmark) + + if(NOT benchmark_POPULATED) + FetchContent_Populate(benchmark) + endif() +endif() + +add_executable(benchmark_zlib + benchmark_adler32.cc + benchmark_compare256.cc + benchmark_crc32.cc + benchmark_main.cc + benchmark_slidehash.cc + ) + +target_include_directories(benchmark_zlib PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${benchmark_SOURCE_DIR}/benchmark/include) + +target_link_libraries(benchmark_zlib zlibstatic benchmark::benchmark) +if(WIN32) + target_link_libraries(benchmark_zlib shlwapi) +endif() + +if(ZLIB_ENABLE_TESTS) + add_test(NAME benchmark_zlib + COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) +endif() diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md new file mode 100644 index 0000000000..b005027e07 --- /dev/null +++ b/test/benchmarks/README.md @@ -0,0 +1,19 @@ +## Benchmarks + +These benchmarks are written using [Google Benchmark](https://github.com/google/benchmark). + +*Repetitions* + +To increase the number of times each benchmark iteration is run use: + +``` +--benchmark_repetitions=20 +``` + +*Filters* + +To filter out which benchmarks are performed use: + +``` +--benchmark_filter="adler32*" +``` diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc new file mode 100644 index 0000000000..682908880a --- /dev/null +++ b/test/benchmarks/benchmark_adler32.cc @@ -0,0 +1,94 @@ +/* benchmark_adler32.cc -- benchmark adler32 variants + * Copyright (C) 2022 Nathan Moinvaziri, Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include +#include + +#include + +extern "C" { +# include "zbuild.h" +# include "zutil.h" +# include "zutil_p.h" +# include "cpu_features.h" +} + +#define MAX_RANDOM_INTS (1024 * 1024) +#define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t)) + +typedef uint32_t (*adler32_func)(uint32_t adler, const unsigned char *buf, size_t len); + +class adler32: public benchmark::Fixture { +private: + uint32_t *random_ints; + +public: + void SetUp(const ::benchmark::State& state) { + /* Control the alignment so that we have the best case scenario for loads. With + * AVX512, unaligned loads can mean we're crossing a cacheline boundary at every load. + * And while this is a realistic scenario, it makes it difficult to compare benchmark + * to benchmark because one allocation could have been aligned perfectly for the loads + * while the subsequent one happened to not be. This is not to be advantageous to AVX512 + * (indeed, all lesser SIMD implementations benefit from this aligned allocation), but to + * control the _consistency_ of the results */ + random_ints = (uint32_t *)zng_alloc(MAX_RANDOM_INTS_SIZE); + assert(random_ints != NULL); + + for (int32_t i = 0; i < MAX_RANDOM_INTS; i++) { + random_ints[i] = rand(); + } + } + + void Bench(benchmark::State& state, adler32_func adler32) { + uint32_t hash = 0; + + for (auto _ : state) { + hash = adler32(hash, (const unsigned char *)random_ints, state.range(0)); + } + + benchmark::DoNotOptimize(hash); + } + + void TearDown(const ::benchmark::State& state) { + zng_free(random_ints); + } +}; + +#define BENCHMARK_ADLER32(name, fptr, support_flag) \ + BENCHMARK_DEFINE_F(adler32, name)(benchmark::State& state) { \ + if (!support_flag) { \ + state.SkipWithError("CPU does not support " #name); \ + } \ + Bench(state, fptr); \ + } \ + BENCHMARK_REGISTER_F(adler32, name)->Range(2048, MAX_RANDOM_INTS_SIZE); + +BENCHMARK_ADLER32(c, adler32_c, 1); + +#ifdef ARM_NEON_ADLER32 +BENCHMARK_ADLER32(neon, adler32_neon, arm_has_neon); +#elif defined(POWER8_VSX_ADLER32) +BENCHMARK_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07); +#elif defined(PPC_VMX_ADLER32) +BENCHMARK_ADLER32(vmx, adler32_vmx, power_cpu_has_altivec); +#endif + +#ifdef X86_SSSE3_ADLER32 +BENCHMARK_ADLER32(ssse3, adler32_ssse3, x86_cpu_has_ssse3); +#endif +#ifdef X86_SSE41_ADLER32 +BENCHMARK_ADLER32(sse41, adler32_sse41, x86_cpu_has_sse41); +#endif +#ifdef X86_AVX2_ADLER32 +BENCHMARK_ADLER32(avx2, adler32_avx2, x86_cpu_has_avx2); +#endif +#ifdef X86_AVX512_ADLER32 +BENCHMARK_ADLER32(avx512, adler32_avx512, x86_cpu_has_avx512); +#endif +#ifdef X86_AVX512VNNI_ADLER32 +BENCHMARK_ADLER32(avx512_vnni, adler32_avx512_vnni, x86_cpu_has_avx512vnni); +#endif diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc new file mode 100644 index 0000000000..063d110fa0 --- /dev/null +++ b/test/benchmarks/benchmark_compare256.cc @@ -0,0 +1,84 @@ +/* benchmark_compare256.cc -- benchmark compare256 variants + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include + +#include + +extern "C" { +# include "zbuild.h" +# include "zutil.h" +# include "zutil_p.h" +# include "cpu_features.h" +} + +#define MAX_COMPARE_SIZE (256) + +typedef uint32_t (*compare256_func)(const unsigned char *src0, const unsigned char *src1); + +class compare256: public benchmark::Fixture { +private: + uint8_t *str1; + uint8_t *str2; + +public: + void SetUp(const ::benchmark::State& state) { + str1 = (uint8_t *)zng_alloc(MAX_COMPARE_SIZE); + assert(str1 != NULL); + memset(str1, 'a', MAX_COMPARE_SIZE); + + str2 = (uint8_t *)zng_alloc(MAX_COMPARE_SIZE); + assert(str2 != NULL); + memset(str2, 'a', MAX_COMPARE_SIZE); + } + + void Bench(benchmark::State& state, compare256_func compare256) { + int32_t match_len = (int32_t)state.range(0); + uint32_t len; + + str2[match_len] = 0; + for (auto _ : state) { + len = compare256((const uint8_t *)str1, (const uint8_t *)str2); + } + str2[match_len] = 'a'; + + benchmark::DoNotOptimize(len); + } + + void TearDown(const ::benchmark::State& state) { + zng_free(str1); + zng_free(str2); + } +}; + +#define BENCHMARK_COMPARE256(name, fptr, support_flag) \ + BENCHMARK_DEFINE_F(compare256, name)(benchmark::State& state) { \ + if (!support_flag) { \ + state.SkipWithError("CPU does not support " #name); \ + } \ + Bench(state, fptr); \ + } \ + BENCHMARK_REGISTER_F(compare256, name)->Range(1, MAX_COMPARE_SIZE); + +BENCHMARK_COMPARE256(c, compare256_c, 1); + +#ifdef UNALIGNED_OK +BENCHMARK_COMPARE256(unaligned_16, compare256_unaligned_16, 1); +#ifdef HAVE_BUILTIN_CTZ +BENCHMARK_COMPARE256(unaligned_32, compare256_unaligned_32, 1); +#endif +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +BENCHMARK_COMPARE256(unaligned_64, compare256_unaligned_64, 1); +#endif +#endif + +#ifdef X86_SSE42_CMP_STR +BENCHMARK_COMPARE256(unaligned_sse4, compare256_unaligned_sse4, x86_cpu_has_sse42); +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +BENCHMARK_COMPARE256(unaligned_avx2, compare256_unaligned_avx2, x86_cpu_has_avx2); +#endif diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc new file mode 100644 index 0000000000..69d11a4d19 --- /dev/null +++ b/test/benchmarks/benchmark_crc32.cc @@ -0,0 +1,80 @@ +/* benchmark_crc32.cc -- benchmark crc32 variants + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include +#include + +#include + +extern "C" { +# include "zbuild.h" +# include "zutil.h" +# include "zutil_p.h" +# include "cpu_features.h" +} + +#define MAX_RANDOM_INTS (1024 * 1024) +#define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t)) + +typedef uint32_t (*crc32_func)(uint32_t crc32, const unsigned char * buf, uint64_t len); + +class crc32: public benchmark::Fixture { +private: + uint32_t *random_ints; + +public: + void SetUp(const ::benchmark::State& state) { + random_ints = (uint32_t *)zng_alloc(MAX_RANDOM_INTS_SIZE); + assert(random_ints != NULL); + + for (int32_t i = 0; i < MAX_RANDOM_INTS; i++) { + random_ints[i] = rand(); + } + } + + void Bench(benchmark::State& state, crc32_func crc32) { + uint32_t hash = 0; + + for (auto _ : state) { + hash = crc32(hash, (const unsigned char *)random_ints, state.range(0)); + } + + benchmark::DoNotOptimize(hash); + } + + void TearDown(const ::benchmark::State& state) { + zng_free(random_ints); + } +}; + +#define BENCHMARK_CRC32(name, fptr, support_flag) \ + BENCHMARK_DEFINE_F(crc32, name)(benchmark::State& state) { \ + if (!support_flag) { \ + state.SkipWithError("CPU does not support " #name); \ + } \ + Bench(state, fptr); \ + } \ + BENCHMARK_REGISTER_F(crc32, name)->Range(1, MAX_RANDOM_INTS_SIZE); + +BENCHMARK_CRC32(byfour, crc32_byfour, 1); + +#ifdef ARM_ACLE_CRC_HASH +BENCHMARK_CRC32(acle, crc32_acle, arm_cpu_has_crc32); +#elif defined(POWER8_VSX_CRC32) +BENCHMARK_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07); +#elif defined(S390_CRC32_VX) +BENCHMARK_CRC32(vx, s390_crc32_vx, s390_cpu_has_vx); +#elif defined(X86_PCLMULQDQ_CRC) +/* CRC32 fold does a memory copy while hashing */ +uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len) { + crc32_fold ALIGNED_(16) crc_state; + crc32_fold_reset_pclmulqdq(&crc_state); + crc32_fold_copy_pclmulqdq(&crc_state, (uint8_t *)buf, buf, len); + return crc32_fold_final_pclmulqdq(&crc_state); +} +BENCHMARK_CRC32(pclmulqdq, crc32_pclmulqdq, x86_cpu_has_pclmulqdq); +#endif \ No newline at end of file diff --git a/test/benchmarks/benchmark_main.cc b/test/benchmarks/benchmark_main.cc new file mode 100644 index 0000000000..81582c353a --- /dev/null +++ b/test/benchmarks/benchmark_main.cc @@ -0,0 +1,25 @@ +/* benchmark_main.cc -- benchmark suite main entry point + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include + +#include + +extern "C" { +# include "zbuild.h" +# include "zutil.h" +# include "cpu_features.h" +} + +int main(int argc, char** argv) { + cpu_check_features(); + + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + + return EXIT_SUCCESS; +} diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc new file mode 100644 index 0000000000..174ea09316 --- /dev/null +++ b/test/benchmarks/benchmark_slidehash.cc @@ -0,0 +1,91 @@ +/* benchmark_slidehash.cc -- benchmark slide_hash variants + * Copyright (C) 2022 Adam Stylinski, Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include + +extern "C" { +# include "zbuild.h" +# include "zutil.h" +# include "zutil_p.h" +# include "cpu_features.h" +# include "deflate.h" +} + +#include + +#define MAX_RANDOM_INTS 32768 + +typedef void (*slide_hash_func)(deflate_state *s); + +class slide_hash: public benchmark::Fixture { +private: + uint16_t *l0; + uint16_t *l1; + deflate_state *s_g; + +public: + void SetUp(const ::benchmark::State& state) { + l0 = (uint16_t *)zng_alloc(HASH_SIZE * sizeof(uint16_t)); + + for (int32_t i = 0; i < HASH_SIZE; i++) { + l0[i] = rand(); + } + + l1 = (uint16_t *)zng_alloc(MAX_RANDOM_INTS * sizeof(uint16_t)); + + for (int32_t i = 0; i < MAX_RANDOM_INTS; i++) { + l1[i] = rand(); + } + + deflate_state *s = (deflate_state*)malloc(sizeof(deflate_state)); + s->head = l0; + s->prev = l1; + s_g = s; + } + + void Bench(benchmark::State& state, slide_hash_func slide_hash) { + s_g->w_size = (uint32_t)state.range(0); + + for (auto _ : state) { + slide_hash(s_g); + benchmark::DoNotOptimize(s_g); + } + } + + void TearDown(const ::benchmark::State& state) { + zng_free(l0); + zng_free(l1); + } +}; + +#define BENCHMARK_SLIDEHASH(name, fptr, support_flag) \ + BENCHMARK_DEFINE_F(slide_hash, name)(benchmark::State& state) { \ + if (!support_flag) { \ + state.SkipWithError("CPU does not support " #name); \ + } \ + Bench(state, fptr); \ + } \ + BENCHMARK_REGISTER_F(slide_hash, name)->RangeMultiplier(2)->Range(1024, MAX_RANDOM_INTS); + +BENCHMARK_SLIDEHASH(c, slide_hash_c, 1); + +#ifdef ARM_NEON_SLIDEHASH +BENCHMARK_SLIDEHASH(neon, slide_hash_neon, arm_cpu_has_neon); +#endif +#ifdef POWER8_VSX_SLIDEHASH +BENCHMARK_SLIDEHASH(power8, slide_hash_power8, power_cpu_has_arch_2_07); +#endif +#ifdef PPC_VMX_SLIDEHASH +BENCHMARK_SLIDEHASH(vmx, slide_hash_vmx, power_cpu_has_altivec); +#endif + +#ifdef X86_SSE2 +BENCHMARK_SLIDEHASH(sse2, slide_hash_sse2, x86_cpu_has_sse2); +#endif +#ifdef X86_AVX2 +BENCHMARK_SLIDEHASH(avx2, slide_hash_avx2, x86_cpu_has_avx2); +#endif diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 82ca6c2dc1..e651233609 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -48,6 +48,7 @@ OBJS = \ chunkset.obj \ compare256.obj \ compress.obj \ + cpu_features.obj \ crc32.obj \ crc32_comb.obj \ crc32_fold.obj \ @@ -185,6 +186,7 @@ gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/z gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h +cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index ace50794e2..29ce955811 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -51,6 +51,7 @@ OBJS = \ chunkset.obj \ compare256.obj \ compress.obj \ + cpu_features.obj \ crc32.obj \ crc32_comb.obj \ crc32_fold.obj \ @@ -197,6 +198,7 @@ gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR) compress.obj: $(SRCDIR)/compress.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h +cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h diff --git a/win32/Makefile.msc b/win32/Makefile.msc index cfdfcca749..0059606c5a 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -57,6 +57,7 @@ OBJS = \ compare256_avx2.obj \ compare256_sse42.obj \ compress.obj \ + cpu_features.obj \ crc32.obj \ crc32_comb.obj \ crc32_fold.obj \ @@ -191,6 +192,7 @@ uncompr.obj: $(SRCDIR)/uncompr.c $(SRCDIR)/zbuild.h $(SRCDIR)/zlib$(SUFFIX).h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_avx.obj: $(SRCDIR)/arch/x86/chunkset_avx.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h chunkset_sse2.obj: $(SRCDIR)/arch/x86/chunkset_sse2.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h +cpu_features.obj: $(SRCDIR)/cpu_features.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h crc32.obj: $(SRCDIR)/crc32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zendian.h $(SRCDIR)/deflate.h $(SRCDIR)/functable.h $(SRCDIR)/crc32_tbl.h crc32_comb.obj: $(SRCDIR)/crc32_comb.c $(SRCDIR)/zbuild.h $(SRCDIR)/deflate.h $(SRCDIR)/crc32_comb_tbl.h crc32_fold.obj: $(SRCDIR)/crc32_fold.c $(SRCDIR)/zbuild.h From 91bc814e39e6b012b3ca4ae6ae62ed11ad0795ae Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 2 Jan 2022 15:27:00 -0800 Subject: [PATCH 207/798] Clean up crc32_fold structure and clearly define the size of the fold buffer. --- arch/x86/crc32_fold_pclmulqdq.c | 10 +++++----- crc32_fold.h | 5 ++++- deflate.h | 2 +- inflate.h | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 1434357a87..a01cdf775c 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -244,7 +244,7 @@ static inline void crc32_fold_save_partial(__m128i *fold, __m128i foldp) { Z_INTERNAL uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc) { __m128i xmm_crc0 = _mm_cvtsi32_si128(0x9db42487); __m128i xmm_zero = _mm_setzero_si128(); - crc32_fold_save((__m128i *)&crc->fold, xmm_crc0, xmm_zero, xmm_zero, xmm_zero); + crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_zero, xmm_zero, xmm_zero); return 0; } @@ -254,7 +254,7 @@ Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const u __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3, xmm_crc_part; char ALIGNED_(16) partial_buf[16] = { 0 }; - crc32_fold_load((__m128i *)&crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); if (len < 16) { if (len == 0) @@ -375,8 +375,8 @@ Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const u partial: partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); done: - crc32_fold_save((__m128i *)&crc->fold, xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3); - crc32_fold_save_partial((__m128i *)&crc->fold, xmm_crc_part); + crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3); + crc32_fold_save_partial((__m128i *)crc->fold, xmm_crc_part); } static const unsigned ALIGNED_(16) crc_k[] = { @@ -402,7 +402,7 @@ Z_INTERNAL uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc) { __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3; __m128i x_tmp0, x_tmp1, x_tmp2, crc_fold; - crc32_fold_load((__m128i *)&crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); /* * k1 diff --git a/crc32_fold.h b/crc32_fold.h index ec6d13d157..8bd0b6bc2a 100644 --- a/crc32_fold.h +++ b/crc32_fold.h @@ -5,8 +5,11 @@ #ifndef CRC32_FOLD_H_ #define CRC32_FOLD_H_ +#define CRC32_FOLD_BUFFER_SIZE (16 * 5) +/* sizeof(__m128i) * (4 folds & 1 partial fold) */ + typedef struct crc32_fold_s { - uint32_t ALIGNED_(16) fold[4 * 5]; + uint8_t fold[CRC32_FOLD_BUFFER_SIZE]; uint32_t value; } crc32_fold; diff --git a/deflate.h b/deflate.h index 030db4f098..7f4eb43f9f 100644 --- a/deflate.h +++ b/deflate.h @@ -211,7 +211,7 @@ struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ - crc32_fold ALIGNED_(16) crc_fold; + struct crc32_fold_s ALIGNED_(16) crc_fold; /* used by trees.c: */ /* Didn't use ct_data typedef below to suppress compiler warning */ diff --git a/inflate.h b/inflate.h index d33ea2a708..3f57e78408 100644 --- a/inflate.h +++ b/inflate.h @@ -103,7 +103,7 @@ struct inflate_state { uint32_t wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if needed */ - crc32_fold ALIGNED_(16) crc_fold; + struct crc32_fold_s ALIGNED_(16) crc_fold; /* bit accumulator */ uint32_t hold; /* input bit accumulator */ From 869104562df27f0c0b2cd39c1bbd947ab4bd2960 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 15 Jan 2022 13:30:08 -0800 Subject: [PATCH 208/798] Clean up and remove bestcmp_t type for longest_match. Use 8 byte buffer (max int comparison size) and cast to integer type when making comparison. --- match_tpl.h | 55 ++++++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/match_tpl.h b/match_tpl.h index 75181bf851..94e796b55e 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -15,16 +15,6 @@ #ifndef MATCH_TPL_H #define MATCH_TPL_H -#ifdef UNALIGNED_OK -# ifdef UNALIGNED64_OK -typedef uint64_t bestcmp_t; -# else -typedef uint32_t bestcmp_t; -# endif -#else -typedef uint8_t bestcmp_t; -#endif - #define EARLY_EXIT_TRIGGER_LEVEL 5 #endif @@ -54,12 +44,7 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { uint32_t chain_length, nice_match, best_len, offset; uint32_t lookahead = s->lookahead; Pos match_offset = 0; - bestcmp_t scan_end; -#ifndef UNALIGNED_OK - bestcmp_t scan_end0; -#else - bestcmp_t scan_start; -#endif + uint8_t scan_start[8], scan_end[8]; #define GOTO_NEXT_CHAIN \ if (--chain_length && (cur_match = prev[cur_match & wmask]) > limit) \ @@ -85,11 +70,15 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { } #endif - memcpy(&scan_end, scan+offset, sizeof(bestcmp_t)); -#ifndef UNALIGNED_OK - memcpy(&scan_end0, scan+offset+1, sizeof(bestcmp_t)); +#ifdef UNALIGNED64_OK + memcpy(scan_start, scan, sizeof(uint64_t)); + memcpy(scan_end, scan+offset, sizeof(uint64_t)); +#elif defined(UNALIGNED_OK) + memcpy(scan_start, scan, sizeof(uint32_t)); + memcpy(scan_end, scan+offset, sizeof(uint32_t)); #else - memcpy(&scan_start, scan, sizeof(bestcmp_t)); + scan_end[0] = *(scan+offset); + scan_end[1] = *(scan+offset+1); #endif mbase_end = (mbase_start+offset); @@ -153,31 +142,31 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #ifdef UNALIGNED_OK if (best_len < sizeof(uint32_t)) { for (;;) { - if (*(uint16_t *)(mbase_end+cur_match) == (uint16_t)scan_end && - *(uint16_t *)(mbase_start+cur_match) == (uint16_t)scan_start) + if (*(uint16_t *)(mbase_end+cur_match) == *(uint16_t *)scan_end && + *(uint16_t *)(mbase_start+cur_match) == *(uint16_t *)scan_start) break; GOTO_NEXT_CHAIN; } # ifdef UNALIGNED64_OK } else if (best_len >= sizeof(uint64_t)) { for (;;) { - if (*(uint64_t *)(mbase_end+cur_match) == (uint64_t)scan_end && - *(uint64_t *)(mbase_start+cur_match) == (uint64_t)scan_start) + if (*(uint64_t *)(mbase_end+cur_match) == *(uint64_t *)scan_end && + *(uint64_t *)(mbase_start+cur_match) == *(uint64_t *)scan_start) break; GOTO_NEXT_CHAIN; } # endif } else { for (;;) { - if (*(uint32_t *)(mbase_end+cur_match) == (uint32_t)scan_end && - *(uint32_t *)(mbase_start+cur_match) == (uint32_t)scan_start) + if (*(uint32_t *)(mbase_end+cur_match) == *(uint32_t *)scan_end && + *(uint32_t *)(mbase_start+cur_match) == *(uint32_t *)scan_start) break; GOTO_NEXT_CHAIN; } } #else for (;;) { - if (mbase_end[cur_match] == scan_end && mbase_end[cur_match+1] == scan_end0 && + if (mbase_end[cur_match] == scan_end[0] && mbase_end[cur_match+1] == scan_end[1] && mbase_start[cur_match] == scan[0] && mbase_start[cur_match+1] == scan[1]) break; GOTO_NEXT_CHAIN; @@ -207,10 +196,16 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif } #endif - memcpy(&scan_end, scan+offset, sizeof(bestcmp_t)); -#ifndef UNALIGNED_OK - memcpy(&scan_end0, scan+offset+1, sizeof(bestcmp_t)); + +#ifdef UNALIGNED64_OK + memcpy(scan_end, scan+offset, sizeof(uint64_t)); +#elif defined(UNALIGNED_OK) + memcpy(scan_end, scan+offset, sizeof(uint32_t)); +#else + scan_end[0] = *(scan+offset); + scan_end[1] = *(scan+offset+1); #endif + #ifdef LONGEST_MATCH_SLOW /* Look for a better string offset */ if (UNLIKELY(len > STD_MIN_MATCH && match_start + len < strstart)) { From e820a76cc9155343058496cacf4a2bcf871cb190 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 14 Jan 2022 12:15:50 -0800 Subject: [PATCH 209/798] Merge feature list entries for crc32. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 5b4834d7b0..40cf9b27b0 100644 --- a/README.md +++ b/README.md @@ -22,12 +22,11 @@ Features * Deflate medium and quick algorithms based on Intels zlib fork * Support for CPU intrinsics when available * Adler32 implementation using SSSE3, AVX2, AVX512, AVX512-VNNI, Neon, VMX & VSX - * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, & ACLE + * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, ACLE, & IBM Z * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX * Compare256 implementations using SSE4.2 & AVX2 * Inflate chunk copying using SSE2, AVX2, Neon & VSX - * CRC32 implementation using IBM Z vector instructions * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements * Includes improvements from Cloudflare and Intel forks From 30c89988e2399e8da18adedb4ba666e08f078db8 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 14 Jan 2022 12:19:11 -0800 Subject: [PATCH 210/798] Fixed incorrect version of AVX specified for inflate chunk copying in feature list. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 40cf9b27b0..d70ac82729 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Features * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX * Compare256 implementations using SSE4.2 & AVX2 - * Inflate chunk copying using SSE2, AVX2, Neon & VSX + * Inflate chunk copying using SSE2, AVX, Neon & VSX * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements * Includes improvements from Cloudflare and Intel forks From c4e890a1e313a0d7e1bda4cc3405c1fabe2b11e9 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 17 Jan 2022 16:30:10 -0800 Subject: [PATCH 211/798] Rename test binaries with test_ prefix. --- .gitignore | 8 +-- CMakeLists.txt | 25 +++++---- Makefile.in | 52 +++++++++---------- test/Makefile.in | 4 +- test/{adler32_test.c => test_adler32.c} | 2 +- test/{crc32_test.c => test_crc32.c} | 2 +- ..._valid.c => test_deflate_quick_bi_valid.c} | 0 ...open.c => test_deflate_quick_block_open.c} | 0 test/{hash_head_0.c => test_hash_head_0.c} | 0 ...flate_adler32.c => test_inflate_adler32.c} | 0 10 files changed, 48 insertions(+), 45 deletions(-) rename test/{adler32_test.c => test_adler32.c} (99%) rename test/{crc32_test.c => test_crc32.c} (99%) rename test/{deflate_quick_bi_valid.c => test_deflate_quick_bi_valid.c} (100%) rename test/{deflate_quick_block_open.c => test_deflate_quick_block_open.c} (100%) rename test/{hash_head_0.c => test_hash_head_0.c} (100%) rename test/{inflate_adler32.c => test_inflate_adler32.c} (100%) diff --git a/.gitignore b/.gitignore index bf420e572c..532aed578a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,10 +13,10 @@ *.gcno *.gcov -/adler32_test -/adler32_testsh -/crc32_test -/crc32_testsh +/test_adler32 +/test_adler32sh +/test_crc32 +/test_crc32sh /example /example64 /examplesh diff --git a/CMakeLists.txt b/CMakeLists.txt index 5391fd5c59..454159bb74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1188,8 +1188,20 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME ${target} COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) endmacro() - add_simple_test_executable(adler32_test) - add_simple_test_executable(crc32_test) + file(GLOB TEST_SRCS + LIST_DIRECTORIES false + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/test + ${CMAKE_CURRENT_SOURCE_DIR}/test/test_*.c) + + foreach(TEST_SRC ${TEST_SRCS}) + get_filename_component(TEST_NAME ${TEST_SRC} NAME_WE) + add_simple_test_executable(${TEST_NAME}) + endforeach() + + if(NOT WIN32 AND ZLIB_COMPAT) + add_simple_test_executable(CVE-2003-0107) + endif() + add_simple_test_executable(example) set(MINIGZIP_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) @@ -1370,10 +1382,6 @@ if(ZLIB_ENABLE_TESTS) # Run tests targeting tools include(cmake/test-tools.cmake) - if(NOT WIN32 AND ZLIB_COMPAT) - add_simple_test_executable(CVE-2003-0107) - endif() - add_test(NAME GH-361 COMMAND ${CMAKE_COMMAND} "-DTARGET=${MINIGZIP_COMMAND}" @@ -1440,11 +1448,6 @@ if(ZLIB_ENABLE_TESTS) -DTEST_NAME=GH-751-test-txt -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/GH-751/test.txt -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_simple_test_executable(deflate_quick_bi_valid) - add_simple_test_executable(deflate_quick_block_open) - add_simple_test_executable(inflate_adler32) - add_simple_test_executable(hash_head_0) endif() add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile related functions") diff --git a/Makefile.in b/Makefile.in index ca2b1127f7..5d86f7867b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -154,9 +154,9 @@ PIC_OBJS = $(PIC_OBJC) all: static shared -static: adler32_test$(EXE) crc32_test$(EXE) example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) +static: test_adler32$(EXE) test_crc32$(EXE) example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) -shared: adler32_testsh$(EXE) crc32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) +shared: test_adler32sh$(EXE) test_crc32sh$(EXE) examplesh$(EXE) minigzipsh$(EXE) check: test @@ -248,12 +248,6 @@ $(STATICLIB): $(OBJS) $(AR) $(ARFLAGS) $@ $(OBJS) -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 -adler32_test.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/adler32_test.c - -crc32_test.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/crc32_test.c - example.o: $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $(SRCDIR)/test/example.c @@ -269,6 +263,12 @@ maketrees.o: makecrct.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/tools/makecrct.c +test_adler32.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/test_adler32.c + +test_crc32.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/test_crc32.c + zlibrc.o: win32/zlib$(SUFFIX)1.rc $(RC) $(RCFLAGS) -o $@ win32/zlib$(SUFFIX)1.rc @@ -311,18 +311,6 @@ ifneq ($(SHAREDLIB),$(SHAREDTARGET)) endif endif -adler32_test$(EXE): adler32_test.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ adler32_test.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -crc32_test$(EXE): crc32_test.o $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ crc32_test.o $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - example$(EXE): example.o $(OBJG) $(STATICLIB) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) @@ -335,14 +323,14 @@ ifneq ($(STRIP),) $(STRIP) $@ endif -adler32_testsh$(EXE): adler32_test.o $(PIC_TESTOBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ adler32_test.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) +test_adler32$(EXE): test_adler32.o $(OBJG) $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test_adler32.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -crc32_testsh$(EXE): crc32_test.o $(SHAREDTARGET) - $(CC) $(LDFLAGS) -o $@ crc32_test.o $(SHAREDTARGET) $(LDSHAREDLIBC) +test_crc32$(EXE): test_crc32.o $(STATICLIB) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test_crc32.o $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif @@ -359,6 +347,18 @@ ifneq ($(STRIP),) $(STRIP) $@ endif +test_adler32sh$(EXE): test_adler32.o $(PIC_TESTOBJG) $(SHAREDTARGET) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test_adler32.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) +ifneq ($(STRIP),) + $(STRIP) $@ +endif + +test_crc32sh$(EXE): test_crc32.o $(SHAREDTARGET) + $(CC) $(LDFLAGS) -o $@ test_crc32.o $(SHAREDTARGET) $(LDSHAREDLIBC) +ifneq ($(STRIP),) + $(STRIP) $@ +endif + makefixed$(EXE): makefixed.o $(OBJG) $(STATICLIB) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makefixed.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) @@ -439,8 +439,8 @@ clean: @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) clean; fi @if [ -f test/Makefile ]; then $(MAKE) -C test clean; fi rm -f *.o *.lo *~ \ - adler32_test$(EXE) crc32_test$(EXE) example$(EXE) minigzip$(EXE) \ - adler32_testsh$(EXE) crc32_testsh$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ + test_adler32$(EXE) test_crc32$(EXE) example$(EXE) minigzip$(EXE) \ + test_adler32sh$(EXE) test_crc32sh$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ fuzzer_checksum$(EXE) fuzzer_compress$(EXE) fuzzer_example_small$(EXE) fuzzer_example_large$(EXE) \ fuzzer_example_flush$(EXE) fuzzer_example_dict$(EXE) fuzzer_minigzip$(EXE) \ infcover makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) \ diff --git a/test/Makefile.in b/test/Makefile.in index ce6d06a35b..f743fa84a7 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -48,7 +48,7 @@ endif teststatic: check_cross_dep @TMPST=tmpst_$$$$; \ HELLOST=tmphellost_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${QEMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${QEMU_RUN} ../example$(EXE) $$TMPST && ${QEMU_RUN} ../adler32_test$(EXE) && ${QEMU_RUN} ../crc32_test$(EXE); then \ + if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${QEMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${QEMU_RUN} ../example$(EXE) $$TMPST && ${QEMU_RUN} ../test_adler32$(EXE) && ${QEMU_RUN} ../test_crc32$(EXE); then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; exit 1; \ @@ -62,7 +62,7 @@ testshared: check_cross_dep SHLIB_PATH=`pwd`/..:$(SHLIB_PATH) ; export SHLIB_PATH; \ TMPSH=tmpsh_$$$$; \ HELLOSH=tmphellosh_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${QEMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH && ${QEMU_RUN} ../adler32_testsh$(EXE) && ${QEMU_RUN} ../crc32_testsh$(EXE); then \ + if echo hello world | ${QEMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${QEMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH && ${QEMU_RUN} ../test_adler32sh$(EXE) && ${QEMU_RUN} ../test_crc32sh$(EXE); then \ echo ' *** zlib shared test OK ***'; \ else \ echo ' *** zlib shared test FAILED ***'; exit 1; \ diff --git a/test/adler32_test.c b/test/test_adler32.c similarity index 99% rename from test/adler32_test.c rename to test/test_adler32.c index f681877d31..38f890956f 100644 --- a/test/adler32_test.c +++ b/test/test_adler32.c @@ -1,4 +1,4 @@ -/* adler32_test.c -- unit test for adler32 in the zlib compression library +/* test_adler32.c -- unit test for adler32 in the zlib compression library * Copyright (C) 2020 IBM Corporation * Author: Rogerio Alves * For conditions of distribution and use, see copyright notice in zlib.h diff --git a/test/crc32_test.c b/test/test_crc32.c similarity index 99% rename from test/crc32_test.c rename to test/test_crc32.c index c625b501a1..6d112c4a66 100644 --- a/test/crc32_test.c +++ b/test/test_crc32.c @@ -1,4 +1,4 @@ -/* crc32_test.c -- crc32 unit test +/* test_crc32.c -- crc32 unit test * Copyright (C) 2019-2021 IBM Corporation * Authors: Rogerio Alves * Matheus Castanho diff --git a/test/deflate_quick_bi_valid.c b/test/test_deflate_quick_bi_valid.c similarity index 100% rename from test/deflate_quick_bi_valid.c rename to test/test_deflate_quick_bi_valid.c diff --git a/test/deflate_quick_block_open.c b/test/test_deflate_quick_block_open.c similarity index 100% rename from test/deflate_quick_block_open.c rename to test/test_deflate_quick_block_open.c diff --git a/test/hash_head_0.c b/test/test_hash_head_0.c similarity index 100% rename from test/hash_head_0.c rename to test/test_hash_head_0.c diff --git a/test/inflate_adler32.c b/test/test_inflate_adler32.c similarity index 100% rename from test/inflate_adler32.c rename to test/test_inflate_adler32.c From a206e147b754d0dfc2632ad706a2c6e09ec9b095 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 17 Jan 2022 16:32:02 -0800 Subject: [PATCH 212/798] Remove crc32 and adler32 shared library tests which don't test anyting further than what is provided by crc32 static build or examplesh. --- .gitignore | 2 -- Makefile.in | 16 ++-------------- test/Makefile.in | 2 +- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 532aed578a..ff0a590957 100644 --- a/.gitignore +++ b/.gitignore @@ -14,9 +14,7 @@ *.gcov /test_adler32 -/test_adler32sh /test_crc32 -/test_crc32sh /example /example64 /examplesh diff --git a/Makefile.in b/Makefile.in index 5d86f7867b..e7ad5a6506 100644 --- a/Makefile.in +++ b/Makefile.in @@ -156,7 +156,7 @@ all: static shared static: test_adler32$(EXE) test_crc32$(EXE) example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) -shared: test_adler32sh$(EXE) test_crc32sh$(EXE) examplesh$(EXE) minigzipsh$(EXE) +shared: examplesh$(EXE) minigzipsh$(EXE) check: test @@ -347,18 +347,6 @@ ifneq ($(STRIP),) $(STRIP) $@ endif -test_adler32sh$(EXE): test_adler32.o $(PIC_TESTOBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test_adler32.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - -test_crc32sh$(EXE): test_crc32.o $(SHAREDTARGET) - $(CC) $(LDFLAGS) -o $@ test_crc32.o $(SHAREDTARGET) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - makefixed$(EXE): makefixed.o $(OBJG) $(STATICLIB) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makefixed.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) @@ -440,7 +428,7 @@ clean: @if [ -f test/Makefile ]; then $(MAKE) -C test clean; fi rm -f *.o *.lo *~ \ test_adler32$(EXE) test_crc32$(EXE) example$(EXE) minigzip$(EXE) \ - test_adler32sh$(EXE) test_crc32sh$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ + examplesh$(EXE) minigzipsh$(EXE) \ fuzzer_checksum$(EXE) fuzzer_compress$(EXE) fuzzer_example_small$(EXE) fuzzer_example_large$(EXE) \ fuzzer_example_flush$(EXE) fuzzer_example_dict$(EXE) fuzzer_minigzip$(EXE) \ infcover makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) \ diff --git a/test/Makefile.in b/test/Makefile.in index f743fa84a7..a32d0adf8d 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -62,7 +62,7 @@ testshared: check_cross_dep SHLIB_PATH=`pwd`/..:$(SHLIB_PATH) ; export SHLIB_PATH; \ TMPSH=tmpsh_$$$$; \ HELLOSH=tmphellosh_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${QEMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH && ${QEMU_RUN} ../test_adler32sh$(EXE) && ${QEMU_RUN} ../test_crc32sh$(EXE); then \ + if echo hello world | ${QEMU_RUN} ../minigzipsh$(EXE) > $$HELLOSH && ${QEMU_RUN} ../minigzipsh$(EXE) -d < $$HELLOSH && ${QEMU_RUN} ../examplesh$(EXE) $$TMPSH; then \ echo ' *** zlib shared test OK ***'; \ else \ echo ' *** zlib shared test FAILED ***'; exit 1; \ From 29e9e398ccb8162e80334440488456656162d5a0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 17 Jan 2022 16:17:00 -0800 Subject: [PATCH 213/798] Fixed AVX512-VNNI detection when compiling with ClangCl. --- cmake/detect-intrinsics.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 47d93d0c15..515135ebfc 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -65,14 +65,14 @@ macro(check_avx512vnni_intrinsics) if(CMAKE_HOST_UNIX OR APPLE) set(AVX512VNNIFLAG "-mavx512f -mavx512bw -mavx512dq -mavx512vl -mavx512vnni") else() - set(AVX512FLAG "/ARCH:AVX512") + set(AVX512VNNIFLAG "/ARCH:AVX512") endif() - elseif(MSVC) - set(AVX512FLAG "/ARCH:AVX512") elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) set(AVX512VNNIFLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx512vnni -mtune=cascadelake") endif() + elseif(MSVC) + set(AVX512VNNIFLAG "/ARCH:AVX512") endif() # Check whether compiler supports AVX512vnni intrinsics From 8437a02b93e6a508a2e0492851003d9139e981eb Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Mon, 17 Jan 2022 09:27:32 -0500 Subject: [PATCH 214/798] Improvements to avx512 adler32 implementations Now that better benchmarks are in place, it became apparent that masked broadcast was _not_ faster and it's actually faster to use vmovd, as suspected. Additionally, for the VNNI variant, we've unlocked some additional ILP by doing a second dot product in the loop to a different running sum that gets recombined later. This broke a data dependency chain and allowed the IPC be ~2.75. The result is about a 40-50% improvement in runtime. Additionally, we've called the lesser SIMD sized variants if the input is too small and they happen to be compiled in. This helps for the impossibly small input that still is large enough to be a vector length. For size 16 and 32 inputs I was seeing something like sub 10 ns instead of 50 ns. --- arch/x86/adler32_avx2.c | 9 +-- arch/x86/adler32_avx512.c | 108 ++++++++++++++++++++++----------- arch/x86/adler32_avx512_vnni.c | 72 ++++++++++++++-------- fallback_builtins.h | 29 ++++++++- 4 files changed, 151 insertions(+), 67 deletions(-) diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index bc9156bb3d..3d49a5b848 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -9,6 +9,7 @@ #include "../../zutil.h" #include "../../adler32_p.h" +#include "../../fallback_builtins.h" #include @@ -53,8 +54,8 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); - __m256i vs1 = _mm256_castsi128_si256(_mm_cvtsi32_si128(adler)); - __m256i vs2 = _mm256_castsi128_si256(_mm_cvtsi32_si128(sum2)); + __m256i vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler)); + __m256i vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(sum2)); const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); @@ -129,8 +130,8 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ adler = partial_hsum(vs1) % BASE; sum2 = hsum(vs2) % BASE; - vs1 = _mm256_castsi128_si256(_mm_cvtsi32_si128(adler)); - vs2 = _mm256_castsi128_si256(_mm_cvtsi32_si128(sum2)); + vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler)); + vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(sum2)); } /* Process tail (len < 16). */ diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index f73ceccef1..79fa271f3e 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -10,18 +10,56 @@ #include "../../zutil.h" #include "../../adler32_p.h" +#include "../../cpu_features.h" +#include "../../fallback_builtins.h" #include #ifdef X86_AVX512_ADLER32 +static inline uint32_t partial_hsum(__m512i x) { + /* We need a permutation vector to extract every other integer. The + * rest are going to be zeros. Marking this const so the compiler stands + * a better chance of keeping this resident in a register through entire + * loop execution. We certainly have enough zmm registers (32) */ + const __m512i perm_vec = _mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, + 1, 1, 1, 1, 1, 1, 1, 1); + + __m512i non_zero = _mm512_permutexvar_epi32(perm_vec, x); + + /* From here, it's a simple 256 bit wide reduction sum */ + __m256i non_zero_avx = _mm512_castsi512_si256(non_zero); + + /* See Agner Fog's vectorclass for a decent reference. Essentially, phadd is + * pretty slow, much slower than the longer instruction sequence below */ + __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(non_zero_avx, 1), + _mm256_castsi256_si128(non_zero_avx)); + __m128i sum2 = _mm_add_epi32(sum1,_mm_unpackhi_epi64(sum1, sum1)); + __m128i sum3 = _mm_add_epi32(sum2,_mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t sum2; + /* For impossibly tiny sizes, use the smaller width versions. We still need + * to check for compile time support for these but they are likely there */ +#ifdef X86_SSE41_ADLER32 + if (len < 32) + return adler32_sse41(adler, buf, len); +#endif + +#ifdef X86_AVX2_ADLER32 + if (len < 64) + return adler32_avx2(adler, buf, len); +#endif + /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; + /* Only capture these corner cases if we didn't compile with SSE41 and AVX2 support + * This should make for shorter compiled code */ +#if !defined(X86_AVX2_ADLER32) && !defined(X86_SSE41_ADLER32) /* in case user likes doing a byte at a time, keep it fast */ if (UNLIKELY(len == 1)) return adler32_len_1(adler, buf, sum2); @@ -33,52 +71,54 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, siz /* in case short lengths are provided, keep it somewhat fast */ if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); +#endif - const __mmask16 vs_mask = 1U << 15; - __m512i vs1 = _mm512_maskz_set1_epi32(vs_mask, adler); - __m512i vs2 = _mm512_maskz_set1_epi32(vs_mask, sum2); + __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); + __m512i vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); - const __m512i dot1v = _mm512_set1_epi8(1); const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); const __m512i dot3v = _mm512_set1_epi16(1); + const __m512i zero = _mm512_setzero_si512(); while (len >= 64) { - __m512i vs1_0 = vs1; - - int k = (len < NMAX ? (int)len : NMAX); - k -= k % 64; - len -= k; - - while (k >= 64) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) - */ - __m512i vbuf = _mm512_loadu_si512(buf); - buf += 64; - k -= 64; - - __m512i v_short_sum1 = _mm512_maddubs_epi16(vbuf, dot1v); // multiply-add, resulting in 16 shorts. - __m512i vsum1 = _mm512_madd_epi16(v_short_sum1, dot3v); // sum 16 shorts to 8 int32_t; - __m512i v_short_sum2 = _mm512_maddubs_epi16(vbuf, dot2v); - vs1 = _mm512_add_epi32(vsum1, vs1); - __m512i vsum2 = _mm512_madd_epi16(v_short_sum2, dot3v); - vs1_0 = _mm512_slli_epi32(vs1_0, 6); - vsum2 = _mm512_add_epi32(vsum2, vs2); - vs2 = _mm512_add_epi32(vsum2, vs1_0); - vs1_0 = vs1; - } - - adler = _mm512_reduce_add_epi32(vs1) % BASE; - vs1 = _mm512_maskz_set1_epi32(vs_mask, adler); + __m512i vs1_0 = vs1; + __m512i vs3 = _mm512_setzero_si512(); + + int k = (len < NMAX ? (int)len : NMAX); + k -= k % 64; + len -= k; + + while (k >= 64) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + __m512i vbuf = _mm512_loadu_si512(buf); + buf += 64; + k -= 64; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf, zero); + __m512i v_short_sum2 = _mm512_maddubs_epi16(vbuf, dot2v); + vs1 = _mm512_add_epi32(vs1_sad, vs1); + vs3 = _mm512_add_epi32(vs3, vs1_0); + __m512i vsum2 = _mm512_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm512_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + vs3 = _mm512_slli_epi32(vs3, 6); + vs2 = _mm512_add_epi32(vs2, vs3); + + adler = partial_hsum(vs1) % BASE; + vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); sum2 = _mm512_reduce_add_epi32(vs2) % BASE; - vs2 = _mm512_maskz_set1_epi32(vs_mask, sum2); + vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); } - /* Process tail (len < 16). */ + /* Process tail (len < 64). */ return adler32_len_16(adler, buf, len, sum2); } diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index f4e2c33edc..fd50b39a6b 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -11,19 +11,21 @@ #include "../../zutil.h" #include "../../adler32_p.h" +#include "../../cpu_features.h" +#include "../../fallback_builtins.h" #include #ifdef X86_AVX512VNNI_ADLER32 -static inline uint32_t partial_hsum(__m512i x) -{ +static inline uint32_t partial_hsum(__m512i x) { /* We need a permutation vector to extract every other integer. The * rest are going to be zeros. Marking this const so the compiler stands * a better chance of keeping this resident in a register through entire * loop execution. We certainly have enough zmm registers (32) */ const __m512i perm_vec = _mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, 1, 1, 1, 1, 1, 1, 1, 1); + __m512i non_zero = _mm512_permutexvar_epi32(perm_vec, x); /* From here, it's a simple 256 bit wide reduction sum */ @@ -41,10 +43,25 @@ static inline uint32_t partial_hsum(__m512i x) Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t sum2; + /* For impossibly tiny sizes, use the smaller width versions. We still need + * to check for compile time support for these but they are likely there */ +#ifdef X86_SSE41_ADLER32 + if (len < 32) + return adler32_sse41(adler, buf, len); +#endif + +#ifdef X86_AVX2_ADLER32 + if (len < 64) + return adler32_avx2(adler, buf, len); +#endif + /* split Adler-32 into component sums */ sum2 = (adler >> 16) & 0xffff; adler &= 0xffff; + /* Only capture these corner cases if we didn't compile with SSE41 and AVX2 support + * This should make for shorter compiled code */ +#if !defined(X86_AVX2_ADLER32) && !defined(X86_SSE41_ADLER32) /* in case user likes doing a byte at a time, keep it fast */ if (UNLIKELY(len == 1)) return adler32_len_1(adler, buf, sum2); @@ -56,15 +73,15 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf /* in case short lengths are provided, keep it somewhat fast */ if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); +#endif - const __mmask16 vs_mask = 1U << 15; /* We want to place initial adler sum at vector position 0, as it is one of the lanes that line up * with the sum of absolute differences' reduction sum. If we do this, we can get away with a partial, * less expensive horizontal sum for the vs1 component at the end. It also happens to be marginally better * (by a single cycle) to do this with the ancient vmovd insruction, and simply allow the register to be * aliased up to a 512 bit wide zmm */ - __m512i vs1 = _mm512_castsi128_si512(_mm_cvtsi32_si128(adler)); - __m512i vs2 = _mm512_maskz_set1_epi32(vs_mask, sum2); + __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); + __m512i vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, @@ -79,6 +96,22 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf len -= k; __m512i vs1_0 = vs1; __m512i vs3 = _mm512_setzero_si512(); + /* We might get a tad bit more ILP here if we sum to a second register in the loop */ + __m512i vs2_1 = _mm512_setzero_si512(); + __m512i vbuf0, vbuf1; + + /* Remainder peeling */ + if (k % 128) { + vbuf1 = _mm512_loadu_si512(buf); + buf += 64; + k -= 64; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf1, zero); + vs1 = _mm512_add_epi32(vs1, vs1_sad); + vs3 = _mm512_add_epi32(vs3, vs1_0); + vs2 = _mm512_dpbusd_epi32(vs2, vbuf1, dot2v); + vs1_0 = vs1; + } /* Manually unrolled this loop by 2 for an decent amount of ILP */ while (k >= 128) { @@ -86,8 +119,8 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf vs1 = adler + sum(c[i]) vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) */ - __m512i vbuf0 = _mm512_loadu_si512(buf); - __m512i vbuf1 = _mm512_loadu_si512(buf+64); + vbuf0 = _mm512_loadu_si512(buf); + vbuf1 = _mm512_loadu_si512(buf + 64); buf += 128; k -= 128; @@ -97,38 +130,25 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf /* multiply-add, resulting in 16 ints. Fuse with sum stage from prior versions, as we now have the dp * instructions to eliminate them */ vs2 = _mm512_dpbusd_epi32(vs2, vbuf0, dot2v); - vs1_0 = vs1; + vs3 = _mm512_add_epi32(vs3, vs1); vs1_sad = _mm512_sad_epu8(vbuf1, zero); vs1 = _mm512_add_epi32(vs1, vs1_sad); - vs3 = _mm512_add_epi32(vs3, vs1_0); - vs2 = _mm512_dpbusd_epi32(vs2, vbuf1, dot2v); - vs1_0 = vs1; - } - - /* Remainder peeling */ - while (k >= 64) { - __m512i vbuf = _mm512_loadu_si512(buf); - buf += 64; - k -= 64; - - __m512i vs1_sad = _mm512_sad_epu8(vbuf, zero); - vs1 = _mm512_add_epi32(vs1, vs1_sad); - vs3 = _mm512_add_epi32(vs3, vs1_0); - vs2 = _mm512_dpbusd_epi32(vs2, vbuf, dot2v); + vs2_1 = _mm512_dpbusd_epi32(vs2_1, vbuf1, dot2v); vs1_0 = vs1; } vs3 = _mm512_slli_epi32(vs3, 6); vs2 = _mm512_add_epi32(vs2, vs3); + vs2 = _mm512_add_epi32(vs2, vs2_1); adler = partial_hsum(vs1) % BASE; - vs1 = _mm512_castsi128_si512(_mm_cvtsi32_si128(adler)); + vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); sum2 = _mm512_reduce_add_epi32(vs2) % BASE; - vs2 = _mm512_maskz_set1_epi32(vs_mask, sum2); + vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); } - /* Process tail (len < 16). */ + /* Process tail (len < 64). */ return adler32_len_16(adler, buf, len, sum2); } diff --git a/fallback_builtins.h b/fallback_builtins.h index 314ad3267f..fd54446ce8 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -1,5 +1,5 @@ -#ifndef X86_BUILTIN_CTZ_H -#define X86_BUILTIN_CTZ_H +#ifndef FALLBACK_BUILTINS_H +#define FALLBACK_BUILTINS_H #if defined(_MSC_VER) && !defined(__clang__) #if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined(_M_ARM) || defined(_M_ARM64) @@ -41,4 +41,27 @@ static __forceinline unsigned long long __builtin_ctzll(uint64_t value) { #endif #endif -#endif + +/* Unfortunately GCC _and_ clang didn't support these things until version + * 10 and 12, respectively */ +#ifdef __AVX2__ +#include + +#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 10) +static inline __m256i _mm256_zextsi128_si256(__m128i a) { + __m128i r; + __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); + return _mm256_castsi128_si256(r); +} + +#ifdef __AVX512F__ +static inline __m512i _mm512_zextsi128_si512(__m128i a) { + __m128i r; + __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); + return _mm512_castsi128_si512(r); +} +#endif // __AVX512F__ +#endif // __AVX2__ + +#endif // clang/gcc test +#endif // include guard FALLBACK_BUILTINS_H From 429bc4f5d5621e70aeeff6ba172eb9117cf8dc7c Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 18 Jan 2022 09:47:45 -0500 Subject: [PATCH 215/798] Remove the "avx512_well_suited" cpu flag Now that we have confirmation that the AVX512 variants so far have been universally better on every capable CPU we've tested them on, there's no sense in trying to maintain a whitelist. --- arch/x86/adler32_avx512.c | 4 ++-- arch/x86/x86.c | 45 --------------------------------------- arch/x86/x86.h | 1 - fallback_builtins.h | 7 +++--- functable.c | 4 ++-- 5 files changed, 7 insertions(+), 54 deletions(-) diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index 79fa271f3e..d85f402a06 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -45,12 +45,12 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, siz * to check for compile time support for these but they are likely there */ #ifdef X86_SSE41_ADLER32 if (len < 32) - return adler32_sse41(adler, buf, len); + return adler32_sse41(adler, buf, len); #endif #ifdef X86_AVX2_ADLER32 if (len < 64) - return adler32_avx2(adler, buf, len); + return adler32_avx2(adler, buf, len); #endif /* split Adler-32 into component sums */ diff --git a/arch/x86/x86.c b/arch/x86/x86.c index 66bfa4e284..3398426e23 100644 --- a/arch/x86/x86.c +++ b/arch/x86/x86.c @@ -28,7 +28,6 @@ Z_INTERNAL int x86_cpu_has_sse42; Z_INTERNAL int x86_cpu_has_pclmulqdq; Z_INTERNAL int x86_cpu_has_vpclmulqdq; Z_INTERNAL int x86_cpu_has_tzcnt; -Z_INTERNAL int x86_cpu_well_suited_avx512; static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) { #ifdef _MSC_VER @@ -61,32 +60,14 @@ static void cpuidex(int info, int subinfo, unsigned* eax, unsigned* ebx, unsigne void Z_INTERNAL x86_check_features(void) { unsigned eax, ebx, ecx, edx; unsigned maxbasic; - unsigned family, model, extended_model; - int intel_cpu; - char cpu_identity[13]; cpuid(0, &maxbasic, &ebx, &ecx, &edx); - /* NULL terminate the string */ - memset(cpu_identity, 0, 13); - memcpy(cpu_identity, (char*)&ebx, sizeof(int)); - memcpy(cpu_identity + 4, (char*)&edx, sizeof(int)); - memcpy(cpu_identity + 8, (char*)&ecx, sizeof(int)); - - intel_cpu = strncmp(cpu_identity, "GenuineIntel", 12) == 0; - - cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx); - x86_cpu_has_sse2 = edx & 0x4000000; x86_cpu_has_ssse3 = ecx & 0x200; x86_cpu_has_sse41 = ecx & 0x80000; x86_cpu_has_sse42 = ecx & 0x100000; x86_cpu_has_pclmulqdq = ecx & 0x2; - x86_cpu_well_suited_avx512 = 0; - - model = (eax & 0xf0) >> 4; - family = (eax & 0xf00) >> 8; - extended_model = (eax & 0xf0000) >> 16; if (maxbasic >= 7) { cpuidex(7, 0, &eax, &ebx, &ecx, &edx); @@ -104,30 +85,4 @@ void Z_INTERNAL x86_check_features(void) { x86_cpu_has_avx2 = 0; x86_cpu_has_vpclmulqdq = 0; } - - - if (intel_cpu) { - /* All of the Knights Landing and Knights Ferry _likely_ benefit - * from the AVX512 adler checksum implementation */ - if (family == 0xb) { - x86_cpu_well_suited_avx512 = 1; - } else if (family == 0x6) { - if (model == 0x5 && extended_model == 0x5) { - /* Experimentally, on skylake-x and cascadelake-x, it has been - * unwaiveringly faster to use avx512 and avx512 vnni */ - x86_cpu_well_suited_avx512 = 1; - } else if (model == 0xa && extended_model == 0x6) { - /* Icelake server */ - x86_cpu_well_suited_avx512 = 1; - } else if (model == 0xf && extended_model == 0x8) { - /* Saphire rapids */ - x86_cpu_well_suited_avx512 = 1; - } - - /* Still need to check whether Rocket Lake and/or AlderLake - * benefit from the AVX512VNNI accelerated adler32 implementations. - * For now this working list is probably safe */ - } - } - } diff --git a/arch/x86/x86.h b/arch/x86/x86.h index 0cb79e69a1..2e56c5d567 100644 --- a/arch/x86/x86.h +++ b/arch/x86/x86.h @@ -16,7 +16,6 @@ extern int x86_cpu_has_sse42; extern int x86_cpu_has_pclmulqdq; extern int x86_cpu_has_vpclmulqdq; extern int x86_cpu_has_tzcnt; -extern int x86_cpu_well_suited_avx512; void Z_INTERNAL x86_check_features(void); diff --git a/fallback_builtins.h b/fallback_builtins.h index fd54446ce8..5aaa2c681e 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -42,8 +42,7 @@ static __forceinline unsigned long long __builtin_ctzll(uint64_t value) { #endif #endif -/* Unfortunately GCC _and_ clang didn't support these things until version - * 10 and 12, respectively */ +/* Unfortunately GCC didn't support these things until version 10 */ #ifdef __AVX2__ #include @@ -61,7 +60,7 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { return _mm512_castsi128_si512(r); } #endif // __AVX512F__ -#endif // __AVX2__ +#endif // gcc version 10 test -#endif // clang/gcc test +#endif // __AVX2__ #endif // include guard FALLBACK_BUILTINS_H diff --git a/functable.c b/functable.c index 96fbc98315..6e9563bcc4 100644 --- a/functable.c +++ b/functable.c @@ -120,11 +120,11 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ functable.adler32 = &adler32_avx2; #endif #ifdef X86_AVX512_ADLER32 - if (x86_cpu_has_avx512 && x86_cpu_well_suited_avx512) + if (x86_cpu_has_avx512) functable.adler32 = &adler32_avx512; #endif #ifdef X86_AVX512VNNI_ADLER32 - if (x86_cpu_has_avx512vnni && x86_cpu_well_suited_avx512) { + if (x86_cpu_has_avx512vnni) { functable.adler32 = &adler32_avx512_vnni; } #endif From c805aaecc939c158f4b9773f5c7c629d42aad0e1 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sat, 22 Jan 2022 20:47:45 -0500 Subject: [PATCH 216/798] Fixed inadvertent breakage of CPUID usage In removing the AVX512 "well-suited" flag, a second cpuid call that's needed for feature detection was accidently removed. This brings that back. --- arch/x86/x86.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/x86.c b/arch/x86/x86.c index 3398426e23..945b29ef94 100644 --- a/arch/x86/x86.c +++ b/arch/x86/x86.c @@ -62,6 +62,7 @@ void Z_INTERNAL x86_check_features(void) { unsigned maxbasic; cpuid(0, &maxbasic, &ebx, &ecx, &edx); + cpuid(1 /*CPU_PROCINFO_AND_FEATUREBITS*/, &eax, &ebx, &ecx, &edx); x86_cpu_has_sse2 = edx & 0x4000000; x86_cpu_has_ssse3 = ecx & 0x200; From 0911015e485ad03c4167798506b7ce4f83d16d41 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 09:17:19 -0800 Subject: [PATCH 217/798] Use fixed width types in compare256 definition. --- arch/x86/compare256_avx2.c | 4 ++-- arch/x86/compare256_sse42.c | 4 ++-- compare256.c | 16 ++++++++-------- cpu_features.h | 12 ++++++------ functable.c | 2 +- functable.h | 2 +- test/benchmarks/benchmark_compare256.cc | 2 +- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/arch/x86/compare256_avx2.c b/arch/x86/compare256_avx2.c index 253976b5bf..fd9481bfde 100644 --- a/arch/x86/compare256_avx2.c +++ b/arch/x86/compare256_avx2.c @@ -16,7 +16,7 @@ #endif /* UNALIGNED_OK, AVX2 intrinsic comparison */ -static inline uint32_t compare256_unaligned_avx2_static(const unsigned char *src0, const unsigned char *src1) { +static inline uint32_t compare256_unaligned_avx2_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; do { @@ -47,7 +47,7 @@ static inline uint32_t compare256_unaligned_avx2_static(const unsigned char *src return 256; } -Z_INTERNAL uint32_t compare256_unaligned_avx2(const unsigned char *src0, const unsigned char *src1) { +Z_INTERNAL uint32_t compare256_unaligned_avx2(const uint8_t *src0, const uint8_t *src1) { return compare256_unaligned_avx2_static(src0, src1); } diff --git a/arch/x86/compare256_sse42.c b/arch/x86/compare256_sse42.c index 3e5f150566..5f30b5e3ed 100644 --- a/arch/x86/compare256_sse42.c +++ b/arch/x86/compare256_sse42.c @@ -26,7 +26,7 @@ #endif /* UNALIGNED_OK, SSE4.2 intrinsic comparison */ -static inline uint32_t compare256_unaligned_sse4_static(const unsigned char *src0, const unsigned char *src1) { +static inline uint32_t compare256_unaligned_sse4_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; do { @@ -54,7 +54,7 @@ static inline uint32_t compare256_unaligned_sse4_static(const unsigned char *src return 256; } -Z_INTERNAL uint32_t compare256_unaligned_sse4(const unsigned char *src0, const unsigned char *src1) { +Z_INTERNAL uint32_t compare256_unaligned_sse4(const uint8_t *src0, const uint8_t *src1) { return compare256_unaligned_sse4_static(src0, src1); } diff --git a/compare256.c b/compare256.c index 20d967e8bd..415088c5f1 100644 --- a/compare256.c +++ b/compare256.c @@ -9,7 +9,7 @@ #include "fallback_builtins.h" /* ALIGNED, byte comparison */ -static inline uint32_t compare256_c_static(const unsigned char *src0, const unsigned char *src1) { +static inline uint32_t compare256_c_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; do { @@ -42,7 +42,7 @@ static inline uint32_t compare256_c_static(const unsigned char *src0, const unsi return 256; } -Z_INTERNAL uint32_t compare256_c(const unsigned char *src0, const unsigned char *src1) { +Z_INTERNAL uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1) { return compare256_c_static(src0, src1); } @@ -59,7 +59,7 @@ Z_INTERNAL uint32_t compare256_c(const unsigned char *src0, const unsigned char #ifdef UNALIGNED_OK /* UNALIGNED_OK, 16-bit integer comparison */ -static inline uint32_t compare256_unaligned_16_static(const unsigned char *src0, const unsigned char *src1) { +static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; do { @@ -80,7 +80,7 @@ static inline uint32_t compare256_unaligned_16_static(const unsigned char *src0, return 256; } -Z_INTERNAL uint32_t compare256_unaligned_16(const unsigned char *src0, const unsigned char *src1) { +Z_INTERNAL uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1) { return compare256_unaligned_16_static(src0, src1); } @@ -97,7 +97,7 @@ Z_INTERNAL uint32_t compare256_unaligned_16(const unsigned char *src0, const uns #ifdef HAVE_BUILTIN_CTZ /* UNALIGNED_OK, 32-bit integer comparison */ -static inline uint32_t compare256_unaligned_32_static(const unsigned char *src0, const unsigned char *src1) { +static inline uint32_t compare256_unaligned_32_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; do { @@ -118,7 +118,7 @@ static inline uint32_t compare256_unaligned_32_static(const unsigned char *src0, return 256; } -Z_INTERNAL uint32_t compare256_unaligned_32(const unsigned char *src0, const unsigned char *src1) { +Z_INTERNAL uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1) { return compare256_unaligned_32_static(src0, src1); } @@ -137,7 +137,7 @@ Z_INTERNAL uint32_t compare256_unaligned_32(const unsigned char *src0, const uns #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) /* UNALIGNED64_OK, 64-bit integer comparison */ -static inline uint32_t compare256_unaligned_64_static(const unsigned char *src0, const unsigned char *src1) { +static inline uint32_t compare256_unaligned_64_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; do { @@ -158,7 +158,7 @@ static inline uint32_t compare256_unaligned_64_static(const unsigned char *src0, return 256; } -Z_INTERNAL uint32_t compare256_unaligned_64(const unsigned char *src0, const unsigned char *src1) { +Z_INTERNAL uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1) { return compare256_unaligned_64_static(src0, src1); } diff --git a/cpu_features.h b/cpu_features.h index 4cd1ed7b26..103356b3e6 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -140,18 +140,18 @@ extern uint32_t s390_crc32_vx(uint32_t crc, const unsigned char *buf, uint64_t l #endif /* compare256 */ -extern uint32_t compare256_c(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1); #ifdef UNALIGNED_OK -extern uint32_t compare256_unaligned_16(const unsigned char *src0, const unsigned char *src1); -extern uint32_t compare256_unaligned_32(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1); +extern uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1); #ifdef UNALIGNED64_OK -extern uint32_t compare256_unaligned_64(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1); #endif #ifdef X86_SSE42_CMP_STR -extern uint32_t compare256_unaligned_sse4(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_sse4(const uint8_t *src0, const uint8_t *src1); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t compare256_unaligned_avx2(const unsigned char *src0, const unsigned char *src1); +extern uint32_t compare256_unaligned_avx2(const uint8_t *src0, const uint8_t *src1); #endif #endif diff --git a/functable.c b/functable.c index 6e9563bcc4..edcbba05d6 100644 --- a/functable.c +++ b/functable.c @@ -348,7 +348,7 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t return functable.crc32(crc, buf, len); } -Z_INTERNAL uint32_t compare256_stub(const unsigned char *src0, const unsigned char *src1) { +Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { #ifdef UNALIGNED_OK # if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) diff --git a/functable.h b/functable.h index f029ed4d13..277e34a24a 100644 --- a/functable.h +++ b/functable.h @@ -19,7 +19,7 @@ struct functable_s { void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); uint32_t (* crc32_fold_final) (crc32_fold *crc); void (* slide_hash) (deflate_state *s); - uint32_t (* compare256) (const unsigned char *src0, const unsigned char *src1); + uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); uint32_t (* chunksize) (void); diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 063d110fa0..a420398d97 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -18,7 +18,7 @@ extern "C" { #define MAX_COMPARE_SIZE (256) -typedef uint32_t (*compare256_func)(const unsigned char *src0, const unsigned char *src1); +typedef uint32_t (*compare256_func)(const uint8_t *src0, const uint8_t *src1); class compare256: public benchmark::Fixture { private: From a5a0b40e17776e52fa981074925d825f3399b231 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 09:27:58 -0800 Subject: [PATCH 218/798] Move cpu_feature includes out of zutil.h. --- arch/x86/crc32_fold_pclmulqdq.c | 2 ++ cpu_features.c | 3 ++- cpu_features.h | 9 ++++++++- deflate.c | 1 + inflate.c | 1 + zutil.h | 10 ---------- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index a01cdf775c..6e429d6274 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -24,6 +24,8 @@ #include #include // _mm_extract_epi32 +#include "x86.h" + #include "../../crc32_fold.h" #ifdef X86_VPCLMULQDQ_CRC diff --git a/cpu_features.c b/cpu_features.c index 70bfcb698c..6ef5aa2c4b 100644 --- a/cpu_features.c +++ b/cpu_features.c @@ -4,7 +4,8 @@ */ #include "zbuild.h" -#include "zutil.h" + +#include "cpu_features.h" Z_INTERNAL void cpu_check_features(void) { static int features_checked = 0; diff --git a/cpu_features.h b/cpu_features.h index 103356b3e6..7dea3a6830 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -9,8 +9,15 @@ #include "deflate.h" #include "crc32_fold.h" -#ifdef X86_FEATURES +#if defined(X86_FEATURES) +# include "arch/x86/x86.h" # include "fallback_builtins.h" +#elif defined(ARM_FEATURES) +# include "arch/arm/arm.h" +#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) +# include "arch/power/power.h" +#elif defined(S390_FEATURES) +# include "arch/s390/s390.h" #endif extern void cpu_check_features(); diff --git a/deflate.c b/deflate.c index 8f569bf2e5..5919cdb364 100644 --- a/deflate.c +++ b/deflate.c @@ -48,6 +48,7 @@ */ #include "zbuild.h" +#include "cpu_features.h" #include "deflate.h" #include "deflate_p.h" #include "functable.h" diff --git a/inflate.c b/inflate.c index 44a50e61c7..1e8806a490 100644 --- a/inflate.c +++ b/inflate.c @@ -5,6 +5,7 @@ #include "zbuild.h" #include "zutil.h" +#include "cpu_features.h" #include "inftrees.h" #include "inflate.h" #include "inffast.h" diff --git a/zutil.h b/zutil.h index 660fabdacd..324fd992ee 100644 --- a/zutil.h +++ b/zutil.h @@ -259,14 +259,4 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr); # define ALIGNED_(x) __declspec(align(x)) #endif -#if defined(X86_FEATURES) -# include "arch/x86/x86.h" -#elif defined(ARM_FEATURES) -# include "arch/arm/arm.h" -#elif defined(PPC_FEATURES) || defined(POWER_FEATURES) -# include "arch/power/power.h" -#elif defined(S390_FEATURES) -# include "arch/s390/s390.h" -#endif - #endif /* ZUTIL_H_ */ From a639a3d43ffcacdde1964fa1d9b4b871916979c0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 09:28:37 -0800 Subject: [PATCH 219/798] Use cpu_check_features in inflate and deflate. --- deflate.c | 6 +----- inflate.c | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/deflate.c b/deflate.c index 5919cdb364..50c5531f1b 100644 --- a/deflate.c +++ b/deflate.c @@ -194,11 +194,7 @@ int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int int wrap = 1; static const char my_version[] = PREFIX2(VERSION); -#if defined(X86_FEATURES) - x86_check_features(); -#elif defined(ARM_FEATURES) - arm_check_features(); -#endif + cpu_check_features(); if (version == NULL || version[0] != my_version[0] || stream_size != sizeof(PREFIX3(stream))) { return Z_VERSION_ERROR; diff --git a/inflate.c b/inflate.c index 1e8806a490..06b37bf40c 100644 --- a/inflate.c +++ b/inflate.c @@ -105,11 +105,7 @@ int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits int32_t ret; struct inflate_state *state; -#if defined(X86_FEATURES) - x86_check_features(); -#elif defined(ARM_FEATURES) - arm_check_features(); -#endif + cpu_check_features(); if (version == NULL || version[0] != PREFIX2(VERSION)[0] || stream_size != (int)(sizeof(PREFIX3(stream)))) return Z_VERSION_ERROR; From 784c56346522d40725e6043bf6aebdabca47a23e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 09:37:13 -0800 Subject: [PATCH 220/798] Group together functable definitions that use deflate_state. --- cpu_features.h | 80 +++++++++++++++++----------------- functable.c | 114 ++++++++++++++++++++++++------------------------- functable.h | 12 +++--- 3 files changed, 103 insertions(+), 103 deletions(-) diff --git a/cpu_features.h b/cpu_features.h index 7dea3a6830..4d09646e73 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -22,46 +22,6 @@ extern void cpu_check_features(); -/* update_hash */ -extern uint32_t update_hash_c(deflate_state *const s, uint32_t h, uint32_t val); -#ifdef X86_SSE42_CRC_HASH -extern uint32_t update_hash_sse4(deflate_state *const s, uint32_t h, uint32_t val); -#elif defined(ARM_ACLE_CRC_HASH) -extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); -#endif - -/* insert_string */ -extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); -#ifdef X86_SSE42_CRC_HASH -extern void insert_string_sse4(deflate_state *const s, const uint32_t str, uint32_t count); -#elif defined(ARM_ACLE_CRC_HASH) -extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint32_t count); -#endif - -/* quick_insert_string */ -extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); -#ifdef X86_SSE42_CRC_HASH -extern Pos quick_insert_string_sse4(deflate_state *const s, const uint32_t str); -#elif defined(ARM_ACLE_CRC_HASH) -extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); -#endif - -/* slide_hash */ -#ifdef X86_SSE2 -void slide_hash_sse2(deflate_state *s); -#elif defined(ARM_NEON_SLIDEHASH) -void slide_hash_neon(deflate_state *s); -#endif -#if defined(PPC_VMX_SLIDEHASH) -void slide_hash_vmx(deflate_state *s); -#endif -#if defined(POWER8_VSX_SLIDEHASH) -void slide_hash_power8(deflate_state *s); -#endif -#ifdef X86_AVX2 -void slide_hash_avx2(deflate_state *s); -#endif - /* adler32 */ extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len); #ifdef ARM_NEON_ADLER32 @@ -162,6 +122,14 @@ extern uint32_t compare256_unaligned_avx2(const uint8_t *src0, const uint8_t *sr #endif #endif +/* insert_string */ +extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); +#ifdef X86_SSE42_CRC_HASH +extern void insert_string_sse4(deflate_state *const s, const uint32_t str, uint32_t count); +#elif defined(ARM_ACLE_CRC_HASH) +extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint32_t count); +#endif + /* longest_match */ extern uint32_t longest_match_c(deflate_state *const s, Pos cur_match); #ifdef UNALIGNED_OK @@ -194,4 +162,36 @@ extern uint32_t longest_match_slow_unaligned_avx2(deflate_state *const s, Pos cu #endif #endif +/* quick_insert_string */ +extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); +#ifdef X86_SSE42_CRC_HASH +extern Pos quick_insert_string_sse4(deflate_state *const s, const uint32_t str); +#elif defined(ARM_ACLE_CRC_HASH) +extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); +#endif + +/* slide_hash */ +#ifdef X86_SSE2 +void slide_hash_sse2(deflate_state *s); +#elif defined(ARM_NEON_SLIDEHASH) +void slide_hash_neon(deflate_state *s); +#endif +#if defined(PPC_VMX_SLIDEHASH) +void slide_hash_vmx(deflate_state *s); +#endif +#if defined(POWER8_VSX_SLIDEHASH) +void slide_hash_power8(deflate_state *s); +#endif +#ifdef X86_AVX2 +void slide_hash_avx2(deflate_state *s); +#endif + +/* update_hash */ +extern uint32_t update_hash_c(deflate_state *const s, uint32_t h, uint32_t val); +#ifdef X86_SSE42_CRC_HASH +extern uint32_t update_hash_sse4(deflate_state *const s, uint32_t h, uint32_t val); +#elif defined(ARM_ACLE_CRC_HASH) +extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); +#endif + #endif diff --git a/functable.c b/functable.c index edcbba05d6..19d7258e1e 100644 --- a/functable.c +++ b/functable.c @@ -96,6 +96,56 @@ Z_INTERNAL void slide_hash_stub(deflate_state *s) { functable.slide_hash(s); } +Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { + +#ifdef UNALIGNED_OK +# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) + functable.longest_match = &longest_match_unaligned_64; +# elif defined(HAVE_BUILTIN_CTZ) + functable.longest_match = &longest_match_unaligned_32; +# else + functable.longest_match = &longest_match_unaligned_16; +# endif +# ifdef X86_SSE42_CMP_STR + if (x86_cpu_has_sse42) + functable.longest_match = &longest_match_unaligned_sse4; +# endif +# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_avx2) + functable.longest_match = &longest_match_unaligned_avx2; +# endif +#else + functable.longest_match = &longest_match_c; +#endif + + return functable.longest_match(s, cur_match); +} + +Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_match) { + +#ifdef UNALIGNED_OK +# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) + functable.longest_match_slow = &longest_match_slow_unaligned_64; +# elif defined(HAVE_BUILTIN_CTZ) + functable.longest_match_slow = &longest_match_slow_unaligned_32; +# else + functable.longest_match_slow = &longest_match_slow_unaligned_16; +# endif +# ifdef X86_SSE42_CMP_STR + if (x86_cpu_has_sse42) + functable.longest_match_slow = &longest_match_slow_unaligned_sse4; +# endif +# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_avx2) + functable.longest_match_slow = &longest_match_slow_unaligned_avx2; +# endif +#else + functable.longest_match_slow = &longest_match_slow_c; +#endif + + return functable.longest_match_slow(s, cur_match); +} + Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_t len) { // Initialize default functable.adler32 = &adler32_c; @@ -373,74 +423,24 @@ Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { return functable.compare256(src0, src1); } -Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { - -#ifdef UNALIGNED_OK -# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.longest_match = &longest_match_unaligned_64; -# elif defined(HAVE_BUILTIN_CTZ) - functable.longest_match = &longest_match_unaligned_32; -# else - functable.longest_match = &longest_match_unaligned_16; -# endif -# ifdef X86_SSE42_CMP_STR - if (x86_cpu_has_sse42) - functable.longest_match = &longest_match_unaligned_sse4; -# endif -# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - functable.longest_match = &longest_match_unaligned_avx2; -# endif -#else - functable.longest_match = &longest_match_c; -#endif - - return functable.longest_match(s, cur_match); -} - -Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_match) { - -#ifdef UNALIGNED_OK -# if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) - functable.longest_match_slow = &longest_match_slow_unaligned_64; -# elif defined(HAVE_BUILTIN_CTZ) - functable.longest_match_slow = &longest_match_slow_unaligned_32; -# else - functable.longest_match_slow = &longest_match_slow_unaligned_16; -# endif -# ifdef X86_SSE42_CMP_STR - if (x86_cpu_has_sse42) - functable.longest_match_slow = &longest_match_slow_unaligned_sse4; -# endif -# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - functable.longest_match_slow = &longest_match_slow_unaligned_avx2; -# endif -#else - functable.longest_match_slow = &longest_match_slow_c; -#endif - - return functable.longest_match_slow(s, cur_match); -} - /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { - update_hash_stub, - insert_string_stub, - quick_insert_string_stub, adler32_stub, crc32_stub, crc32_fold_reset_stub, crc32_fold_copy_stub, crc32_fold_final_stub, - slide_hash_stub, compare256_stub, - longest_match_stub, - longest_match_slow_stub, chunksize_stub, chunkcopy_stub, chunkcopy_safe_stub, chunkunroll_stub, chunkmemset_stub, - chunkmemset_safe_stub + chunkmemset_safe_stub, + insert_string_stub, + longest_match_stub, + longest_match_slow_stub, + quick_insert_string_stub, + slide_hash_stub, + update_hash_stub }; diff --git a/functable.h b/functable.h index 277e34a24a..949c5b1be8 100644 --- a/functable.h +++ b/functable.h @@ -10,24 +10,24 @@ #include "crc32_fold.h" struct functable_s { - uint32_t (* update_hash) (deflate_state *const s, uint32_t h, uint32_t val); - void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); - Pos (* quick_insert_string)(deflate_state *const s, uint32_t str); uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, size_t len); uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); uint32_t (* crc32_fold_reset) (crc32_fold *crc); void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); uint32_t (* crc32_fold_final) (crc32_fold *crc); - void (* slide_hash) (deflate_state *s); uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); - uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); - uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); uint32_t (* chunksize) (void); uint8_t* (* chunkcopy) (uint8_t *out, uint8_t const *from, unsigned len); uint8_t* (* chunkcopy_safe) (uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); uint8_t* (* chunkunroll) (uint8_t *out, unsigned *dist, unsigned *len); uint8_t* (* chunkmemset) (uint8_t *out, unsigned dist, unsigned len); uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); + void (* insert_string) (deflate_state *const s, uint32_t str, uint32_t count); + uint32_t (* longest_match) (deflate_state *const s, Pos cur_match); + uint32_t (* longest_match_slow) (deflate_state *const s, Pos cur_match); + Pos (* quick_insert_string)(deflate_state *const s, uint32_t str); + void (* slide_hash) (deflate_state *s); + uint32_t (* update_hash) (deflate_state *const s, uint32_t h, uint32_t val); }; Z_INTERNAL extern Z_TLS struct functable_s functable; From 197825d838c8edcd0243f5f6ec4e66694a6f920c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 09:38:20 -0800 Subject: [PATCH 221/798] Use extern keyword in slide_hash function definitions. --- cpu_features.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpu_features.h b/cpu_features.h index 4d09646e73..ce5f0f7eff 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -172,18 +172,18 @@ extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); /* slide_hash */ #ifdef X86_SSE2 -void slide_hash_sse2(deflate_state *s); +extern void slide_hash_sse2(deflate_state *s); #elif defined(ARM_NEON_SLIDEHASH) -void slide_hash_neon(deflate_state *s); +extern void slide_hash_neon(deflate_state *s); #endif #if defined(PPC_VMX_SLIDEHASH) -void slide_hash_vmx(deflate_state *s); +extern void slide_hash_vmx(deflate_state *s); #endif #if defined(POWER8_VSX_SLIDEHASH) -void slide_hash_power8(deflate_state *s); +extern void slide_hash_power8(deflate_state *s); #endif #ifdef X86_AVX2 -void slide_hash_avx2(deflate_state *s); +extern void slide_hash_avx2(deflate_state *s); #endif /* update_hash */ From 7a38338fad958a1a1a70f43050cefcaeef1a2371 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 09:49:13 -0800 Subject: [PATCH 222/798] Move cpu feature variant callback typedefs to cpu_features header. --- cpu_features.h | 8 ++++++++ test/benchmarks/benchmark_adler32.cc | 2 -- test/benchmarks/benchmark_compare256.cc | 2 -- test/benchmarks/benchmark_crc32.cc | 2 -- test/benchmarks/benchmark_slidehash.cc | 2 -- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpu_features.h b/cpu_features.h index ce5f0f7eff..ecb09eaa47 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -23,6 +23,8 @@ extern void cpu_check_features(); /* adler32 */ +typedef uint32_t (*adler32_func)(uint32_t adler, const unsigned char *buf, size_t len); + extern uint32_t adler32_c(uint32_t adler, const unsigned char *buf, size_t len); #ifdef ARM_NEON_ADLER32 extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len); @@ -97,6 +99,8 @@ extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned le #endif /* CRC32 */ +typedef uint32_t (*crc32_func)(uint32_t crc32, const unsigned char * buf, uint64_t len); + extern uint32_t crc32_byfour(uint32_t crc, const unsigned char *buf, uint64_t len); #ifdef ARM_ACLE_CRC_HASH extern uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len); @@ -107,6 +111,8 @@ extern uint32_t s390_crc32_vx(uint32_t crc, const unsigned char *buf, uint64_t l #endif /* compare256 */ +typedef uint32_t (*compare256_func)(const uint8_t *src0, const uint8_t *src1); + extern uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1); #ifdef UNALIGNED_OK extern uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1); @@ -171,6 +177,8 @@ extern Pos quick_insert_string_acle(deflate_state *const s, const uint32_t str); #endif /* slide_hash */ +typedef void (*slide_hash_func)(deflate_state *s); + #ifdef X86_SSE2 extern void slide_hash_sse2(deflate_state *s); #elif defined(ARM_NEON_SLIDEHASH) diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index 682908880a..0f63c5c3d1 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -20,8 +20,6 @@ extern "C" { #define MAX_RANDOM_INTS (1024 * 1024) #define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t)) -typedef uint32_t (*adler32_func)(uint32_t adler, const unsigned char *buf, size_t len); - class adler32: public benchmark::Fixture { private: uint32_t *random_ints; diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index a420398d97..0166816d04 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -18,8 +18,6 @@ extern "C" { #define MAX_COMPARE_SIZE (256) -typedef uint32_t (*compare256_func)(const uint8_t *src0, const uint8_t *src1); - class compare256: public benchmark::Fixture { private: uint8_t *str1; diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index 69d11a4d19..68ad3f0f17 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -20,8 +20,6 @@ extern "C" { #define MAX_RANDOM_INTS (1024 * 1024) #define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t)) -typedef uint32_t (*crc32_func)(uint32_t crc32, const unsigned char * buf, uint64_t len); - class crc32: public benchmark::Fixture { private: uint32_t *random_ints; diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index 174ea09316..7e6557365c 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -19,8 +19,6 @@ extern "C" { #define MAX_RANDOM_INTS 32768 -typedef void (*slide_hash_func)(deflate_state *s); - class slide_hash: public benchmark::Fixture { private: uint16_t *l0; From 3f879f27b1151015c8a6e545ba18c021ed839e32 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 13:05:44 -0800 Subject: [PATCH 223/798] Allow setting of version when building with pigz. --- test/pigz/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/pigz/CMakeLists.txt b/test/pigz/CMakeLists.txt index 43082cf263..0d5bc86430 100644 --- a/test/pigz/CMakeLists.txt +++ b/test/pigz/CMakeLists.txt @@ -13,6 +13,7 @@ # WITH_CODE_COVERAGE - Enable code coverage reporting # WITH_THREADS - Enable threading support # PIGZ_ENABLE_TESTS - Enable adding unit tests +# PIGZ_VERSION - Set the version of pigz to build # ZLIB_ROOT - Path to the zlib source directory # PTHREADS4W_ROOT - Path to pthreads4w source directory on Windows. # If not specified then threading will be disabled. @@ -28,6 +29,7 @@ include(../../cmake/detect-coverage.cmake) option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF) option(WITH_THREADS "Enable threading support" ON) option(PIGZ_ENABLE_TESTS "Build unit tests" ON) +option(PIGZ_VERSION "Set the version of pigz to build" "") project(pigz LANGUAGES C) @@ -54,8 +56,14 @@ elseif(WIN32) endif() # Fetch pigz source code from official repository +if(PIGZ_VERSION STREQUAL "") + set(PIGZ_TAG master) +else() + set(PIGZ_TAG ${PIGZ_VERSION}) +endif() FetchContent_Declare(pigz - GIT_REPOSITORY https://github.com/madler/pigz.git) + GIT_REPOSITORY https://github.com/madler/pigz.git + GIT_TAG ${PIGZ_TAG}) FetchContent_MakeAvailable(pigz) FetchContent_GetProperties(pigz) From 81f19715ba9337f76622aaa082ef2f7d2d76fdd4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 13:06:14 -0800 Subject: [PATCH 224/798] Use pigz version 2.6 due to bug in NOTHREADS support. https://github.com/madler/pigz/issues/97 --- .github/workflows/pigz.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index bce94fa4ea..153a7ac5f4 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -34,13 +34,14 @@ jobs: codecov: ubuntu_clang_pigz_no_optim cmake-args: -DWITH_OPTIM=OFF + # Use v2.6 due to NOTHREADS bug https://github.com/madler/pigz/issues/97 - name: Ubuntu Clang No Threads os: ubuntu-latest compiler: clang packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_pigz_no_threads - cmake-args: -DWITH_THREADS=OFF + cmake-args: -DWITH_THREADS=OFF -DPIGZ_VERSION=v2.6 - name: Ubuntu GCC AARCH64 os: ubuntu-latest From 08c2a332da25f9ae7e60148ae15d30e2077f5687 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 23 Jan 2022 16:18:05 -0800 Subject: [PATCH 225/798] Remove unused fdopen define for MSVC. --- test/minigzip.c | 2 +- zutil.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/test/minigzip.c b/test/minigzip.c index 29729f3894..e2e4bad3b3 100644 --- a/test/minigzip.c +++ b/test/minigzip.c @@ -12,7 +12,7 @@ * real thing. */ -#define _POSIX_SOURCE 1 /* This file needs POSIX for fdopen(). */ +#define _POSIX_SOURCE 1 #define _POSIX_C_SOURCE 200112 /* For snprintf(). */ #include "zbuild.h" diff --git a/zutil.h b/zutil.h index 324fd992ee..6ab70e8a29 100644 --- a/zutil.h +++ b/zutil.h @@ -132,10 +132,6 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ # define OS_CODE 19 #endif -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# define fdopen(fd, type) _fdopen(fd, type) -#endif - /* MS Visual Studio does not allow inline in C, only C++. But it provides __inline instead, so use that. */ #if defined(_MSC_VER) && !defined(inline) && !defined(__cplusplus) From 33e5e297e745e3474cd038c7cf0eca9612969dd6 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 25 Jan 2022 00:16:37 -0500 Subject: [PATCH 226/798] Make cmake and configure release flags consistent CMake sufficiently appends -DNDEBUG to the preprocessor macros when not compiling with debug symbols. This turns off debug level assertions and has some other side effects. As such, we should equally append this define to the configure scripts' CFLAGS. --- configure | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure b/configure index 215d0f286f..e957aa0ba1 100755 --- a/configure +++ b/configure @@ -396,6 +396,9 @@ if test "$gcc" -eq 1 && ($cc $CFLAGS -c $test.c) >> configure.log 2>&1; then if test $debug -eq 1; then CFLAGS="${CFLAGS} -DZLIB_DEBUG" SFLAGS="${SFLAGS} -DZLIB_DEBUG" + else + CFLAGS="${CFLAGS} -DNDEBUG" + SFLAGS="${SFLAGS} -DNDEBUG" fi if test -z "$uname"; then uname=$((uname -s || echo unknown) 2>/dev/null) From 87f2ae3f4918e856fff289357db2682b1691c37c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 23 Jan 2022 20:15:40 -0800 Subject: [PATCH 227/798] Fixed GCC warning about unused variable in longest_match. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit match_tpl.h:47:13: warning: unused variable ‘scan_start’ [-Wunused-variable] 47 | uint8_t scan_start[8], scan_end[8]; --- match_tpl.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/match_tpl.h b/match_tpl.h index 94e796b55e..853a4ad32f 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -44,7 +44,10 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { uint32_t chain_length, nice_match, best_len, offset; uint32_t lookahead = s->lookahead; Pos match_offset = 0; - uint8_t scan_start[8], scan_end[8]; +#ifdef UNALIGNED_OK + uint8_t scan_start[8]; +#endif + uint8_t scan_end[8]; #define GOTO_NEXT_CHAIN \ if (--chain_length && (cur_match = prev[cur_match & wmask]) > limit) \ From ea8f88a05e0ee9d200c9950b5638f5879da2add8 Mon Sep 17 00:00:00 2001 From: Michael Hirsch Date: Mon, 24 Jan 2022 19:22:01 -0500 Subject: [PATCH 228/798] Intel compilers: update deprecated -wn to -Wall style This removes warnings on every single target like: icx: command line warning #10430: Unsupported command line options encountered These options as listed are not supported. For more information, use '-qnextgen-diag'. option list: -w3 Signed-off-by: Michael Hirsch --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 454159bb74..72d4341655 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,13 +151,13 @@ if(WITH_GZFILEOP) add_definitions(-DWITH_GZFILEOP) endif() -if(CMAKE_C_COMPILER_ID MATCHES "Intel") +if(CMAKE_C_COMPILER_ID MATCHES "^Intel") if(CMAKE_HOST_UNIX) - set(WARNFLAGS "-w3") - set(WARNFLAGS_MAINTAINER "-w3 -Wcheck -Wremarks") + set(WARNFLAGS "-Wall") + set(WARNFLAGS_MAINTAINER "-Wall -Wcheck -Wremarks") set(WARNFLAGS_DISABLE "") else() - set(WARNFLAGS "/W3") + set(WARNFLAGS "/Wall") set(WARNFLAGS_MAINTAINER "/W5") set(WARNFLAGS_DISABLE "") endif() From 677f56825f7080403e18e57ffe8177f3df290f20 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 23 Jan 2022 12:59:01 -0800 Subject: [PATCH 229/798] Use static keyword for vec_sumsu to prevent undefined reference error when g++ linking. --- arch/power/adler32_power8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/power/adler32_power8.c b/arch/power/adler32_power8.c index 029aa3a84c..fc4086322e 100644 --- a/arch/power/adler32_power8.c +++ b/arch/power/adler32_power8.c @@ -44,7 +44,7 @@ #include "adler32_p.h" /* Vector across sum unsigned int (saturate). */ -inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsigned int __b) { +static inline vector unsigned int vec_sumsu(vector unsigned int __a, vector unsigned int __b) { __b = vec_sld(__a, __a, 8); __b = vec_add(__b, __a); __a = vec_sld(__b, __b, 4); From af4dfa188f4f2dd70fa72f32878f0d39380bd4e0 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Sat, 29 Jan 2022 00:49:14 +0200 Subject: [PATCH 230/798] [PowerPC] Default CPU to 7400 to enable VMX support in qemu-ppc --- cmake/toolchain-powerpc.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/toolchain-powerpc.cmake b/cmake/toolchain-powerpc.cmake index 4f7f8e92f5..b1627b8696 100644 --- a/cmake/toolchain-powerpc.cmake +++ b/cmake/toolchain-powerpc.cmake @@ -6,7 +6,7 @@ set(CMAKE_C_COMPILER_TARGET "powerpc-linux-gnu") set(CMAKE_CXX_COMPILER_TARGET "powerpc-linux-gnu") set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc -L /usr/${CMAKE_C_COMPILER_TARGET}/) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc -cpu 7400 -L /usr/${CMAKE_C_COMPILER_TARGET}/) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) From 4526c3379349041f718b88c58654aa969da861a0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 23 Jan 2022 13:48:45 -0800 Subject: [PATCH 231/798] Update CMake toolchains for alternative gcc/gcc++ names. Remove compiler attribute in GHA when using CMake toolchain files. --- .github/workflows/cmake.yml | 29 ++++++----------------------- .github/workflows/pigz.yml | 1 - .github/workflows/pkgcheck.yml | 2 +- cmake/toolchain-aarch64.cmake | 6 +++--- cmake/toolchain-arm.cmake | 15 +++++++++++---- cmake/toolchain-armhf.cmake | 27 +++++++++++++++++++++++++++ cmake/toolchain-mingw-i686.cmake | 21 +++++++++++++++++---- cmake/toolchain-mingw-x86_64.cmake | 21 +++++++++++++++++---- cmake/toolchain-powerpc.cmake | 10 +++++----- cmake/toolchain-powerpc64.cmake | 10 +++++----- cmake/toolchain-powerpc64le.cmake | 10 +++++----- cmake/toolchain-s390x.cmake | 10 +++++----- cmake/toolchain-sparc64.cmake | 10 +++++----- 13 files changed, 107 insertions(+), 65 deletions(-) create mode 100644 cmake/toolchain-armhf.cmake diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 918be18b33..2d00c71349 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -102,8 +102,7 @@ jobs: - name: Ubuntu GCC ARM SF os: ubuntu-latest - compiler: arm-linux-gnueabi-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi -DWITH_SANITIZER=Address + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross qemu-run: qemu-arm @@ -111,8 +110,7 @@ jobs: - name: Ubuntu GCC ARM SF Compat No Opt os: ubuntu-latest - compiler: arm-linux-gnueabi-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross qemu-run: qemu-arm @@ -120,8 +118,7 @@ jobs: - name: Ubuntu GCC ARM HF os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_SANITIZER=Address + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross qemu-run: qemu-arm @@ -129,8 +126,7 @@ jobs: - name: Ubuntu GCC ARM HF No ACLE os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_ACLE=OFF -DWITH_SANITIZER=Address + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross qemu-run: qemu-arm @@ -138,8 +134,7 @@ jobs: - name: Ubuntu GCC ARM HF No NEON os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DWITH_NEON=OFF -DWITH_SANITIZER=Address + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross qemu-run: qemu-arm @@ -147,8 +142,7 @@ jobs: - name: Ubuntu GCC ARM HF Compat No Opt os: ubuntu-latest - compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross qemu-run: qemu-arm @@ -156,7 +150,6 @@ jobs: - name: Ubuntu GCC AARCH64 os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross @@ -165,7 +158,6 @@ jobs: - name: Ubuntu GCC AARCH64 No ACLE os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross @@ -174,7 +166,6 @@ jobs: - name: Ubuntu GCC AARCH64 No NEON os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross @@ -183,7 +174,6 @@ jobs: - name: Ubuntu GCC AARCH64 Compat No Opt os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross @@ -192,7 +182,6 @@ jobs: - name: Ubuntu GCC PPC os: ubuntu-latest - compiler: powerpc-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross @@ -202,7 +191,6 @@ jobs: - name: Ubuntu GCC PPC No Power8 os: ubuntu-latest - compiler: powerpc-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake -DWITH_POWER8=OFF asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross @@ -211,7 +199,6 @@ jobs: - name: Ubuntu GCC PPC64 os: ubuntu-latest - compiler: powerpc64-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc64-linux-gnu libc-dev-ppc64-cross @@ -221,7 +208,6 @@ jobs: - name: Ubuntu GCC PPC64LE os: ubuntu-latest - compiler: powerpc64le-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc64le-linux-gnu libc-dev-ppc64el-cross @@ -230,7 +216,6 @@ jobs: - name: Ubuntu GCC SPARC64 os: ubuntu-latest - compiler: sparc64-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-sparc64-linux-gnu libc-dev-sparc64-cross @@ -240,7 +225,6 @@ jobs: - name: Ubuntu GCC S390X os: ubuntu-latest - compiler: s390x-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross @@ -250,7 +234,6 @@ jobs: - name: Ubuntu GCC S390X No vectorized CRC32 os: ubuntu-latest - compiler: s390x-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_CRC32_VX=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 153a7ac5f4..7ffe845b6d 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -45,7 +45,6 @@ jobs: - name: Ubuntu GCC AARCH64 os: ubuntu-latest - compiler: aarch64-linux-gnu-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=../../cmake/toolchain-aarch64.cmake packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross qemu-run: qemu-aarch64 diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index fa9dbdfa11..8f3338abff 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -24,7 +24,7 @@ jobs: os: ubuntu-latest chost: arm-linux-gnueabihf compiler: arm-linux-gnueabihf-gcc - cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabihf + cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake packages: qemu gcc-arm-linux-gnueabihf libc6-dev-armhf-cross - name: Ubuntu GCC AARCH64 diff --git a/cmake/toolchain-aarch64.cmake b/cmake/toolchain-aarch64.cmake index 31894fdcd5..0bb190398f 100644 --- a/cmake/toolchain-aarch64.cmake +++ b/cmake/toolchain-aarch64.cmake @@ -14,13 +14,13 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() diff --git a/cmake/toolchain-arm.cmake b/cmake/toolchain-arm.cmake index 0e3c5c377e..84cd3e575e 100644 --- a/cmake/toolchain-arm.cmake +++ b/cmake/toolchain-arm.cmake @@ -2,7 +2,14 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_SYSTEM_VERSION 1) -message(STATUS "Using cross-compile toolchain: ${CMAKE_C_COMPILER_TARGET}") +message(STATUS "Using cross-compile toolchain: ${CROSS_COMPILE_TOOLCHAIN}") + +if(NOT DEFINED CMAKE_C_COMPILER_TARGET) + set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabi) +endif() +if(NOT DEFINED CMAKE_CXX_COMPILER_TARGET) + set(CMAKE_CXX_COMPILER_TARGET arm-linux-gnueabi) +endif() set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR qemu-arm -L /usr/${CMAKE_C_COMPILER_TARGET}/) @@ -12,13 +19,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() diff --git a/cmake/toolchain-armhf.cmake b/cmake/toolchain-armhf.cmake new file mode 100644 index 0000000000..85db326720 --- /dev/null +++ b/cmake/toolchain-armhf.cmake @@ -0,0 +1,27 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(CMAKE_SYSTEM_VERSION 1) + +message(STATUS "Using cross-compile toolchain: ${CROSS_COMPILE_TOOLCHAIN}") + +set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf) +set(CMAKE_CXX_COMPILER_TARGET arm-linux-gnueabihf) + +set(CMAKE_CROSSCOMPILING TRUE) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-arm -L /usr/${CMAKE_C_COMPILER_TARGET}/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() diff --git a/cmake/toolchain-mingw-i686.cmake b/cmake/toolchain-mingw-i686.cmake index 588ec0ef9c..07ae63ce74 100644 --- a/cmake/toolchain-mingw-i686.cmake +++ b/cmake/toolchain-mingw-i686.cmake @@ -2,10 +2,7 @@ set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_C_COMPILER_TARGET i686) set(CMAKE_CXX_COMPILER_TARGET i686) - -set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) -set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) -set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) +set(CMAKE_RC_COMPILER_TARGET i686) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR wine) @@ -14,3 +11,19 @@ set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH NAMES ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() + +find_program(RC_COMPILER_FULL_PATH NAMES ${CMAKE_RC_COMPILER_TARGET}-w64-mingw32-windres) +if(RC_COMPILER_FULL_PATH) + set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) +endif() diff --git a/cmake/toolchain-mingw-x86_64.cmake b/cmake/toolchain-mingw-x86_64.cmake index c778b72227..aa597da333 100644 --- a/cmake/toolchain-mingw-x86_64.cmake +++ b/cmake/toolchain-mingw-x86_64.cmake @@ -2,10 +2,7 @@ set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_C_COMPILER_TARGET x86_64) set(CMAKE_CXX_COMPILER_TARGET x86_64) - -set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) -set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) -set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) +set(CMAKE_RC_COMPILER_TARGET x86_64) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR wine) @@ -14,3 +11,19 @@ set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc) +if(NOT C_COMPILER_FULL_PATH) + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") +endif() +set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) + +find_program(CXX_COMPILER_FULL_PATH NAMES ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) +if(CXX_COMPILER_FULL_PATH) + set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) +endif() + +find_program(RC_COMPILER_FULL_PATH NAMES ${CMAKE_RC_COMPILER_TARGET}-w64-mingw32-windres) +if(RC_COMPILER_FULL_PATH) + set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) +endif() diff --git a/cmake/toolchain-powerpc.cmake b/cmake/toolchain-powerpc.cmake index b1627b8696..f09713370d 100644 --- a/cmake/toolchain-powerpc.cmake +++ b/cmake/toolchain-powerpc.cmake @@ -2,8 +2,8 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR powerpc) set(CMAKE_SYSTEM_VERSION 1) -set(CMAKE_C_COMPILER_TARGET "powerpc-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "powerpc-linux-gnu") +set(CMAKE_C_COMPILER_TARGET powerpc-linux-gnu) +set(CMAKE_CXX_COMPILER_TARGET powerpc-linux-gnu) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc -cpu 7400 -L /usr/${CMAKE_C_COMPILER_TARGET}/) @@ -13,13 +13,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() diff --git a/cmake/toolchain-powerpc64.cmake b/cmake/toolchain-powerpc64.cmake index 4be3bbd59c..42a5a44b7d 100644 --- a/cmake/toolchain-powerpc64.cmake +++ b/cmake/toolchain-powerpc64.cmake @@ -2,8 +2,8 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR ppc64) set(CMAKE_SYSTEM_VERSION 1) -set(CMAKE_C_COMPILER_TARGET "powerpc64-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "powerpc64-linux-gnu") +set(CMAKE_C_COMPILER_TARGET powerpc64-linux-gnu) +set(CMAKE_CXX_COMPILER_TARGET powerpc64-linux-gnu) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64 -L /usr/${CMAKE_C_COMPILER_TARGET}/) @@ -13,13 +13,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() diff --git a/cmake/toolchain-powerpc64le.cmake b/cmake/toolchain-powerpc64le.cmake index 5535f616f6..bb6391a481 100644 --- a/cmake/toolchain-powerpc64le.cmake +++ b/cmake/toolchain-powerpc64le.cmake @@ -2,8 +2,8 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR ppc64le) set(CMAKE_SYSTEM_VERSION 1) -set(CMAKE_C_COMPILER_TARGET "powerpc64le-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "powerpc64le-linux-gnu") +set(CMAKE_C_COMPILER_TARGET powerpc64le-linux-gnu) +set(CMAKE_CXX_COMPILER_TARGET powerpc64le-linux-gnu) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64le -L /usr/${CMAKE_C_COMPILER_TARGET}/) @@ -13,13 +13,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() diff --git a/cmake/toolchain-s390x.cmake b/cmake/toolchain-s390x.cmake index 41bc0d1011..9455a2bedb 100644 --- a/cmake/toolchain-s390x.cmake +++ b/cmake/toolchain-s390x.cmake @@ -2,8 +2,8 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR s390x) set(CMAKE_SYSTEM_VERSION 1) -set(CMAKE_C_COMPILER_TARGET "s390x-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "s390x-linux-gnu") +set(CMAKE_C_COMPILER_TARGET s390x-linux-gnu) +set(CMAKE_CXX_COMPILER_TARGET s390x-linux-gnu) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR qemu-s390x -L /usr/${CMAKE_C_COMPILER_TARGET}/) @@ -13,13 +13,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() diff --git a/cmake/toolchain-sparc64.cmake b/cmake/toolchain-sparc64.cmake index f0cd99565e..16161a78c0 100644 --- a/cmake/toolchain-sparc64.cmake +++ b/cmake/toolchain-sparc64.cmake @@ -2,8 +2,8 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR sparc64) set(CMAKE_SYSTEM_VERSION 1) -set(CMAKE_C_COMPILER_TARGET "sparc64-linux-gnu") -set(CMAKE_CXX_COMPILER_TARGET "sparc64-linux-gnu") +set(CMAKE_C_COMPILER_TARGET sparc64-linux-gnu) +set(CMAKE_CXX_COMPILER_TARGET sparc64-linux-gnu) set(CMAKE_CROSSCOMPILING TRUE) set(CMAKE_CROSSCOMPILING_EMULATOR qemu-sparc64 -L /usr/${CMAKE_C_COMPILER_TARGET}/) @@ -13,13 +13,13 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -find_program(C_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-gcc) +find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-gcc) if(NOT C_COMPILER_FULL_PATH) - message(FATAL_ERROR "Cross-compiler ${CMAKE_C_COMPILER_TARGET}-gcc not found") + message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH ${CMAKE_C_COMPILER_TARGET}-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES g++-${CMAKE_CXX_COMPILER_TARGET} ${CMAKE_CXX_COMPILER_TARGET}-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() From c78eaee79670b68e2aaee247522c3a0100f97d30 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 23 Jan 2022 13:26:36 -0800 Subject: [PATCH 232/798] Use add_link_options in cmake code coverage detection. --- cmake/detect-coverage.cmake | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake/detect-coverage.cmake b/cmake/detect-coverage.cmake index 96478f6771..ba5e8af948 100644 --- a/cmake/detect-coverage.cmake +++ b/cmake/detect-coverage.cmake @@ -14,8 +14,7 @@ macro(add_code_coverage) if(HAVE_COVERAGE) set(CMAKE_C_FLAGS "-O0 ${CMAKE_C_FLAGS} -coverage") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -coverage") + add_link_options(-coverage) else() # Some versions of GCC don't support -coverage shorthand if(CMAKE_VERSION VERSION_LESS 3.14) @@ -29,8 +28,7 @@ macro(add_code_coverage) if(HAVE_TEST_COVERAGE) set(CMAKE_C_FLAGS "-O0 ${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs -fprofile-values") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov -fprofile-arcs") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -lgcov -fprofile-arcs") + add_link_options(-lgcov -fprofile-arcs) else() message(WARNING "Compiler does not support code coverage") endif() From 882d3be4952217109b118b6c37d0819f690063b6 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 25 Jan 2022 17:49:45 -0800 Subject: [PATCH 233/798] Use add_link_options in cmake sanitizer detection. --- cmake/detect-sanitizer.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmake/detect-sanitizer.cmake b/cmake/detect-sanitizer.cmake index b0a0236e83..93b437454d 100644 --- a/cmake/detect-sanitizer.cmake +++ b/cmake/detect-sanitizer.cmake @@ -14,7 +14,7 @@ macro(check_sanitizer_support known_checks supported_checks) set(compile_checks "${available_checks},${check}") endif() - set(CMAKE_REQUIRED_FLAGS "-fsanitize=${compile_checks}") + set(CMAKE_REQUIRED_FLAGS -fsanitize=${compile_checks}) check_c_source_compiles("int main() { return 0; }" HAS_SANITIZER_${check} FAIL_REGEX "not supported|unrecognized command|unknown option") @@ -40,6 +40,7 @@ macro(add_address_sanitizer) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Address sanitizer is enabled: ${supported_checks}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_link_options(-fsanitize=${supported_checks}) else() message(STATUS "Address sanitizer is not supported") endif() @@ -53,6 +54,7 @@ macro(add_address_sanitizer) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Leak sanitizer is enabled: ${supported_checks}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_link_options(-fsanitize=${supported_checks}) else() message(STATUS "Leak sanitizer is not supported") endif() @@ -64,6 +66,7 @@ macro(add_memory_sanitizer) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Memory sanitizer is enabled: ${supported_checks}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_link_options(-fsanitize=${supported_checks}) else() message(STATUS "Memory sanitizer is not supported") endif() @@ -74,6 +77,7 @@ macro(add_thread_sanitizer) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Thread sanitizer is enabled: ${supported_checks}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_link_options(-fsanitize=${supported_checks}) else() message(STATUS "Thread sanitizer is not supported") endif() @@ -121,6 +125,7 @@ macro(add_undefined_sanitizer) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Undefined behavior sanitizer is enabled: ${supported_checks}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_link_options(-fsanitize=${supported_checks}) # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if # it is not in our sanitize flag list, so we need to explicitly disable alignment sanitizing. From 24291edbd6d25c225bb8d76787ad9737803d0b6f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 25 Jan 2022 17:56:12 -0800 Subject: [PATCH 234/798] Use add_compile_options in cmake which sets both C and CXX flags. It is necessary to break apart strings that contain multiple flags so they are processed by add_compile_options properly. --- CMakeLists.txt | 56 ++++++++++++++++++------------------ cmake/detect-coverage.cmake | 12 ++++++-- cmake/detect-sanitizer.cmake | 12 ++++---- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 72d4341655..b9de19a755 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -153,14 +153,14 @@ endif() if(CMAKE_C_COMPILER_ID MATCHES "^Intel") if(CMAKE_HOST_UNIX) - set(WARNFLAGS "-Wall") - set(WARNFLAGS_MAINTAINER "-Wall -Wcheck -Wremarks") - set(WARNFLAGS_DISABLE "") + set(WARNFLAGS -Wall) + set(WARNFLAGS_MAINTAINER -Wall -Wcheck -Wremarks) + set(WARNFLAGS_DISABLE) else() - set(WARNFLAGS "/Wall") - set(WARNFLAGS_MAINTAINER "/W5") - set(WARNFLAGS_DISABLE "") - endif() + set(WARNFLAGS /Wall) + set(WARNFLAGS_MAINTAINER /W5) + set(WARNFLAGS_DISABLE) + endif() if(WITH_NATIVE_INSTRUCTIONS) message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration") set(WITH_NATIVE_INSTRUCTIONS OFF) @@ -175,9 +175,9 @@ elseif(MSVC) # (who'd use cmake from an IDE...) but checking for ICC before checking for MSVC should # avoid mistakes. # /Oi ? - set(WARNFLAGS "/W3") - set(WARNFLAGS_MAINTAINER "/W4") - set(WARNFLAGS_DISABLE "") + set(WARNFLAGS /W3) + set(WARNFLAGS_MAINTAINER /W4) + set(WARNFLAGS_DISABLE) if(BASEARCH_ARM_FOUND) add_definitions(-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE) if(NOT "${ARCH}" MATCHES "aarch64") @@ -190,9 +190,9 @@ elseif(MSVC) endif() elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") # Enable warnings in GCC and Clang - set(WARNFLAGS "-Wall") - set(WARNFLAGS_MAINTAINER "-Wextra -Wpedantic") - set(WARNFLAGS_DISABLE "-Wno-implicit-fallthrough") + set(WARNFLAGS -Wall) + set(WARNFLAGS_MAINTAINER -Wextra -Wpedantic) + set(WARNFLAGS_DISABLE -Wno-implicit-fallthrough) if(WITH_NATIVE_INSTRUCTIONS) if(BASEARCH_PPC_FOUND) set(NATIVEFLAG "-mcpu=native") @@ -203,27 +203,27 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(BASEARCH_ARM_FOUND) if("${ARCH}" MATCHES "arm" AND NOT CMAKE_C_FLAGS MATCHES "-mfloat-abi") # Auto-detect support for ARM floating point ABI - set(CMAKE_REQUIRED_FLAGS "-mfloat-abi=softfp") + set(CMAKE_REQUIRED_FLAGS -mfloat-abi=softfp) check_c_source_compiles( "#include int main() { return 0; }" HAVE_FLOATABI_SOFTFP) if(HAVE_FLOATABI_SOFTFP) - set(FLOATABI "-mfloat-abi=softfp") + set(FLOATABI -mfloat-abi=softfp) else() - set(CMAKE_REQUIRED_FLAGS "-mfloat-abi=hard") + set(CMAKE_REQUIRED_FLAGS -mfloat-abi=hard) check_c_source_compiles( "#include int main() { return 0; }" HAVE_FLOATABI_HARD) if(HAVE_FLOATABI_HARD) - set(FLOATABI "-mfloat-abi=hard") + set(FLOATABI -mfloat-abi=hard) endif() endif() set(CMAKE_REQUIRED_FLAGS) if(FLOATABI) message(STATUS "ARM floating point arch: ${FLOATABI}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${FLOATABI}") + add_compile_options(${FLOATABI}) else() message(STATUS "ARM floating point arch not auto-detected") endif() @@ -246,12 +246,6 @@ else() endif() endif() -# Replace optimization level 3 added by default with level 2 -if(NOT MSVC AND NOT CMAKE_C_FLAGS MATCHES "([\\/\\-]O)3") - string(REGEX REPLACE "([\\/\\-]O)3" "\\12" - CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") -endif() - # Set architecture alignment requirements if(WITH_UNALIGNED) if((BASEARCH_ARM_FOUND AND NOT "${ARCH}" MATCHES "armv[2-7]") OR (BASEARCH_PPC_FOUND AND "${ARCH}" MATCHES "powerpc64le") OR BASEARCH_X86_FOUND) @@ -294,9 +288,9 @@ endif() # Apply warning compiler flags if(WITH_MAINTAINER_WARNINGS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNFLAGS} ${WARNFLAGS_MAINTAINER} ${WARNFLAGS_DISABLE}") + add_compile_options(${WARNFLAGS} ${WARNFLAGS_MAINTAINER} ${WARNFLAGS_DISABLE}) else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNFLAGS} ${WARNFLAGS_DISABLE}") + add_compile_options(${WARNFLAGS} ${WARNFLAGS_DISABLE}) endif() # Set code coverage compiler flags @@ -304,10 +298,16 @@ if(WITH_CODE_COVERAGE) add_code_coverage() endif() +# Replace optimization level 3 added by default with level 2 +if(NOT WITH_CODE_COVERAGE AND NOT MSVC AND NOT CMAKE_C_FLAGS MATCHES "([\\/\\-]O)3") + string(REGEX REPLACE "([\\/\\-]O)3" "\\12" + CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") +endif() + # Set native instruction set compiler flag if(WITH_NATIVE_INSTRUCTIONS AND DEFINED NATIVEFLAG) # Apply flag to all source files and compilation checks - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NATIVEFLAG}") + add_compile_options(${NATIVEFLAG}) endif() # @@ -465,7 +465,7 @@ macro(check_c_source_compile_or_run source flag) endif() endmacro() -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DZLIB_DEBUG") +add_compile_options($<$:-DZLIB_DEBUG>) if(MSVC) set(CMAKE_DEBUG_POSTFIX "d") diff --git a/cmake/detect-coverage.cmake b/cmake/detect-coverage.cmake index ba5e8af948..8688716c44 100644 --- a/cmake/detect-coverage.cmake +++ b/cmake/detect-coverage.cmake @@ -13,7 +13,7 @@ macro(add_code_coverage) set(CMAKE_REQUIRED_LINK_OPTIONS) if(HAVE_COVERAGE) - set(CMAKE_C_FLAGS "-O0 ${CMAKE_C_FLAGS} -coverage") + add_compile_options(-coverage) add_link_options(-coverage) else() # Some versions of GCC don't support -coverage shorthand @@ -27,10 +27,18 @@ macro(add_code_coverage) set(CMAKE_REQUIRED_LINK_OPTIONS) if(HAVE_TEST_COVERAGE) - set(CMAKE_C_FLAGS "-O0 ${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs -fprofile-values") + add_compile_options(-ftest-coverage -fprofile-arcs -fprofile-values) add_link_options(-lgcov -fprofile-arcs) else() message(WARNING "Compiler does not support code coverage") + set(WITH_CODE_COVERAGE OFF) endif() endif() + + # Set optimization level to zero for code coverage builds + if (WITH_CODE_COVERAGE) + # Use CMake compiler flag variables due to add_compile_options failure on Windows GCC + set(CMAKE_C_FLAGS "-O0 ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "-O0 ${CMAKE_CXX_FLAGS}") + endif() endmacro() diff --git a/cmake/detect-sanitizer.cmake b/cmake/detect-sanitizer.cmake index 93b437454d..344427c44f 100644 --- a/cmake/detect-sanitizer.cmake +++ b/cmake/detect-sanitizer.cmake @@ -39,7 +39,7 @@ macro(add_address_sanitizer) check_sanitizer_support("${known_checks}" supported_checks) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Address sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) else() message(STATUS "Address sanitizer is not supported") @@ -53,7 +53,7 @@ macro(add_address_sanitizer) check_sanitizer_support("leak" supported_checks) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Leak sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) else() message(STATUS "Leak sanitizer is not supported") @@ -65,7 +65,7 @@ macro(add_memory_sanitizer) check_sanitizer_support("memory" supported_checks) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Memory sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) else() message(STATUS "Memory sanitizer is not supported") @@ -76,7 +76,7 @@ macro(add_thread_sanitizer) check_sanitizer_support("thread" supported_checks) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Thread sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) else() message(STATUS "Thread sanitizer is not supported") @@ -124,13 +124,13 @@ macro(add_undefined_sanitizer) if(NOT ${supported_checks} STREQUAL "") message(STATUS "Undefined behavior sanitizer is enabled: ${supported_checks}") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=${supported_checks}") + add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if # it is not in our sanitize flag list, so we need to explicitly disable alignment sanitizing. if(UNALIGNED_OK) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=alignment") + add_compile_options(-fno-sanitize=alignment) endif() else() message(STATUS "UNdefined behavior sanitizer is not supported") From 8927b8553d2e3fd89582d1a9f91f0d24f4ce736d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 23 Jan 2022 19:53:22 -0800 Subject: [PATCH 235/798] Added fallback macros for add_compile_options and add_link_options. --- CMakeLists.txt | 1 + cmake/fallback-macros.cmake | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 cmake/fallback-macros.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index b9de19a755..dfdc98bbb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ include(cmake/detect-install-dirs.cmake) include(cmake/detect-coverage.cmake) include(cmake/detect-intrinsics.cmake) include(cmake/detect-sanitizer.cmake) +include(cmake/fallback-macros.cmake) if(CMAKE_TOOLCHAIN_FILE) message(STATUS "Using CMake toolchain: ${CMAKE_TOOLCHAIN_FILE}") diff --git a/cmake/fallback-macros.cmake b/cmake/fallback-macros.cmake new file mode 100644 index 0000000000..8bc6cf25be --- /dev/null +++ b/cmake/fallback-macros.cmake @@ -0,0 +1,19 @@ +# fallback-macros.cmake -- CMake fallback macros +# Copyright (C) 2022 Nathan Moinvaziri +# Licensed under the Zlib license, see LICENSE.md for details + +# CMake less than version 3.5.2 +if(NOT COMMAND add_compile_options) + macro(add_compile_options options) + string(APPEND CMAKE_C_FLAGS ${options}) + string(APPEND CMAKE_CXX_FLAGS ${options}) + endmacro() +endif() + +# CMake less than version 3.14 +if(NOT COMMAND add_link_options) + macro(add_link_options options) + string(APPEND CMAKE_EXE_LINKER_FLAGS ${options}) + string(APPEND CMAKE_SHARED_LINKER_FLAGS ${options}) + endmacro() +endif() From 6a553e01290c1ef8cea5f6cb6701b3e25ff82a96 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 24 Jan 2022 21:28:13 -0800 Subject: [PATCH 236/798] Use NATIVEFLAG in intrinsic checks that is added whenever it is enabled. --- cmake/detect-intrinsics.cmake | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 515135ebfc..cc1ffa51c1 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -6,7 +6,7 @@ macro(check_acle_intrinsics) set(ACLEFLAG "-march=armv8-a+crc") endif() # Check whether compiler supports ACLE flag - set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG}") + set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG}") check_c_source_compiles( "int main() { return 0; }" HAVE_ACLE_INTRIN FAIL_REGEX "not supported") @@ -30,7 +30,7 @@ macro(check_avx512_intrinsics) set(AVX512FLAG "/ARCH:AVX512") endif() # Check whether compiler supports AVX512 intrinsics - set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG}") + set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include int main(void) { @@ -76,7 +76,7 @@ macro(check_avx512vnni_intrinsics) endif() # Check whether compiler supports AVX512vnni intrinsics - set(CMAKE_REQUIRED_FLAGS "${AVX512VNNIFLAG}") + set(CMAKE_REQUIRED_FLAGS "${AVX512VNNIFLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include int main(void) { @@ -108,7 +108,7 @@ macro(check_avx2_intrinsics) endif() endif() # Check whether compiler supports AVX2 intrinics - set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG}") + set(CMAKE_REQUIRED_FLAGS "${AVX2FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include int main(void) { @@ -134,7 +134,7 @@ macro(check_neon_intrinsics) endif() endif() # Check whether compiler supports NEON flag - set(CMAKE_REQUIRED_FLAGS "${NEONFLAG}") + set(CMAKE_REQUIRED_FLAGS "${NEONFLAG} ${NATIVEFLAG}") check_c_source_compiles( "int main() { return 0; }" MFPU_NEON_AVAILABLE FAIL_REGEX "not supported") @@ -150,7 +150,7 @@ macro(check_pclmulqdq_intrinsics) # Check whether compiler supports PCLMULQDQ intrinsics if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) # The pclmul code currently crashes on Mac in 32bit mode. Avoid for now. - set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG}") + set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include int main(void) { @@ -176,7 +176,7 @@ macro(check_vpclmulqdq_intrinsics) endif() # Check whether compiler supports VPCLMULQDQ intrinsics if(NOT (APPLE AND "${ARCH}" MATCHES "i386")) - set(CMAKE_REQUIRED_FLAGS "${VPCLMULFLAG}") + set(CMAKE_REQUIRED_FLAGS "${VPCLMULFLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include int main(void) { @@ -233,7 +233,7 @@ macro(check_ppc_intrinsics) endif() # Check if we have what we need for AltiVec optimizations - set(CMAKE_REQUIRED_FLAGS "${PPCFLAGS}") + set(CMAKE_REQUIRED_FLAGS "${PPCFLAGS} ${NATIVEFLAG}") check_c_source_compiles( "#include int main() { @@ -251,7 +251,7 @@ macro(check_power8_intrinsics) endif() endif() # Check if we have what we need for POWER8 optimizations - set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG}") + set(CMAKE_REQUIRED_FLAGS "${POWER8FLAG} ${NATIVEFLAG}") check_c_source_compiles( "#include int main() { @@ -279,7 +279,7 @@ macro(check_sse2_intrinsics) endif() endif() # Check whether compiler supports SSE2 instrinics - set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG}") + set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include int main(void) { @@ -305,7 +305,7 @@ macro(check_ssse3_intrinsics) endif() endif() # Check whether compiler supports SSSE3 intrinsics - set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG}") + set(CMAKE_REQUIRED_FLAGS "${SSSE3FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include int main(void) { @@ -333,7 +333,7 @@ macro(check_sse41_intrinsics) endif() endif() # Check whether compiler supports SSE4.1 intrinsics - set(CMAKE_REQUIRED_FLAGS "${SSE41FLAG}") + set(CMAKE_REQUIRED_FLAGS "${SSE41FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "#include int main(void) { @@ -361,7 +361,7 @@ macro(check_sse42_intrinsics) endif() endif() # Check whether compiler supports SSE4 CRC inline asm - set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG}") + set(CMAKE_REQUIRED_FLAGS "${SSE42FLAG} ${NATIVEFLAG}") check_c_source_compile_or_run( "int main(void) { unsigned val = 0, h = 0; @@ -417,7 +417,7 @@ macro(check_vgfma_intrinsics) endif() endif() # Check whether compiler supports "VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE" intrinsic - set(CMAKE_REQUIRED_FLAGS "${VGFMAFLAG}") + set(CMAKE_REQUIRED_FLAGS "${VGFMAFLAG} ${NATIVEFLAG}") check_c_source_compiles( "#include int main(void) { From 1f8eef39dcdead302a4e2f67384962d6aed1661b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 25 Jan 2022 15:28:56 -0800 Subject: [PATCH 237/798] Added CMake status message when code coverage is enabled. --- cmake/detect-coverage.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/detect-coverage.cmake b/cmake/detect-coverage.cmake index 8688716c44..8e67a085cd 100644 --- a/cmake/detect-coverage.cmake +++ b/cmake/detect-coverage.cmake @@ -15,6 +15,7 @@ macro(add_code_coverage) if(HAVE_COVERAGE) add_compile_options(-coverage) add_link_options(-coverage) + message(STATUS "Code coverage enabled using: -coverage") else() # Some versions of GCC don't support -coverage shorthand if(CMAKE_VERSION VERSION_LESS 3.14) @@ -29,6 +30,7 @@ macro(add_code_coverage) if(HAVE_TEST_COVERAGE) add_compile_options(-ftest-coverage -fprofile-arcs -fprofile-values) add_link_options(-lgcov -fprofile-arcs) + message(STATUS "Code coverage enabled using: -ftest-coverage") else() message(WARNING "Compiler does not support code coverage") set(WITH_CODE_COVERAGE OFF) From 6d01d437fd770bf39b21e66f8eb1b8d41f0c6654 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 09:57:24 -0800 Subject: [PATCH 238/798] Move build basics to zbuild.h. --- zbuild.h | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ zutil.h | 128 +------------------------------------------------------ 2 files changed, 129 insertions(+), 127 deletions(-) diff --git a/zbuild.h b/zbuild.h index dc90e11038..9430ba34f2 100644 --- a/zbuild.h +++ b/zbuild.h @@ -1,6 +1,11 @@ #ifndef _ZBUILD_H #define _ZBUILD_H +#include +#include +#include +#include + /* Determine compiler version of C Standard */ #ifdef __STDC_VERSION__ # if __STDC_VERSION__ >= 199901L @@ -38,6 +43,12 @@ # endif #endif +/* MS Visual Studio does not allow inline in C, only C++. + But it provides __inline instead, so use that. */ +#if defined(_MSC_VER) && !defined(inline) && !defined(__cplusplus) +# define inline __inline +#endif + #if defined(ZLIB_COMPAT) # define PREFIX(x) x # define PREFIX2(x) ZLIB_ ## x @@ -61,4 +72,121 @@ /* Ignore unused variable warning */ #define Z_UNUSED(var) (void)(var) +#if defined(HAVE_VISIBILITY_INTERNAL) +# define Z_INTERNAL __attribute__((visibility ("internal"))) +#elif defined(HAVE_VISIBILITY_HIDDEN) +# define Z_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define Z_INTERNAL +#endif + +#ifndef __cplusplus +# define Z_REGISTER register +#else +# define Z_REGISTER +#endif + +/* Reverse the bytes in a value. Use compiler intrinsics when + possible to take advantage of hardware implementations. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1300) +# include +# pragma intrinsic(_byteswap_ulong) +# define ZSWAP16(q) _byteswap_ushort(q) +# define ZSWAP32(q) _byteswap_ulong(q) +# define ZSWAP64(q) _byteswap_uint64(q) + +#elif defined(__Clang__) || (defined(__GNUC__) && \ + (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) +# define ZSWAP16(q) __builtin_bswap16(q) +# define ZSWAP32(q) __builtin_bswap32(q) +# define ZSWAP64(q) __builtin_bswap64(q) + +#elif defined(__GNUC__) && (__GNUC__ >= 2) && defined(__linux__) +# include +# define ZSWAP16(q) bswap_16(q) +# define ZSWAP32(q) bswap_32(q) +# define ZSWAP64(q) bswap_64(q) + +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) +# include +# define ZSWAP16(q) bswap16(q) +# define ZSWAP32(q) bswap32(q) +# define ZSWAP64(q) bswap64(q) +#elif defined(__OpenBSD__) +# include +# define ZSWAP16(q) swap16(q) +# define ZSWAP32(q) swap32(q) +# define ZSWAP64(q) swap64(q) +#elif defined(__INTEL_COMPILER) +/* ICC does not provide a two byte swap. */ +# define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) +# define ZSWAP32(q) _bswap(q) +# define ZSWAP64(q) _bswap64(q) + +#else +# define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) +# define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) +# define ZSWAP64(q) \ + (((q & 0xFF00000000000000u) >> 56u) | \ + ((q & 0x00FF000000000000u) >> 40u) | \ + ((q & 0x0000FF0000000000u) >> 24u) | \ + ((q & 0x000000FF00000000u) >> 8u) | \ + ((q & 0x00000000FF000000u) << 8u) | \ + ((q & 0x0000000000FF0000u) << 24u) | \ + ((q & 0x000000000000FF00u) << 40u) | \ + ((q & 0x00000000000000FFu) << 56u)) +#endif + +/* Only enable likely/unlikely if the compiler is known to support it */ +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__INTEL_COMPILER) || defined(__Clang__) +# define LIKELY_NULL(x) __builtin_expect((x) != 0, 0) +# define LIKELY(x) __builtin_expect(!!(x), 1) +# define UNLIKELY(x) __builtin_expect(!!(x), 0) +# define PREFETCH_L1(addr) __builtin_prefetch(addr, 0, 3) +# define PREFETCH_L2(addr) __builtin_prefetch(addr, 0, 2) +# define PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 2) +#elif defined(__WIN__) +# include +# define LIKELY_NULL(x) x +# define LIKELY(x) x +# define UNLIKELY(x) x +# define PREFETCH_L1(addr) _mm_prefetch((char *) addr, _MM_HINT_T0) +# define PREFETCH_L2(addr) _mm_prefetch((char *) addr, _MM_HINT_T1) +# define PREFETCH_RW(addr) _mm_prefetch((char *) addr, _MM_HINT_T1) +#else +# define LIKELY_NULL(x) x +# define LIKELY(x) x +# define UNLIKELY(x) x +# define PREFETCH_L1(addr) addr +# define PREFETCH_L2(addr) addr +# define PREFETCH_RW(addr) addr +#endif /* (un)likely */ + +#if defined(__clang__) || defined(__GNUC__) +# define ALIGNED_(x) __attribute__ ((aligned(x))) +#elif defined(_MSC_VER) +# define ALIGNED_(x) __declspec(align(x)) +#endif + +/* Diagnostic functions */ +#ifdef ZLIB_DEBUG +# include + extern int Z_INTERNAL z_verbose; + extern void Z_INTERNAL z_error(char *m); +# define Assert(cond, msg) {if (!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose >= 0) fprintf x;} +# define Tracev(x) {if (z_verbose > 0) fprintf x;} +# define Tracevv(x) {if (z_verbose > 1) fprintf x;} +# define Tracec(c, x) {if (z_verbose > 0 && (c)) fprintf x;} +# define Tracecv(c, x) {if (z_verbose > 1 && (c)) fprintf x;} +#else +# define Assert(cond, msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c, x) +# define Tracecv(c, x) +#endif + #endif diff --git a/zutil.h b/zutil.h index 6ab70e8a29..2a30c6d577 100644 --- a/zutil.h +++ b/zutil.h @@ -10,30 +10,12 @@ subject to change. Applications should only use zlib.h. */ -#if defined(HAVE_VISIBILITY_INTERNAL) -# define Z_INTERNAL __attribute__((visibility ("internal"))) -#elif defined(HAVE_VISIBILITY_HIDDEN) -# define Z_INTERNAL __attribute__((visibility ("hidden"))) -#else -# define Z_INTERNAL -#endif - -#ifndef __cplusplus -# define Z_REGISTER register -#else -# define Z_REGISTER -#endif - -#include -#include -#include -#include +#include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" #else # include "zlib-ng.h" #endif -#include "zbuild.h" typedef unsigned char uch; /* Included for compatibility with external code only */ typedef uint16_t ush; /* Included for compatibility with external code only */ @@ -130,12 +112,6 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ #ifdef __APPLE__ # define OS_CODE 19 -#endif - -/* MS Visual Studio does not allow inline in C, only C++. - But it provides __inline instead, so use that. */ -#if defined(_MSC_VER) && !defined(inline) && !defined(__cplusplus) -# define inline __inline #endif /* common defaults */ @@ -146,26 +122,6 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ /* functions */ -/* Diagnostic functions */ -#ifdef ZLIB_DEBUG -# include - extern int Z_INTERNAL z_verbose; - extern void Z_INTERNAL z_error(char *m); -# define Assert(cond, msg) {if (!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose >= 0) fprintf x;} -# define Tracev(x) {if (z_verbose > 0) fprintf x;} -# define Tracevv(x) {if (z_verbose > 1) fprintf x;} -# define Tracec(c, x) {if (z_verbose > 0 && (c)) fprintf x;} -# define Tracecv(c, x) {if (z_verbose > 1 && (c)) fprintf x;} -#else -# define Assert(cond, msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c, x) -# define Tracecv(c, x) -#endif - void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size); void Z_INTERNAL zng_cfree(void *opaque, void *ptr); @@ -173,86 +129,4 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr); #define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (void *)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} -/* Reverse the bytes in a value. Use compiler intrinsics when - possible to take advantage of hardware implementations. */ -#if defined(_MSC_VER) && (_MSC_VER >= 1300) -# pragma intrinsic(_byteswap_ulong) -# define ZSWAP16(q) _byteswap_ushort(q) -# define ZSWAP32(q) _byteswap_ulong(q) -# define ZSWAP64(q) _byteswap_uint64(q) - -#elif defined(__Clang__) || (defined(__GNUC__) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) -# define ZSWAP16(q) __builtin_bswap16(q) -# define ZSWAP32(q) __builtin_bswap32(q) -# define ZSWAP64(q) __builtin_bswap64(q) - -#elif defined(__GNUC__) && (__GNUC__ >= 2) && defined(__linux__) -# include -# define ZSWAP16(q) bswap_16(q) -# define ZSWAP32(q) bswap_32(q) -# define ZSWAP64(q) bswap_64(q) - -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -# include -# define ZSWAP16(q) bswap16(q) -# define ZSWAP32(q) bswap32(q) -# define ZSWAP64(q) bswap64(q) -#elif defined(__OpenBSD__) -# include -# define ZSWAP16(q) swap16(q) -# define ZSWAP32(q) swap32(q) -# define ZSWAP64(q) swap64(q) -#elif defined(__INTEL_COMPILER) -/* ICC does not provide a two byte swap. */ -# define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) -# define ZSWAP32(q) _bswap(q) -# define ZSWAP64(q) _bswap64(q) - -#else -# define ZSWAP16(q) ((((q) & 0xff) << 8) | (((q) & 0xff00) >> 8)) -# define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) -# define ZSWAP64(q) \ - (((q & 0xFF00000000000000u) >> 56u) | \ - ((q & 0x00FF000000000000u) >> 40u) | \ - ((q & 0x0000FF0000000000u) >> 24u) | \ - ((q & 0x000000FF00000000u) >> 8u) | \ - ((q & 0x00000000FF000000u) << 8u) | \ - ((q & 0x0000000000FF0000u) << 24u) | \ - ((q & 0x000000000000FF00u) << 40u) | \ - ((q & 0x00000000000000FFu) << 56u)) -#endif - -/* Only enable likely/unlikely if the compiler is known to support it */ -#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__INTEL_COMPILER) || defined(__Clang__) -# define LIKELY_NULL(x) __builtin_expect((x) != 0, 0) -# define LIKELY(x) __builtin_expect(!!(x), 1) -# define UNLIKELY(x) __builtin_expect(!!(x), 0) -# define PREFETCH_L1(addr) __builtin_prefetch(addr, 0, 3) -# define PREFETCH_L2(addr) __builtin_prefetch(addr, 0, 2) -# define PREFETCH_RW(addr) __builtin_prefetch(addr, 1, 2) -#elif defined(__WIN__) -# include -# define LIKELY_NULL(x) x -# define LIKELY(x) x -# define UNLIKELY(x) x -# define PREFETCH_L1(addr) _mm_prefetch((char *) addr, _MM_HINT_T0) -# define PREFETCH_L2(addr) _mm_prefetch((char *) addr, _MM_HINT_T1) -# define PREFETCH_RW(addr) _mm_prefetch((char *) addr, _MM_HINT_T1) -#else -# define LIKELY_NULL(x) x -# define LIKELY(x) x -# define UNLIKELY(x) x -# define PREFETCH_L1(addr) addr -# define PREFETCH_L2(addr) addr -# define PREFETCH_RW(addr) addr -#endif /* (un)likely */ - -#if defined(__clang__) || defined(__GNUC__) -# define ALIGNED_(x) __attribute__ ((aligned(x))) -#elif defined(_MSC_VER) -# define ALIGNED_(x) __declspec(align(x)) -#endif - #endif /* ZUTIL_H_ */ From ab0a6d9fa75c004fa8db569af5043504fdfad68f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 22 Jan 2022 10:52:12 -0800 Subject: [PATCH 239/798] Remove zutil.h includes from many files to prevent zlib.h being included. --- adler32.c | 1 - arch/x86/adler32_avx2.c | 2 -- arch/x86/adler32_avx512.c | 2 -- arch/x86/adler32_avx512_vnni.c | 2 -- arch/x86/adler32_sse41.c | 2 -- arch/x86/adler32_ssse3.c | 2 -- arch/x86/chunkset_avx.c | 1 - arch/x86/chunkset_sse2.c | 1 - arch/x86/compare256_avx2.c | 1 - arch/x86/compare256_sse42.c | 11 +++++------ arch/x86/crc32_fold_pclmulqdq.c | 2 +- arch/x86/crc32_fold_vpclmulqdq.c | 6 +++--- arch/x86/x86.c | 2 +- chunkset.c | 1 - chunkset_tpl.h | 2 ++ compare256.c | 2 -- crc32_fold.c | 1 - crc32_p.h | 2 +- test/benchmarks/benchmark_main.cc | 1 - uncompr.c | 1 - 20 files changed, 13 insertions(+), 32 deletions(-) diff --git a/adler32.c b/adler32.c index 499adbb60b..42e7b0fe25 100644 --- a/adler32.c +++ b/adler32.c @@ -4,7 +4,6 @@ */ #include "zbuild.h" -#include "zutil.h" #include "functable.h" #include "adler32_p.h" diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index 3d49a5b848..bd3547d0b1 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -6,8 +6,6 @@ */ #include "../../zbuild.h" -#include "../../zutil.h" - #include "../../adler32_p.h" #include "../../fallback_builtins.h" diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index d85f402a06..c6327167a5 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -7,8 +7,6 @@ */ #include "../../zbuild.h" -#include "../../zutil.h" - #include "../../adler32_p.h" #include "../../cpu_features.h" #include "../../fallback_builtins.h" diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index fd50b39a6b..ff0a9b580b 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -8,8 +8,6 @@ */ #include "../../zbuild.h" -#include "../../zutil.h" - #include "../../adler32_p.h" #include "../../cpu_features.h" #include "../../fallback_builtins.h" diff --git a/arch/x86/adler32_sse41.c b/arch/x86/adler32_sse41.c index 1e0f0ca463..87386e9460 100644 --- a/arch/x86/adler32_sse41.c +++ b/arch/x86/adler32_sse41.c @@ -7,8 +7,6 @@ */ #include "../../zbuild.h" -#include "../../zutil.h" - #include "../../adler32_p.h" #ifdef X86_SSE41_ADLER32 diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index f7587f3da1..57357d59c9 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -6,8 +6,6 @@ */ #include "../../zbuild.h" -#include "../../zutil.h" - #include "../../adler32_p.h" #ifdef X86_SSSE3_ADLER32 diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index 7a9a56a096..358869bc6a 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -2,7 +2,6 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zbuild.h" -#include "zutil.h" #ifdef X86_AVX_CHUNKSET #include diff --git a/arch/x86/chunkset_sse2.c b/arch/x86/chunkset_sse2.c index 577b0e2ef4..59b86f15ca 100644 --- a/arch/x86/chunkset_sse2.c +++ b/arch/x86/chunkset_sse2.c @@ -3,7 +3,6 @@ */ #include "zbuild.h" -#include "zutil.h" #ifdef X86_SSE2 #include diff --git a/arch/x86/compare256_avx2.c b/arch/x86/compare256_avx2.c index fd9481bfde..07f57f2839 100644 --- a/arch/x86/compare256_avx2.c +++ b/arch/x86/compare256_avx2.c @@ -4,7 +4,6 @@ */ #include "../../zbuild.h" -#include "../../zutil.h" #include "fallback_builtins.h" diff --git a/arch/x86/compare256_sse42.c b/arch/x86/compare256_sse42.c index 5f30b5e3ed..37a847c45c 100644 --- a/arch/x86/compare256_sse42.c +++ b/arch/x86/compare256_sse42.c @@ -16,7 +16,6 @@ */ #include "../../zbuild.h" -#include "../../zutil.h" #ifdef X86_SSE42_CMP_STR @@ -30,22 +29,22 @@ static inline uint32_t compare256_unaligned_sse4_static(const uint8_t *src0, con uint32_t len = 0; do { - #define mode _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY + #define cmp_mode _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY __m128i xmm_src0, xmm_src1; uint32_t ret; xmm_src0 = _mm_loadu_si128((__m128i *)src0); xmm_src1 = _mm_loadu_si128((__m128i *)src1); - ret = (uint32_t)_mm_cmpestri(xmm_src0, 16, xmm_src1, 16, mode); - if (_mm_cmpestrc(xmm_src0, 16, xmm_src1, 16, mode)) { + ret = (uint32_t)_mm_cmpestri(xmm_src0, 16, xmm_src1, 16, cmp_mode); + if (_mm_cmpestrc(xmm_src0, 16, xmm_src1, 16, cmp_mode)) { return len + ret; } src0 += 16, src1 += 16, len += 16; xmm_src0 = _mm_loadu_si128((__m128i *)src0); xmm_src1 = _mm_loadu_si128((__m128i *)src1); - ret = (uint32_t)_mm_cmpestri(xmm_src0, 16, xmm_src1, 16, mode); - if (_mm_cmpestrc(xmm_src0, 16, xmm_src1, 16, mode)) { + ret = (uint32_t)_mm_cmpestri(xmm_src0, 16, xmm_src1, 16, cmp_mode); + if (_mm_cmpestrc(xmm_src0, 16, xmm_src1, 16, cmp_mode)) { return len + ret; } src0 += 16, src1 += 16, len += 16; diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 6e429d6274..d801c8ccb1 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -17,7 +17,7 @@ */ #ifdef X86_PCLMULQDQ_CRC -#include "../../zutil.h" +#include "../../zbuild.h" #include #include diff --git a/arch/x86/crc32_fold_vpclmulqdq.c b/arch/x86/crc32_fold_vpclmulqdq.c index 9ed54b37e3..5272aed013 100644 --- a/arch/x86/crc32_fold_vpclmulqdq.c +++ b/arch/x86/crc32_fold_vpclmulqdq.c @@ -4,7 +4,7 @@ */ #ifdef X86_VPCLMULQDQ_CRC -#include "../../zutil.h" +#include "../../zbuild.h" #include @@ -14,9 +14,9 @@ size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; __m512i z0, z1, z2, z3; - z_const __m512i zmm_fold4 = _mm512_set4_epi32( + const __m512i zmm_fold4 = _mm512_set4_epi32( 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); - z_const __m512i zmm_fold16 = _mm512_set4_epi32( + const __m512i zmm_fold16 = _mm512_set4_epi32( 0x00000001, 0x1542778a, 0x00000001, 0x322d1430); // zmm register init diff --git a/arch/x86/x86.c b/arch/x86/x86.c index 945b29ef94..aec5062616 100644 --- a/arch/x86/x86.c +++ b/arch/x86/x86.c @@ -7,7 +7,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include "../../zutil.h" +#include "../../zbuild.h" #ifdef _MSC_VER # include diff --git a/chunkset.c b/chunkset.c index 48cdd9df6f..4cc70771f6 100644 --- a/chunkset.c +++ b/chunkset.c @@ -3,7 +3,6 @@ */ #include "zbuild.h" -#include "zutil.h" /* Define 8 byte chunks differently depending on unaligned support */ #if defined(UNALIGNED64_OK) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index c451c0d16c..dced2895d8 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -2,6 +2,8 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ +#include "zbuild.h" + /* Returns the chunk size */ Z_INTERNAL uint32_t CHUNKSIZE(void) { return sizeof(chunk_t); diff --git a/compare256.c b/compare256.c index 415088c5f1..68c0cf5431 100644 --- a/compare256.c +++ b/compare256.c @@ -4,8 +4,6 @@ */ #include "zbuild.h" -#include "zutil.h" - #include "fallback_builtins.h" /* ALIGNED, byte comparison */ diff --git a/crc32_fold.c b/crc32_fold.c index 7771c369ce..1800ed0a06 100644 --- a/crc32_fold.c +++ b/crc32_fold.c @@ -3,7 +3,6 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ #include "zbuild.h" -#include "zutil.h" #include "functable.h" #include "crc32_fold.h" diff --git a/crc32_p.h b/crc32_p.h index 371ddf1374..ae54c579ff 100644 --- a/crc32_p.h +++ b/crc32_p.h @@ -1,7 +1,7 @@ #ifndef CRC32_P_H_ #define CRC32_P_H_ -#include "zutil.h" +#include "zbuild.h" #include "zendian.h" #define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ diff --git a/test/benchmarks/benchmark_main.cc b/test/benchmarks/benchmark_main.cc index 81582c353a..fa8195e083 100644 --- a/test/benchmarks/benchmark_main.cc +++ b/test/benchmarks/benchmark_main.cc @@ -11,7 +11,6 @@ extern "C" { # include "zbuild.h" -# include "zutil.h" # include "cpu_features.h" } diff --git a/uncompr.c b/uncompr.c index 1435fab975..0053ef9827 100644 --- a/uncompr.c +++ b/uncompr.c @@ -3,7 +3,6 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#define Z_INTERNAL #include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" From b7192b694cc2b6405be570b35bf1b4fc5317930e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 26 Jan 2022 11:30:34 -0800 Subject: [PATCH 240/798] Move _POSIX_C_SOURCE define before first stdlib.h include in zbuild.h for posix_memalign. --- test/example.c | 3 --- test/fuzz/fuzzer_checksum.c | 4 ---- test/fuzz/fuzzer_compress.c | 4 ---- test/fuzz/fuzzer_example_dict.c | 4 ---- test/fuzz/fuzzer_example_large.c | 3 --- test/fuzz/fuzzer_example_small.c | 4 ---- test/fuzz/fuzzer_minigzip.c | 5 ----- test/fuzz/standalone_fuzz_target_runner.c | 1 - test/minideflate.c | 9 +-------- test/minigzip.c | 3 --- test/switchlevels.c | 4 ---- test/test_adler32.c | 6 ++---- test/test_crc32.c | 6 ++---- zbuild.h | 5 +++++ zutil_p.h | 6 +----- 15 files changed, 11 insertions(+), 56 deletions(-) diff --git a/test/example.c b/test/example.c index 3963fc2f9f..33232dedda 100644 --- a/test/example.c +++ b/test/example.c @@ -12,9 +12,6 @@ #include "deflate.h" #include - -#include -#include #include #include diff --git a/test/fuzz/fuzzer_checksum.c b/test/fuzz/fuzzer_checksum.c index 5874bb5335..e2002d5167 100644 --- a/test/fuzz/fuzzer_checksum.c +++ b/test/fuzz/fuzzer_checksum.c @@ -1,9 +1,5 @@ #include -#include -#include -#include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/fuzz/fuzzer_compress.c b/test/fuzz/fuzzer_compress.c index 11fb19f0f3..71cdf99ecf 100644 --- a/test/fuzz/fuzzer_compress.c +++ b/test/fuzz/fuzzer_compress.c @@ -1,9 +1,5 @@ #include -#include -#include -#include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/fuzz/fuzzer_example_dict.c b/test/fuzz/fuzzer_example_dict.c index 65df26a646..053a3e101a 100644 --- a/test/fuzz/fuzzer_example_dict.c +++ b/test/fuzz/fuzzer_example_dict.c @@ -1,9 +1,5 @@ #include -#include -#include -#include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/fuzz/fuzzer_example_large.c b/test/fuzz/fuzzer_example_large.c index 864b84126a..4114597218 100644 --- a/test/fuzz/fuzzer_example_large.c +++ b/test/fuzz/fuzzer_example_large.c @@ -1,8 +1,5 @@ #include -#include -#include #include -#include #include #include "zbuild.h" diff --git a/test/fuzz/fuzzer_example_small.c b/test/fuzz/fuzzer_example_small.c index a4547feaf1..e59c720835 100644 --- a/test/fuzz/fuzzer_example_small.c +++ b/test/fuzz/fuzzer_example_small.c @@ -1,9 +1,5 @@ #include -#include -#include -#include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT diff --git a/test/fuzz/fuzzer_minigzip.c b/test/fuzz/fuzzer_minigzip.c index 0c7a79a7d7..819148d2b3 100644 --- a/test/fuzz/fuzzer_minigzip.c +++ b/test/fuzz/fuzzer_minigzip.c @@ -12,9 +12,6 @@ * real thing. */ -#define _POSIX_SOURCE 1 /* This file needs POSIX for fileno(). */ -#define _POSIX_C_SOURCE 200112 /* For snprintf(). */ - #include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" @@ -23,8 +20,6 @@ #endif #include #include -#include -#include #ifdef USE_MMAP # include diff --git a/test/fuzz/standalone_fuzz_target_runner.c b/test/fuzz/standalone_fuzz_target_runner.c index 49f5e7fa19..810a56072f 100644 --- a/test/fuzz/standalone_fuzz_target_runner.c +++ b/test/fuzz/standalone_fuzz_target_runner.c @@ -1,6 +1,5 @@ #include #include -#include #include "zbuild.h" diff --git a/test/minideflate.c b/test/minideflate.c index f82cfcc302..2ea280f21a 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -3,15 +3,8 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#define _POSIX_SOURCE 1 /* This file needs POSIX for fileno(). */ -#define _POSIX_C_SOURCE 200112 /* For snprintf(). */ - #include -#include -#include -#include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT @@ -272,7 +265,7 @@ int main(int argc, char **argv) { } else if (argv[i][0] == '-') { show_help(); return 64; /* EX_USAGE */ - } else + } else break; } diff --git a/test/minigzip.c b/test/minigzip.c index e2e4bad3b3..34fc664309 100644 --- a/test/minigzip.c +++ b/test/minigzip.c @@ -12,9 +12,6 @@ * real thing. */ -#define _POSIX_SOURCE 1 -#define _POSIX_C_SOURCE 200112 /* For snprintf(). */ - #include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" diff --git a/test/switchlevels.c b/test/switchlevels.c index 1e1fb00a5c..a065dbcff0 100644 --- a/test/switchlevels.c +++ b/test/switchlevels.c @@ -2,8 +2,6 @@ * Each chunk is compressed with a user-specified level. */ -#define _POSIX_SOURCE 1 /* This file needs POSIX for fileno(). */ - #include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" @@ -12,8 +10,6 @@ #endif #include -#include -#include #if defined(_WIN32) || defined(__CYGWIN__) # include diff --git a/test/test_adler32.c b/test/test_adler32.c index 38f890956f..56e8c0ca11 100644 --- a/test/test_adler32.c +++ b/test/test_adler32.c @@ -4,10 +4,6 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include -#include -#include - #include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" @@ -15,6 +11,8 @@ # include "zlib-ng.h" #endif +#include + typedef struct { uint32_t line; uint32_t adler; diff --git a/test/test_crc32.c b/test/test_crc32.c index 6d112c4a66..83718eb0bc 100644 --- a/test/test_crc32.c +++ b/test/test_crc32.c @@ -5,10 +5,6 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include -#include -#include - #include "zbuild.h" #ifdef ZLIB_COMPAT # include "zlib.h" @@ -16,6 +12,8 @@ # include "zlib-ng.h" #endif +#include + typedef struct { uint32_t line; unsigned long crc; diff --git a/zbuild.h b/zbuild.h index 9430ba34f2..d2b6a922dd 100644 --- a/zbuild.h +++ b/zbuild.h @@ -1,6 +1,11 @@ #ifndef _ZBUILD_H #define _ZBUILD_H +#define _POSIX_SOURCE 1 /* fileno */ +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L /* snprintf, posix_memalign */ +#endif + #include #include #include diff --git a/zutil_p.h b/zutil_p.h index 55f00611b3..fdfb4438a9 100644 --- a/zutil_p.h +++ b/zutil_p.h @@ -1,14 +1,10 @@ /* zutil_p.h -- Private inline functions used internally in zlib-ng - * + * For conditions of distribution and use, see copyright notice in zlib.h */ #ifndef ZUTIL_P_H #define ZUTIL_P_H -#if defined(HAVE_POSIX_MEMALIGN) && !defined(_POSIX_C_SOURCE) -# define _POSIX_C_SOURCE 200112L /* For posix_memalign(). */ -#endif - #if defined(__APPLE__) || defined(HAVE_POSIX_MEMALIGN) # include #elif defined(__FreeBSD__) From 529f42edea86af5f3e765ca50fb6ce4c60cff3e2 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Mon, 24 Jan 2022 08:21:10 +0200 Subject: [PATCH 241/798] [ARM] Use armv8-crc+simd when compiling ACLE code on toolchains that don't enable FPU by default. --- cmake/detect-intrinsics.cmake | 14 ++++++++++++-- configure | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index cc1ffa51c1..429383cd72 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -2,14 +2,24 @@ # Licensed under the Zlib license, see LICENSE.md for details macro(check_acle_intrinsics) - if(NOT NATIVEFLAG) - set(ACLEFLAG "-march=armv8-a+crc") + if(NOT NATIVEFLAG AND NOT HAVE_ACLE_INTRIN) + set(ACLEFLAG "-march=armv8-a+crc" CACHE INTERNAL "Compiler option to enable ACLE support") endif() # Check whether compiler supports ACLE flag set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG}") check_c_source_compiles( "int main() { return 0; }" HAVE_ACLE_INTRIN FAIL_REGEX "not supported") + if(NOT NATIVEFLAG AND NOT HAVE_ACLE_INTRIN) + set(ACLEFLAG "-march=armv8-a+crc+simd" CACHE INTERNAL "Compiler option to enable ACLE support" FORCE) + # Check whether compiler supports ACLE flag + set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG}") + check_c_source_compiles( + "int main() { return 0; }" + HAVE_ACLE_INTRIN2 FAIL_REGEX "not supported") + set(HAVE_ACLE_INTRIN ${HAVE_ACLE_INTRIN2} CACHE INTERNAL "Have ACLE intrinsics" FORCE) + unset(HAVE_ACLE_INTRIN2 CACHE) # Don't cache this internal variable + endif() set(CMAKE_REQUIRED_FLAGS) endmacro() diff --git a/configure b/configure index e957aa0ba1..1e063322a4 100755 --- a/configure +++ b/configure @@ -1132,6 +1132,29 @@ EOF fi } +check_acle_intrinsics() { + # Check whether -march=armv8-a+crc works correctly + cat > $test.c << EOF +int main() { return 0; } +EOF + if try $CC -c $CFLAGS -march=armv8-a+crc $test.c; then + ACLE_AVAILABLE=1 + echo "Check whether -march=armv8-a+crc works ... Yes." | tee -a configure.log + else + echo "Check whether -march=armv8-a+crc works ... No." | tee -a configure.log + if try $CC -c $CFLAGS -march=armv8-a+crc+simd $test.c; then + ACLE_AVAILABLE=1 + echo "Check whether -march=armv8-a+crc+simd works ... Yes." | tee -a configure.log + if test "$ARCH" = "armv8-a+crc"; then + ARCH=armv8-a+crc+simd + fi + else + ACLE_AVAILABLE=0 + echo "Check whether -march=armv8-a+crc+simd works ... No." | tee -a configure.log + fi + fi +} + check_neon_intrinsics() { # Check whether -mfpu=neon is available on ARM processors. cat > $test.c << EOF @@ -1633,6 +1656,7 @@ EOF fi if test $without_optimizations -eq 0; then + check_acle_intrinsics check_neon_intrinsics fi @@ -1713,11 +1737,13 @@ EOF acleflag="-march=${ARCH}" if test $without_optimizations -eq 0; then - CFLAGS="${CFLAGS} -DARM_ACLE_CRC_HASH" - SFLAGS="${SFLAGS} -DARM_ACLE_CRC_HASH" + if test $ACLE_AVAILABLE -eq 1; then + CFLAGS="${CFLAGS} -DARM_ACLE_CRC_HASH" + SFLAGS="${SFLAGS} -DARM_ACLE_CRC_HASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} crc32_acle.o insert_string_acle.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} crc32_acle.lo insert_string_acle.lo" + fi if test $buildneon -eq 1; then if test $MFPU_NEON_AVAILABLE -eq 1;then From da7622bc8719c2b872a733bcddf1a0f42d8c7475 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Tue, 25 Jan 2022 16:11:39 +0200 Subject: [PATCH 242/798] [ARM] rename cmake/configure macros check_{acle,neon}_intrinsics to check_{acle,neon}_compiler_flag * Currently these macros only check that the compiler flag(s) are supported, not that the compiler supports the actual intrinsics --- CMakeLists.txt | 6 +++--- cmake/detect-intrinsics.cmake | 16 ++++++++-------- configure | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dfdc98bbb7..f15d1f9cb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -603,8 +603,8 @@ if(WITH_OPTIM) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/armfeature.c) if(WITH_ACLE AND NOT MSVC AND NOT "${ARCH}" MATCHES "armv[2-7]") - check_acle_intrinsics() - if(HAVE_ACLE_INTRIN) + check_acle_compiler_flag() + if(HAVE_ACLE_FLAG) add_definitions(-DARM_ACLE_CRC_HASH) set(ACLE_SRCS ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c) set_property(SOURCE ${ACLE_SRCS} PROPERTY COMPILE_FLAGS "${ACLEFLAG} ${NOLTOFLAG}") @@ -617,7 +617,7 @@ if(WITH_OPTIM) set(WITH_ACLE OFF) endif() if(WITH_NEON) - check_neon_intrinsics() + check_neon_compiler_flag() if(MFPU_NEON_AVAILABLE) add_definitions(-DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_hash_neon.c) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 429383cd72..f7d27dc2b1 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -1,24 +1,24 @@ # detect-intrinsics.cmake -- Detect compiler intrinsics support # Licensed under the Zlib license, see LICENSE.md for details -macro(check_acle_intrinsics) - if(NOT NATIVEFLAG AND NOT HAVE_ACLE_INTRIN) +macro(check_acle_compiler_flag) + if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) set(ACLEFLAG "-march=armv8-a+crc" CACHE INTERNAL "Compiler option to enable ACLE support") endif() # Check whether compiler supports ACLE flag set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG} ${NATIVEFLAG}") check_c_source_compiles( "int main() { return 0; }" - HAVE_ACLE_INTRIN FAIL_REGEX "not supported") - if(NOT NATIVEFLAG AND NOT HAVE_ACLE_INTRIN) + HAVE_ACLE_FLAG FAIL_REGEX "not supported") + if(NOT NATIVEFLAG AND NOT HAVE_ACLE_FLAG) set(ACLEFLAG "-march=armv8-a+crc+simd" CACHE INTERNAL "Compiler option to enable ACLE support" FORCE) # Check whether compiler supports ACLE flag set(CMAKE_REQUIRED_FLAGS "${ACLEFLAG}") check_c_source_compiles( "int main() { return 0; }" - HAVE_ACLE_INTRIN2 FAIL_REGEX "not supported") - set(HAVE_ACLE_INTRIN ${HAVE_ACLE_INTRIN2} CACHE INTERNAL "Have ACLE intrinsics" FORCE) - unset(HAVE_ACLE_INTRIN2 CACHE) # Don't cache this internal variable + HAVE_ACLE_FLAG2 FAIL_REGEX "not supported") + set(HAVE_ACLE_FLAG ${HAVE_ACLE_FLAG2} CACHE INTERNAL "Have compiler option to enable ACLE intrinsics" FORCE) + unset(HAVE_ACLE_FLAG2 CACHE) # Don't cache this internal variable endif() set(CMAKE_REQUIRED_FLAGS) endmacro() @@ -133,7 +133,7 @@ macro(check_avx2_intrinsics) set(CMAKE_REQUIRED_FLAGS) endmacro() -macro(check_neon_intrinsics) +macro(check_neon_compiler_flag) if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) if("${ARCH}" MATCHES "aarch64") diff --git a/configure b/configure index 1e063322a4..1f8c64db01 100755 --- a/configure +++ b/configure @@ -1132,7 +1132,7 @@ EOF fi } -check_acle_intrinsics() { +check_acle_compiler_flag() { # Check whether -march=armv8-a+crc works correctly cat > $test.c << EOF int main() { return 0; } @@ -1155,7 +1155,7 @@ EOF fi } -check_neon_intrinsics() { +check_neon_compiler_flag() { # Check whether -mfpu=neon is available on ARM processors. cat > $test.c << EOF int main() { return 0; } @@ -1656,8 +1656,8 @@ EOF fi if test $without_optimizations -eq 0; then - check_acle_intrinsics - check_neon_intrinsics + check_acle_compiler_flag + check_neon_compiler_flag fi case "${ARCH}" in From b8c9c73e6b3c789d7a54e826cc64ff026f2b6388 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 31 Jan 2022 13:19:18 +0100 Subject: [PATCH 243/798] IBM Z: Upgrade self-hosted builder to v2.287.1 --- arch/s390/self-hosted-builder/actions-runner.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/self-hosted-builder/actions-runner.Dockerfile b/arch/s390/self-hosted-builder/actions-runner.Dockerfile index a4bb774ab0..8b9f60945f 100644 --- a/arch/s390/self-hosted-builder/actions-runner.Dockerfile +++ b/arch/s390/self-hosted-builder/actions-runner.Dockerfile @@ -31,7 +31,7 @@ ENV QEMU_LD_PREFIX=/usr/x86_64-linux-gnu RUN useradd -m actions-runner USER actions-runner WORKDIR /home/actions-runner -RUN curl -L https://github.com/actions/runner/releases/download/v2.283.2/actions-runner-linux-x64-2.283.2.tar.gz | tar -xz +RUN curl -L https://github.com/actions/runner/releases/download/v2.287.1/actions-runner-linux-x64-2.287.1.tar.gz | tar -xz VOLUME /home/actions-runner # Scripts. From d6560afa18fe95a32f418a27a73fb4a6b6ed85a4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 26 Jan 2022 14:36:07 -0800 Subject: [PATCH 244/798] Fixed wrong cpu check variable used for ARM in adler benchmarks. --- test/benchmarks/benchmark_adler32.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index 0f63c5c3d1..d391f7b17f 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -68,7 +68,7 @@ class adler32: public benchmark::Fixture { BENCHMARK_ADLER32(c, adler32_c, 1); #ifdef ARM_NEON_ADLER32 -BENCHMARK_ADLER32(neon, adler32_neon, arm_has_neon); +BENCHMARK_ADLER32(neon, adler32_neon, arm_cpu_has_neon); #elif defined(POWER8_VSX_ADLER32) BENCHMARK_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07); #elif defined(PPC_VMX_ADLER32) From 5670dfe575777ae829250b7f7be0a46cc8685bb6 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 26 Jan 2022 14:36:26 -0800 Subject: [PATCH 245/798] Removed unused CMake includes in benchmark cmake. --- test/benchmarks/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index c3d8410234..2e87df49d6 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -1,7 +1,5 @@ cmake_minimum_required(VERSION 3.12) -include(CheckCCompilerFlag) -include(FeatureSummary) include(FetchContent) enable_language(CXX) From 2d6a1371b701016d7f0ee5446c116cbbfcdd5fe2 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 26 Jan 2022 16:07:31 -0800 Subject: [PATCH 246/798] Remove unnecessary compiler specification from mingw configs. --- .github/workflows/cmake.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 2d00c71349..8d22814eb0 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -257,7 +257,6 @@ jobs: - name: Ubuntu MinGW i686 os: ubuntu-latest - compiler: i686-w64-mingw32-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake packages: wine32 gcc-mingw-w64 codecov: ubuntu_gcc_mingw_i686 @@ -266,7 +265,6 @@ jobs: - name: Ubuntu MinGW x86_64 os: ubuntu-latest - compiler: x86_64-w64-mingw32-gcc cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-x86_64.cmake packages: wine-stable gcc-mingw-w64 codecov: ubuntu_gcc_mingw_x86_64 From 575ed3ac77c37409d1fcdc5fa074fd74db956354 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 21 Jan 2022 12:15:36 -0800 Subject: [PATCH 247/798] Fixed typo when undefined behavior sanitizer is not supported. --- cmake/detect-sanitizer.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/detect-sanitizer.cmake b/cmake/detect-sanitizer.cmake index 344427c44f..fc4519ef28 100644 --- a/cmake/detect-sanitizer.cmake +++ b/cmake/detect-sanitizer.cmake @@ -133,6 +133,6 @@ macro(add_undefined_sanitizer) add_compile_options(-fno-sanitize=alignment) endif() else() - message(STATUS "UNdefined behavior sanitizer is not supported") + message(STATUS "Undefined behavior sanitizer is not supported") endif() endmacro() From 10a238f6d9eb6c028769add7fe846623da2a8efe Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 30 Jan 2022 08:30:34 -0800 Subject: [PATCH 248/798] Remove qemu-run variable which is already defined in the toolchain files. Only configure script would need this variable defined. --- .github/workflows/cmake.yml | 18 ------------------ .github/workflows/pigz.yml | 1 - 2 files changed, 19 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8d22814eb0..c8b27e98e1 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -105,7 +105,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross - qemu-run: qemu-arm codecov: ubuntu_gcc_armsf - name: Ubuntu GCC ARM SF Compat No Opt @@ -113,7 +112,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross - qemu-run: qemu-arm codecov: ubuntu_gcc_armsf_compat_no_opt - name: Ubuntu GCC ARM HF @@ -121,7 +119,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross - qemu-run: qemu-arm codecov: ubuntu_gcc_armhf - name: Ubuntu GCC ARM HF No ACLE @@ -129,7 +126,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross - qemu-run: qemu-arm codecov: ubuntu_gcc_armhf_no_acle - name: Ubuntu GCC ARM HF No NEON @@ -137,7 +133,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross - qemu-run: qemu-arm codecov: ubuntu_gcc_armhf_no_neon - name: Ubuntu GCC ARM HF Compat No Opt @@ -145,7 +140,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross - qemu-run: qemu-arm codecov: ubuntu_gcc_armhf_compat_no_opt - name: Ubuntu GCC AARCH64 @@ -153,7 +147,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 codecov: ubuntu_gcc_aarch64 - name: Ubuntu GCC AARCH64 No ACLE @@ -161,7 +154,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 codecov: ubuntu_gcc_aarch64_no_acle - name: Ubuntu GCC AARCH64 No NEON @@ -169,7 +161,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 codecov: ubuntu_gcc_aarch64_no_neon - name: Ubuntu GCC AARCH64 Compat No Opt @@ -177,7 +168,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 codecov: ubuntu_gcc_aarch64_compat_no_opt - name: Ubuntu GCC PPC @@ -185,7 +175,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross - qemu-run: qemu-ppc ldflags: -static codecov: ubuntu_gcc_ppc @@ -194,7 +183,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake -DWITH_POWER8=OFF asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross - qemu-run: qemu-ppc codecov: ubuntu_gcc_ppc_no_power8 - name: Ubuntu GCC PPC64 @@ -202,7 +190,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc64-linux-gnu libc-dev-ppc64-cross - qemu-run: qemu-ppc64 ldflags: -static codecov: ubuntu_gcc_ppc64 @@ -211,7 +198,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc64le-linux-gnu libc-dev-ppc64el-cross - qemu-run: qemu-ppc64le codecov: ubuntu_gcc_ppc64le - name: Ubuntu GCC SPARC64 @@ -219,7 +205,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-sparc64-linux-gnu libc-dev-sparc64-cross - qemu-run: qemu-sparc64 ldflags: -static codecov: ubuntu_gcc_sparc64 @@ -228,7 +213,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross - qemu-run: qemu-s390x ldflags: -static codecov: ubuntu_gcc_s390x @@ -237,7 +221,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_CRC32_VX=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross - qemu-run: qemu-s390x ldflags: -static codecov: ubuntu_gcc_s390x @@ -450,7 +433,6 @@ jobs: MSAN_OPTIONS: ${{ matrix.msan-options || 'verbosity=0' }}:abort_on_error=1 TSAN_OPTIONS: ${{ matrix.tsan-options || 'verbosity=0' }}:abort_on_error=1 LSAN_OPTIONS: ${{ matrix.lsan-options || 'verbosity=0' }}:abort_on_error=1 - QEMU_RUN: ${{ matrix.qemu-run }} - name: Upload coverage report if: matrix.codecov && ( env.CODECOV_TOKEN_SECRET != '' || github.repository == 'zlib-ng/zlib-ng' ) diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 7ffe845b6d..c36cfafa70 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -47,7 +47,6 @@ jobs: os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=../../cmake/toolchain-aarch64.cmake packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross - qemu-run: qemu-aarch64 codecov: ubuntu_gcc_pigz_aarch64 steps: From 7f9d84dc6ab75d051c8591e4e925c74cb7587a59 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 31 Jan 2022 07:51:01 -0800 Subject: [PATCH 249/798] Fixed S390X CI instance code coverage report names not unique. --- .github/workflows/cmake.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index c8b27e98e1..ddbd3531f2 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -222,21 +222,21 @@ jobs: asan-options: detect_leaks=0 packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross ldflags: -static - codecov: ubuntu_gcc_s390x + codecov: ubuntu_gcc_s390x_no_crc32 - name: Ubuntu GCC S390X DFLTCC os: z15 compiler: gcc cmake-args: -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - codecov: ubuntu_gcc_s390x + codecov: ubuntu_gcc_s390x_dfltcc - name: Ubuntu GCC S390X DFLTCC Compat os: z15 compiler: gcc cmake-args: -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 - codecov: ubuntu_gcc_s390x + codecov: ubuntu_gcc_s390x_dfltcc_compat - name: Ubuntu MinGW i686 os: ubuntu-latest From 88f331e6a64653b533721a645f8253b78e7f391a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 31 Jan 2022 07:54:52 -0800 Subject: [PATCH 250/798] Added sanitizer identification to CMake CI instance names. --- .github/workflows/cmake.yml | 46 ++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index ddbd3531f2..8319fa1a7f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -12,7 +12,7 @@ jobs: os: ubuntu-18.04 compiler: gcc - - name: Ubuntu GCC + - name: Ubuntu GCC ASAN os: ubuntu-latest compiler: gcc cmake-args: -DWITH_SANITIZER=Address @@ -36,7 +36,7 @@ jobs: cmake-args: -DZLIB_COMPAT=ON -DZLIB_SYMBOL_PREFIX=zTest_ codecov: ubuntu_gcc_compat_sprefix - - name: Ubuntu GCC OSB -O1 No Unaligned64 + - name: Ubuntu GCC OSB -O1 No Unaligned64 UBSAN os: ubuntu-latest compiler: gcc cmake-args: -DWITH_UNALIGNED=ON -DUNALIGNED64_OK=OFF -DWITH_SANITIZER=Undefined @@ -69,101 +69,101 @@ jobs: compiler: gcc cmake-args: -DZLIB_DUAL_LINK=ON - - name: Ubuntu GCC No AVX2 + - name: Ubuntu GCC No AVX2 UBSAN os: ubuntu-latest compiler: gcc cmake-args: -DWITH_AVX2=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_avx2 - - name: Ubuntu GCC No SSE2 + - name: Ubuntu GCC No SSE2 UBSAN os: ubuntu-latest compiler: gcc cmake-args: -DWITH_SSE2=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_sse2 - - name: Ubuntu GCC No SSE4 + - name: Ubuntu GCC No SSE4 UBSAN os: ubuntu-latest compiler: gcc cmake-args: -DWITH_SSE4=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_sse4 - - name: Ubuntu GCC No PCLMULQDQ + - name: Ubuntu GCC No PCLMULQDQ UBSAN os: ubuntu-latest compiler: gcc cmake-args: -DWITH_PCLMULQDQ=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_pclmulqdq - - name: Ubuntu GCC Compat No Opt + - name: Ubuntu GCC Compat No Opt ASAN os: ubuntu-latest compiler: gcc cmake-args: -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Address codecov: ubuntu_gcc_compat_no_opt cflags: -DNOT_TWEAK_COMPILER - - name: Ubuntu GCC ARM SF + - name: Ubuntu GCC ARM SF ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross codecov: ubuntu_gcc_armsf - - name: Ubuntu GCC ARM SF Compat No Opt + - name: Ubuntu GCC ARM SF Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross codecov: ubuntu_gcc_armsf_compat_no_opt - - name: Ubuntu GCC ARM HF + - name: Ubuntu GCC ARM HF ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf - - name: Ubuntu GCC ARM HF No ACLE + - name: Ubuntu GCC ARM HF No ACLE ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf_no_acle - - name: Ubuntu GCC ARM HF No NEON + - name: Ubuntu GCC ARM HF No NEON ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf_no_neon - - name: Ubuntu GCC ARM HF Compat No Opt + - name: Ubuntu GCC ARM HF Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf_compat_no_opt - - name: Ubuntu GCC AARCH64 + - name: Ubuntu GCC AARCH64 ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64 - - name: Ubuntu GCC AARCH64 No ACLE + - name: Ubuntu GCC AARCH64 No ACLE UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_no_acle - - name: Ubuntu GCC AARCH64 No NEON + - name: Ubuntu GCC AARCH64 No NEON UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_no_neon - - name: Ubuntu GCC AARCH64 Compat No Opt + - name: Ubuntu GCC AARCH64 Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 @@ -208,7 +208,7 @@ jobs: ldflags: -static codecov: ubuntu_gcc_sparc64 - - name: Ubuntu GCC S390X + - name: Ubuntu GCC S390X ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 @@ -216,7 +216,7 @@ jobs: ldflags: -static codecov: ubuntu_gcc_s390x - - name: Ubuntu GCC S390X No vectorized CRC32 + - name: Ubuntu GCC S390X No vectorized CRC32 ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_CRC32_VX=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 @@ -224,14 +224,14 @@ jobs: ldflags: -static codecov: ubuntu_gcc_s390x_no_crc32 - - name: Ubuntu GCC S390X DFLTCC + - name: Ubuntu GCC S390X DFLTCC ASAN os: z15 compiler: gcc cmake-args: -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Address asan-options: detect_leaks=0 codecov: ubuntu_gcc_s390x_dfltcc - - name: Ubuntu GCC S390X DFLTCC Compat + - name: Ubuntu GCC S390X DFLTCC Compat UBSAN os: z15 compiler: gcc cmake-args: -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined @@ -347,13 +347,13 @@ jobs: cmake-args: -G Ninja -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF codecov: win64_gcc_compat_no_opt - - name: macOS Clang + - name: macOS Clang ASAN os: macos-latest compiler: clang cmake-args: -DWITH_SANITIZER=Address codecov: macos_clang - - name: macOS GCC + - name: macOS GCC UBSAN os: macos-latest compiler: gcc-10 cmake-args: -DWITH_SANITIZER=Undefined From 403a9aee6751c9eb7ada6090c530f1ba8991da97 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Fri, 28 Jan 2022 10:00:07 -0500 Subject: [PATCH 251/798] More than double adler32 performance with altivec Bits of low hanging and high hanging fruit in this round of optimization. Altivec has a sum characters into 4 lanes of integers instructions (intrinsic vec_sum4s) that seems basically made for this algorithm. Additionally, there's a similar multiply-accumulate routine that takes two character vectors for input and outputs a vector of 4 ints for their respective adjacent sums. This alone was a good amount of the performance gains. Additionally, the shifting by 4 was still done in the loop when it was easy to roll outside of the loop and do only once. This removed some latency for a dependent operand to be ready. We also unrolled the loop with independent sums, though, this only seems to help for much larger input sizes. Additionally, we reduced feeding the two 16 bit halves of the sum simply by packing them into an aligned allocation in the stack next to each other. Then, when loaded, we permute and shift the values to two separate vector registers from the same input registers. The separation of these scalars probably could have been done in vector registers through some tricks but we need them in scalar GPRs anyhow every time they leave the loop so it was naturally better to keep those separate before hitting the vectorized code. For the horizontal addition, the code was modified to use a sequence of shifts and adds to produce a vector sum in the first lane. Then, the much cheaper vec_ste was used to store the value into a general purpose register rather than vec_extract. Lastly, instead of doing the relatively expensive modulus in GPRs after we perform the scalar operations to align all of the loads in the loop, we can instead reduce "n" here for the first round to be n minus the alignment offset. --- arch/power/adler32_vmx.c | 85 ++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 30 deletions(-) diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index 5d7dc43e2c..491d8d5dfc 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -1,6 +1,7 @@ /* adler32_vmx.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011 Mark Adler * Copyright (C) 2017-2021 Mika T. Lindqvist + * Copyright (C) 2021 Adam Stylinski * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -11,16 +12,6 @@ #define vmx_zero() (vec_splat_u32(0)) -vector unsigned short vec_hadduh(vector unsigned char a) { - vector unsigned char vmx_one = vec_splat_u8(1); - return vec_add(vec_mulo(a, vmx_one), vec_mule(a, vmx_one)); -} - -vector unsigned int vec_hadduw(vector unsigned short a) { - vector unsigned short vmx_one = vec_splat_u16(1); - return vec_add(vec_mulo(a, vmx_one), vec_mule(a, vmx_one)); -} - static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char *buf, size_t len) { unsigned int i; for (i = 0; i < len; ++i) { @@ -30,31 +21,64 @@ static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char * } static void vmx_accum32(uint32_t *s, const unsigned char *buf, size_t len) { - static const uint8_t tc0[16] ALIGNED_(16) = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; - - vector unsigned char t0 = vec_ld(0, tc0); + const vector unsigned char t0 = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + /* As silly and inefficient as it seems, creating 1 permutation vector to permute + * a 2 element vector from a single load + a subsequent shift is just barely faster + * than doing 2 indexed insertions into zero initialized vectors from unaligned memory. */ + const vector unsigned char s0_perm = {0, 1, 2, 3, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + const vector unsigned char shift_vec = vec_sl(vec_splat_u8(8), vec_splat_u8(2)); vector unsigned int adacc, s2acc; - adacc = vec_insert(s[0], vmx_zero(), 0); - s2acc = vec_insert(s[1], vmx_zero(), 0); + vector unsigned int pair_vec = vec_ld(0, s); + adacc = vec_perm(pair_vec, pair_vec, s0_perm); + s2acc = vec_slo(pair_vec, shift_vec); + + vector unsigned int s3acc = vmx_zero(); + vector unsigned int s2acc_0 = s3acc; + vector unsigned int adacc_0 = adacc; + + int num_iter = len / 2; + int rem = len & 1; + + for (int i = 0; i < num_iter; ++i) { + vector unsigned char d0 = vec_ld(0, buf); + vector unsigned char d1 = vec_ld(16, buf); + + adacc = vec_sum4s(d0, adacc); + s3acc = vec_add(s3acc, adacc_0); + s2acc = vec_msum(t0, d0, s2acc); - while (len > 0) { + s3acc = vec_add(s3acc, adacc); + adacc = vec_sum4s(d1, adacc); + s2acc_0 = vec_msum(t0, d1, s2acc_0); + adacc_0 = adacc; + + buf += 32; + } + + if (rem) { vector unsigned char d0 = vec_ld(0, buf); - vector unsigned short sum2; - sum2 = vec_add(vec_mulo(t0, d0), vec_mule(t0, d0)); - s2acc = vec_add(s2acc, vec_sl(adacc, vec_splat_u32(4))); - s2acc = vec_add(s2acc, vec_hadduw(sum2)); - adacc = vec_add(adacc, vec_hadduw(vec_hadduh(d0))); - buf += 16; - len--; + s3acc = vec_add(s3acc, adacc); + s2acc = vec_msum(t0, d0, s2acc); + adacc = vec_sum4s(d0, adacc); } - s[0] = vec_extract(adacc, 0) + vec_extract(adacc, 1) + vec_extract(adacc, 2) + vec_extract(adacc, 3); /* Horizontal add */ - s[1] = vec_extract(s2acc, 0) + vec_extract(s2acc, 1) + vec_extract(s2acc, 2) + vec_extract(s2acc, 3); /* Horizontal add */ + s2acc = vec_add(s2acc, s2acc_0); + s3acc = vec_sl(s3acc, vec_splat_u32(4)); + s2acc = vec_add(s2acc, s3acc); + + adacc = vec_add(adacc, vec_sld(adacc, adacc, 8)); + s2acc = vec_add(s2acc, vec_sld(s2acc, s2acc, 8)); + adacc = vec_add(adacc, vec_sld(adacc, adacc, 4)); + s2acc = vec_add(s2acc, vec_sld(s2acc, s2acc, 4)); + + vec_ste(adacc, 0, s); + vec_ste(s2acc, 0, s+1); } uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t sum2; - uint32_t pair[2]; + uint32_t pair[16] ALIGNED_(16); + memset(&pair[2], 0, 14); int n = NMAX; unsigned int done = 0, i; @@ -86,14 +110,15 @@ uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len) { al=len; } vmx_handle_head_or_tail(pair, buf, al); - pair[0] %= BASE; - pair[1] %= BASE; done += al; + /* Rather than rebasing, we can reduce the max sums for the + * first round only */ + n -= al; } for (i = al; i < len; i += n) { - if ((i + n) > len) - n = (int)(len - i); + int remaining = (int)(len-i); + n = MIN(remaining, (i == al) ? n : NMAX); if (n < 16) break; From 9146bd472c23a501725d275f8b7edec93c072466 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 23 Jan 2022 11:59:57 -0500 Subject: [PATCH 252/798] Marginal improvement by pipelining loads on NEON The ld1{4 reg} variant saves us instructions and only adds 3 cycles of latency to load 3 more neon/asimd registers worth of data. --- CMakeLists.txt | 4 ++++ arch/arm/slide_hash_neon.c | 21 ++++++++-------- cmake/detect-intrinsics.cmake | 28 ++++++++++++++++++++++ configure | 44 ++++++++++++++++++++++++++++++++++ fallback_builtins.h | 45 ++++++++++++++++++++++++++++++++--- win32/Makefile.a64 | 5 ++-- win32/Makefile.arm | 5 ++-- 7 files changed, 134 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f15d1f9cb5..ccac51cbf1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -628,6 +628,10 @@ if(WITH_OPTIM) endif() add_feature_info(NEON_ADLER32 1 "Support NEON instructions in adler32, using \"${NEONFLAG}\"") add_feature_info(NEON_SLIDEHASH 1 "Support NEON instructions in slide_hash, using \"${NEONFLAG}\"") + check_neon_ld4_intrinsics() + if(NEON_HAS_LD4) + add_definitions(-DARM_NEON_HASLD4) + endif() else() set(WITH_NEON OFF) endif() diff --git a/arch/arm/slide_hash_neon.c b/arch/arm/slide_hash_neon.c index b90e470219..6ff7a0bb60 100644 --- a/arch/arm/slide_hash_neon.c +++ b/arch/arm/slide_hash_neon.c @@ -16,10 +16,12 @@ #endif #include "../../zbuild.h" #include "../../deflate.h" +#include "../../fallback_builtins.h" /* SIMD version of hash_chain rebase */ static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) { - Z_REGISTER uint16x8_t v, *p; + Z_REGISTER uint16x8_t v; + uint16x8x4_t p0, p1; Z_REGISTER size_t n; size_t size = entries*sizeof(table[0]); @@ -28,18 +30,15 @@ static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize Assert(sizeof(Pos) == 2, "Wrong Pos size"); v = vdupq_n_u16(wsize); - p = (uint16x8_t *)table; n = size / (sizeof(uint16x8_t) * 8); do { - p[0] = vqsubq_u16(p[0], v); - p[1] = vqsubq_u16(p[1], v); - p[2] = vqsubq_u16(p[2], v); - p[3] = vqsubq_u16(p[3], v); - p[4] = vqsubq_u16(p[4], v); - p[5] = vqsubq_u16(p[5], v); - p[6] = vqsubq_u16(p[6], v); - p[7] = vqsubq_u16(p[7], v); - p += 8; + p0 = vld1q_u16_x4(table); + p1 = vld1q_u16_x4(table+32); + vqsubq_u16_x4_x1(p0, p0, v); + vqsubq_u16_x4_x1(p1, p1, v); + vst1q_u16_x4(table, p0); + vst1q_u16_x4(table+32, p1); + table += 64; } while (--n); } diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index f7d27dc2b1..c4231c26ac 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -151,6 +151,34 @@ macro(check_neon_compiler_flag) set(CMAKE_REQUIRED_FLAGS) endmacro() +macro(check_neon_ld4_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + if("${ARCH}" MATCHES "aarch64") + set(NEONFLAG "-march=armv8-a+simd") + else() + set(NEONFLAG "-mfpu=neon") + endif() + endif() + endif() + # Check whether compiler supports loading 4 neon vecs into a register range + set(CMAKE_REQUIRED_FLAGS "${NEONFLAG}") + check_c_source_compiles( + "#ifdef _M_ARM64 + # include + #else + # include + #endif + int main(void) { + int stack_var[16]; + int32x4x4_t v = vld1q_s32_x4(stack_var); + (void)v; + return 0; + }" + NEON_HAS_LD4) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + macro(check_pclmulqdq_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) diff --git a/configure b/configure index 1f8c64db01..93b109b7ca 100755 --- a/configure +++ b/configure @@ -1169,6 +1169,29 @@ EOF fi } +check_neon_ld4_intrinsics() { + cat > $test.c << EOF +#ifdef _M_ARM64 +# include +#else +# include +#endif +int main(void) { + int stack_var[16]; + int32x4x4_t v = vld1q_s32_x4(stack_var); + (void)v; + return 0; +} +EOF + if try $CC -c $CFLAGS -march=native $test.c; then + NEON_HAS_LD4=1 + echo "check whether compiler supports 4 wide register loads ... Yes." | tee -a configure.log + else + NEON_HAS_LD4=0 + echo "check whether compiler supports 4 wide register loads ... No." | tee -a configure.log + fi +} + check_pclmulqdq_intrinsics() { # Check whether compiler supports PCLMULQDQ intrinsics cat > $test.c << EOF @@ -1658,6 +1681,7 @@ EOF if test $without_optimizations -eq 0; then check_acle_compiler_flag check_neon_compiler_flag + check_neon_ld4_intrinsics fi case "${ARCH}" in @@ -1700,6 +1724,11 @@ EOF neonflag="-mfpu=neon" fi + if test $NEON_HAS_LD4 -eq 1; then + CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" + SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" + fi + CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" @@ -1722,6 +1751,11 @@ EOF neonflag="-mfpu=neon" fi + if test $NEON_HAS_LD4 -eq 1; then + CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" + SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" + fi + CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" @@ -1750,6 +1784,11 @@ EOF neonflag="-mfpu=neon" fi + if test $NEON_HAS_LD4 -eq 1; then + CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" + SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" + fi + CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" @@ -1793,6 +1832,11 @@ EOF fi fi + if test $NEON_HAS_LD4 -eq 1; then + CFLAGS="${CFLAGS} -DARM_NEON_HASLD4" + SFLAGS="${SFLAGS} -DARM_NEON_HASLD4" + fi + if test $buildacle -eq 1; then if test $native -eq 0; then ARCH="${ARCH}+crc" diff --git a/fallback_builtins.h b/fallback_builtins.h index 5aaa2c681e..ee623a66f2 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -37,10 +37,10 @@ static __forceinline unsigned long long __builtin_ctzll(uint64_t value) { return trailing_zero; } #define HAVE_BUILTIN_CTZLL -#endif +#endif // Microsoft AMD64 -#endif -#endif +#endif // Microsoft AMD64/IA64/x86/ARM/ARM64 test +#endif // _MSC_VER & !clang /* Unfortunately GCC didn't support these things until version 10 */ #ifdef __AVX2__ @@ -63,4 +63,43 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { #endif // gcc version 10 test #endif // __AVX2__ + +#ifdef ARM_NEON_SLIDEHASH + +#define vqsubq_u16_x4_x1(out, a, b) do { \ + out.val[0] = vqsubq_u16(a.val[0], b); \ + out.val[1] = vqsubq_u16(a.val[1], b); \ + out.val[2] = vqsubq_u16(a.val[2], b); \ + out.val[3] = vqsubq_u16(a.val[3], b); \ +} while (0) + +/* Have to check for hard float ABI on GCC/clang, but not + * on MSVC (we don't compile for the soft float ABI on windows) + */ +#if !defined(ARM_NEON_HASLD4) && (defined(__ARM_FP) || defined(_MSC_VER)) + +#ifdef _M_ARM64 +# include +#else +# include +#endif + +static inline uint16x8x4_t vld1q_u16_x4(uint16_t *a) { + uint16x8x4_t ret = (uint16x8x4_t) {{ + vld1q_u16(a), + vld1q_u16(a+8), + vld1q_u16(a+16), + vld1q_u16(a+24)}}; + return ret; +} + +static inline void vst1q_u16_x4(uint16_t *p, uint16x8x4_t a) { + vst1q_u16(p, a.val[0]); + vst1q_u16(p + 8, a.val[1]); + vst1q_u16(p + 16, a.val[2]); + vst1q_u16(p + 24, a.val[3]); +} +#endif // HASLD4 check and hard float +#endif // ARM_NEON_SLIDEHASH + #endif // include guard FALLBACK_BUILTINS_H diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index e651233609..1dc0815a3b 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -25,12 +25,13 @@ RC = rc CP = copy /y CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) WFLAGS = \ + -D_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 \ -D_CRT_SECURE_NO_DEPRECATE \ -D_CRT_NONSTDC_NO_DEPRECATE \ + -DARM_NEON_HASLD4 \ + -DARM_FEATURES \ -DUNALIGNED_OK \ -DUNALIGNED64_OK \ - -D_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 \ - -DARM_FEATURES \ # LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest ARFLAGS = -nologo diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 29ce955811..7628b617fe 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -25,11 +25,12 @@ RC = rc CP = copy /y CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) WFLAGS = \ + -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 \ -D_CRT_SECURE_NO_DEPRECATE \ -D_CRT_NONSTDC_NO_DEPRECATE \ - -DUNALIGNED_OK \ - -D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1 \ -DARM_FEATURES \ + -DARM_NEON_HASLD4 \ + -DUNALIGNED_OK \ # LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest ARFLAGS = -nologo From 748127e51cfd368923f688cfa74ae784d2f1998a Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Tue, 1 Feb 2022 16:20:38 +0200 Subject: [PATCH 253/798] [Benchmarks] Fix adler32/vmx benchmark not found under 32-bit PowerPC --- test/benchmarks/benchmark_adler32.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index d391f7b17f..c3fc46dc0c 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -69,11 +69,14 @@ BENCHMARK_ADLER32(c, adler32_c, 1); #ifdef ARM_NEON_ADLER32 BENCHMARK_ADLER32(neon, adler32_neon, arm_cpu_has_neon); -#elif defined(POWER8_VSX_ADLER32) -BENCHMARK_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07); -#elif defined(PPC_VMX_ADLER32) +#endif + +#ifdef PPC_VMX_ADLER32 BENCHMARK_ADLER32(vmx, adler32_vmx, power_cpu_has_altivec); #endif +#ifdef POWER8_VSX_ADLER32 +BENCHMARK_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07); +#endif #ifdef X86_SSSE3_ADLER32 BENCHMARK_ADLER32(ssse3, adler32_ssse3, x86_cpu_has_ssse3); From b52fec58ffe6585b3a4048c97805f150189a0895 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 3 Feb 2022 14:31:10 -0800 Subject: [PATCH 254/798] Enable code coverage build only when code coverage report name specified. --- .github/workflows/cmake.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8319fa1a7f..187e37e0b9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -410,7 +410,7 @@ jobs: run: | mkdir ${{ matrix.build-dir || '.not-used' }} cd ${{ matrix.build-dir || '.' }} - cmake ${{ matrix.build-src-dir || '.' }} ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=ON -DWITH_CODE_COVERAGE=ON -DWITH_MAINTAINER_WARNINGS=ON + cmake ${{ matrix.build-src-dir || '.' }} ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=ON ${{ matrix.codecov && '-DWITH_CODE_COVERAGE=ON' }} -DWITH_MAINTAINER_WARNINGS=ON env: CC: ${{ matrix.compiler }} CFLAGS: ${{ matrix.cflags }} From 4dbcd05abf9ef544a59fa2e7b35c0f01ba542608 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 3 Feb 2022 15:02:14 -0800 Subject: [PATCH 255/798] Remove code coverage libraries which introduce memory leak on exit. --- .github/workflows/cmake.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 187e37e0b9..6700810783 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -313,7 +313,6 @@ jobs: packages: ninja-build llvm-11-tools gcov-exec: llvm-cov-11 gcov cflags: -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins - codecov: ubuntu_clang_msan - name: Windows MSVC Win32 os: windows-latest From 036d46c0ca2dc106986ab3ee347f804a1ac32247 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 3 Feb 2022 15:14:56 -0800 Subject: [PATCH 256/798] Add wine repositories only when needed. --- .github/workflows/cmake.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 6700810783..f99e6b1407 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -373,11 +373,15 @@ jobs: repository: zlib-ng/corpora path: test/data/corpora + - name: Add repositories (Wine) + if: contains(matrix.packages, 'wine') + run: | + sudo dpkg --add-architecture i386 + sudo apt-add-repository ppa:ondrej/php -y + - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages run: | - sudo dpkg --add-architecture i386 # Required for wine32 - sudo apt-add-repository ppa:ondrej/php -y sudo apt-get update sudo apt-get install -y ${{ matrix.packages }} From ee9ebafe1f0fd418102ab74a7cdfd5a4d70e845f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 4 Feb 2022 08:47:54 -0800 Subject: [PATCH 257/798] Install codecov tools only after successful build and test. --- .github/workflows/cmake.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index f99e6b1407..f45a2261c1 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -397,11 +397,6 @@ jobs: env: HOMEBREW_NO_INSTALL_CLEANUP: 1 - - name: Install codecov.io tools - if: matrix.codecov - run: | - python -u -m pip install --user codecov - - name: Initialize Wine # Prevent parallel test jobs from initializing Wine at the same time if: contains(matrix.packages, 'wine') @@ -441,6 +436,7 @@ jobs: if: matrix.codecov && ( env.CODECOV_TOKEN_SECRET != '' || github.repository == 'zlib-ng/zlib-ng' ) shell: bash run: | + python -u -m pip install --user codecov bash tools/codecov-upload.sh env: # Codecov does not yet support GitHub Actions From ac250aed9c982b60dd7a503bbaa93a9cbf963d75 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Thu, 3 Feb 2022 18:23:45 -0500 Subject: [PATCH 258/798] Obtained more ILP with VMX by breaking a data dependency By unrolling and finding the equivalent recurrence relation here, we can do more independent sums, maximizing ILP. For when the data size fits into cache, we get a sizable return. For when we don't, it's minor but still measurable. Testing was done on a quad Powermac G5 at 2.5Ghz. --- arch/power/adler32_vmx.c | 74 ++++++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index 491d8d5dfc..3b5c3e2f7e 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -21,7 +21,11 @@ static inline void vmx_handle_head_or_tail(uint32_t *pair, const unsigned char * } static void vmx_accum32(uint32_t *s, const unsigned char *buf, size_t len) { - const vector unsigned char t0 = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; + /* Different taps for the separable components of sums */ + const vector unsigned char t0 = {64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49}; + const vector unsigned char t1 = {48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33}; + const vector unsigned char t2 = {32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17}; + const vector unsigned char t3 = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; /* As silly and inefficient as it seems, creating 1 permutation vector to permute * a 2 element vector from a single load + a subsequent shift is just barely faster * than doing 2 indexed insertions into zero initialized vectors from unaligned memory. */ @@ -32,38 +36,72 @@ static void vmx_accum32(uint32_t *s, const unsigned char *buf, size_t len) { adacc = vec_perm(pair_vec, pair_vec, s0_perm); s2acc = vec_slo(pair_vec, shift_vec); - vector unsigned int s3acc = vmx_zero(); - vector unsigned int s2acc_0 = s3acc; - vector unsigned int adacc_0 = adacc; + vector unsigned int zero = vmx_zero(); + vector unsigned int s3acc = zero; + vector unsigned int s3acc_0 = zero; + vector unsigned int adacc_prev = adacc; + vector unsigned int adacc_prev_0 = zero; - int num_iter = len / 2; - int rem = len & 1; + vector unsigned int s2acc_0 = zero; + vector unsigned int s2acc_1 = zero; + vector unsigned int s2acc_2 = zero; + + /* Maintain a running sum of a second half, this might help use break yet another + * data dependency bubble in the sum */ + vector unsigned int adacc_0 = zero; + + int num_iter = len / 4; + int rem = len & 3; for (int i = 0; i < num_iter; ++i) { vector unsigned char d0 = vec_ld(0, buf); vector unsigned char d1 = vec_ld(16, buf); + vector unsigned char d2 = vec_ld(32, buf); + vector unsigned char d3 = vec_ld(48, buf); + /* The core operation of the loop, basically + * what is being unrolled below */ adacc = vec_sum4s(d0, adacc); - s3acc = vec_add(s3acc, adacc_0); + s3acc = vec_add(s3acc, adacc_prev); + s3acc_0 = vec_add(s3acc_0, adacc_prev_0); s2acc = vec_msum(t0, d0, s2acc); - s3acc = vec_add(s3acc, adacc); - adacc = vec_sum4s(d1, adacc); - s2acc_0 = vec_msum(t0, d1, s2acc_0); - adacc_0 = adacc; - - buf += 32; + /* interleave dependent sums in here */ + adacc_0 = vec_sum4s(d1, adacc_0); + s2acc_0 = vec_msum(t1, d1, s2acc_0); + adacc = vec_sum4s(d2, adacc); + s2acc_1 = vec_msum(t2, d2, s2acc_1); + s2acc_2 = vec_msum(t3, d3, s2acc_2); + adacc_0 = vec_sum4s(d3, adacc_0); + + adacc_prev = adacc; + adacc_prev_0 = adacc_0; + buf += 64; } + adacc = vec_add(adacc, adacc_0); + s3acc = vec_add(s3acc, s3acc_0); + s3acc = vec_sl(s3acc, vec_splat_u32(6)); + if (rem) { - vector unsigned char d0 = vec_ld(0, buf); - s3acc = vec_add(s3acc, adacc); - s2acc = vec_msum(t0, d0, s2acc); - adacc = vec_sum4s(d0, adacc); + adacc_prev = vec_add(adacc_prev_0, adacc_prev); + adacc_prev = vec_sl(adacc_prev, vec_splat_u32(4)); + while (rem--) { + vector unsigned char d0 = vec_ld(0, buf); + adacc = vec_sum4s(d0, adacc); + s3acc = vec_add(s3acc, adacc_prev); + s2acc = vec_msum(t3, d0, s2acc); + adacc_prev = vec_sl(adacc, vec_splat_u32(4)); + buf += 16; + } } + + /* Sum up independent second sums */ s2acc = vec_add(s2acc, s2acc_0); - s3acc = vec_sl(s3acc, vec_splat_u32(4)); + s2acc_2 = vec_add(s2acc_1, s2acc_2); + s2acc = vec_add(s2acc, s2acc_2); + s2acc = vec_add(s2acc, s3acc); adacc = vec_add(adacc, vec_sld(adacc, adacc, 8)); From 91e6fd1b6ea679f8c89a373b2a4e79d2526c904d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 30 Jan 2022 09:34:02 -0800 Subject: [PATCH 259/798] Added power8 cpu flag to powerpc64 CMake toolchain files. --- cmake/toolchain-powerpc64.cmake | 2 +- cmake/toolchain-powerpc64le.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/toolchain-powerpc64.cmake b/cmake/toolchain-powerpc64.cmake index 42a5a44b7d..80d8b904e7 100644 --- a/cmake/toolchain-powerpc64.cmake +++ b/cmake/toolchain-powerpc64.cmake @@ -6,7 +6,7 @@ set(CMAKE_C_COMPILER_TARGET powerpc64-linux-gnu) set(CMAKE_CXX_COMPILER_TARGET powerpc64-linux-gnu) set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64 -L /usr/${CMAKE_C_COMPILER_TARGET}/) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64 -cpu power8 -L /usr/${CMAKE_C_COMPILER_TARGET}/) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) diff --git a/cmake/toolchain-powerpc64le.cmake b/cmake/toolchain-powerpc64le.cmake index bb6391a481..68381de120 100644 --- a/cmake/toolchain-powerpc64le.cmake +++ b/cmake/toolchain-powerpc64le.cmake @@ -6,7 +6,7 @@ set(CMAKE_C_COMPILER_TARGET powerpc64le-linux-gnu) set(CMAKE_CXX_COMPILER_TARGET powerpc64le-linux-gnu) set(CMAKE_CROSSCOMPILING TRUE) -set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64le -L /usr/${CMAKE_C_COMPILER_TARGET}/) +set(CMAKE_CROSSCOMPILING_EMULATOR qemu-ppc64le -cpu power8 -L /usr/${CMAKE_C_COMPILER_TARGET}/) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) From cc361feaad1c42f7919a83843a1f1488b5ed3b53 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 5 Feb 2022 11:47:03 -0800 Subject: [PATCH 260/798] Rename CPU feature header and source files for consistency. --- CMakeLists.txt | 15 ++++++++------- arch/arm/Makefile.in | 10 +++++----- arch/arm/{armfeature.c => arm_features.c} | 0 arch/arm/{arm.h => arm_features.h} | 2 +- arch/power/Makefile.in | 12 ++++++------ arch/power/{power.c => power_features.c} | 4 ++-- arch/power/{power.h => power_features.h} | 2 +- arch/s390/Makefile.in | 8 ++++---- arch/s390/{s390.c => s390_features.c} | 2 +- arch/s390/{s390.h => s390_features.h} | 4 ++-- arch/x86/Makefile.in | 10 +++++----- arch/x86/crc32_fold_pclmulqdq.c | 2 +- arch/x86/{x86.c => x86_features.c} | 2 +- arch/x86/{x86.h => x86_features.h} | 6 +++--- configure | 20 ++++++++++---------- cpu_features.h | 8 ++++---- fallback_builtins.h | 8 ++++---- win32/Makefile.a64 | 4 ++-- win32/Makefile.arm | 4 ++-- win32/Makefile.msc | 4 ++-- 20 files changed, 64 insertions(+), 63 deletions(-) rename arch/arm/{armfeature.c => arm_features.c} (100%) rename arch/arm/{arm.h => arm_features.h} (83%) rename arch/power/{power.c => power_features.c} (91%) rename arch/power/{power.h => power_features.h} (87%) rename arch/s390/{s390.c => s390_features.c} (87%) rename arch/s390/{s390.h => s390_features.h} (66%) rename arch/x86/{x86.c => x86_features.c} (98%) rename arch/x86/{x86.h => x86_features.h} (84%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ccac51cbf1..472cf2f092 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -600,8 +600,8 @@ if(WITH_OPTIM) endif() endif() endif() - list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm.h) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/armfeature.c) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/arm_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/arm_features.c) if(WITH_ACLE AND NOT MSVC AND NOT "${ARCH}" MATCHES "armv[2-7]") check_acle_compiler_flag() if(HAVE_ACLE_FLAG) @@ -645,8 +645,8 @@ if(WITH_OPTIM) check_power8_intrinsics() endif() if(HAVE_VMX OR HAVE_POWER8_INTRIN) - list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power.h) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power.c) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power_features.c) endif() # VMX specific options and files if(WITH_ALTIVEC) @@ -686,7 +686,8 @@ if(WITH_OPTIM) elseif(BASEARCH_S360_FOUND) if(WITH_CRC32_VX) add_definitions(-DS390_FEATURES) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/s390.c) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/s390_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/s390_features.c) endif() if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/dfltcc_common.c) @@ -712,8 +713,8 @@ if(WITH_OPTIM) endif() elseif(BASEARCH_X86_FOUND) add_definitions(-DX86_FEATURES) - list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/x86.h) - list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/x86.c) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/x86_features.h) + list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/x86_features.c) if(MSVC) list(APPEND ZLIB_ARCH_HDRS fallback_builtins.h) endif() diff --git a/arch/arm/Makefile.in b/arch/arm/Makefile.in index 39c9a6a3bb..f47325c231 100644 --- a/arch/arm/Makefile.in +++ b/arch/arm/Makefile.in @@ -18,7 +18,7 @@ TOPDIR=$(SRCTOP) all: \ adler32_neon.o adler32_neon.lo \ - armfeature.o armfeature.lo \ + arm_features.o arm_features.lo \ chunkset_neon.o chunkset_neon.lo \ crc32_acle.o crc32_acle.lo \ slide_hash_neon.o slide_hash_neon.lo \ @@ -30,11 +30,11 @@ adler32_neon.o: adler32_neon.lo: $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_neon.c -armfeature.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c +arm_features.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arm_features.c -armfeature.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/armfeature.c +arm_features.lo: + $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/arm_features.c chunkset_neon.o: $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c diff --git a/arch/arm/armfeature.c b/arch/arm/arm_features.c similarity index 100% rename from arch/arm/armfeature.c rename to arch/arm/arm_features.c diff --git a/arch/arm/arm.h b/arch/arm/arm_features.h similarity index 83% rename from arch/arm/arm.h rename to arch/arm/arm_features.h index 378006efbd..7998e79422 100644 --- a/arch/arm/arm.h +++ b/arch/arm/arm_features.h @@ -1,4 +1,4 @@ -/* arm.h -- check for ARM features. +/* arm_features.h -- check for ARM features. * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index 344b221044..ca0e2ba9ca 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -17,8 +17,8 @@ SRCDIR=. SRCTOP=../.. TOPDIR=$(SRCTOP) -all: power.o \ - power.lo \ +all: power_features.o \ + power_features.lo \ adler32_power8.o \ adler32_power8.lo \ adler32_vmx.o \ @@ -32,11 +32,11 @@ all: power.o \ slide_hash_vmx.o \ slide_hash_vmx.lo -power.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power.c +power_features.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power_features.c -power.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power.c +power_features.lo: + $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/power_features.c adler32_power8.o: $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_power8.c diff --git a/arch/power/power.c b/arch/power/power_features.c similarity index 91% rename from arch/power/power.c rename to arch/power/power_features.c index d17fe3f4f3..60c5e53f2f 100644 --- a/arch/power/power.c +++ b/arch/power/power_features.c @@ -1,4 +1,4 @@ -/* POWER feature check +/* power_features.c - POWER feature check * Copyright (C) 2020 Matheus Castanho , IBM * Copyright (C) 2021 Mika T. Lindqvist * For conditions of distribution and use, see copyright notice in zlib.h @@ -6,7 +6,7 @@ #include #include "../../zutil.h" -#include "power.h" +#include "power_features.h" Z_INTERNAL int power_cpu_has_altivec = 0; Z_INTERNAL int power_cpu_has_arch_2_07 = 0; diff --git a/arch/power/power.h b/arch/power/power_features.h similarity index 87% rename from arch/power/power.h rename to arch/power/power_features.h index 81ce009617..077bec1158 100644 --- a/arch/power/power.h +++ b/arch/power/power_features.h @@ -1,4 +1,4 @@ -/* power.h -- check for POWER CPU features +/* power_features.h -- check for POWER CPU features * Copyright (C) 2020 Matheus Castanho , IBM * Copyright (C) 2021 Mika T. Lindqvist * For conditions of distribution and use, see copyright notice in zlib.h diff --git a/arch/s390/Makefile.in b/arch/s390/Makefile.in index 9780f24cff..39b5aae619 100644 --- a/arch/s390/Makefile.in +++ b/arch/s390/Makefile.in @@ -14,11 +14,11 @@ SRCDIR=. SRCTOP=../.. TOPDIR=$(SRCTOP) -s390.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/s390.c +s390_features.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/s390_features.c -s390.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/s390.c +s390_features.lo: + $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/s390_features.c dfltcc_common.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/dfltcc_common.c diff --git a/arch/s390/s390.c b/arch/s390/s390_features.c similarity index 87% rename from arch/s390/s390.c rename to arch/s390/s390_features.c index a67bfc249a..1051d116a0 100644 --- a/arch/s390/s390.c +++ b/arch/s390/s390_features.c @@ -1,5 +1,5 @@ #include "zutil.h" -#include "s390.h" +#include "s390_features.h" #include diff --git a/arch/s390/s390.h b/arch/s390/s390_features.h similarity index 66% rename from arch/s390/s390.h rename to arch/s390/s390_features.h index 453c58137c..1e27b23865 100644 --- a/arch/s390/s390.h +++ b/arch/s390/s390_features.h @@ -1,5 +1,5 @@ -#ifndef S390_H_ -#define S390_H_ +#ifndef S390_FEATURES_H_ +#define S390_FEATURES_H_ #include "zutil.h" diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index f0d7c38f9f..9ef328ebef 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -24,7 +24,7 @@ SRCTOP=../.. TOPDIR=$(SRCTOP) all: \ - x86.o x86.lo \ + x86_features.o x86_features.lo \ adler32_avx2.o adler32_avx2.lo \ adler32_avx512.o adler32_avx512.lo \ adler32_avx512_vnni.o adler32_avx512_vnni.lo \ @@ -40,11 +40,11 @@ all: \ slide_hash_avx2.o slide_hash_avx2.lo \ slide_hash_sse2.o slide_hash_sse2.lo -x86.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c +x86_features.o: + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c -x86.lo: - $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86.c +x86_features.lo: + $(CC) $(SFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/x86_features.c chunkset_avx.o: $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_avx.c diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index d801c8ccb1..2548bfbea3 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -24,7 +24,7 @@ #include #include // _mm_extract_epi32 -#include "x86.h" +#include "x86_features.h" #include "../../crc32_fold.h" diff --git a/arch/x86/x86.c b/arch/x86/x86_features.c similarity index 98% rename from arch/x86/x86.c rename to arch/x86/x86_features.c index aec5062616..72ef885e82 100644 --- a/arch/x86/x86.c +++ b/arch/x86/x86_features.c @@ -1,4 +1,4 @@ -/* x86.c - x86 feature check +/* x86_features.c - x86 feature check * * Copyright (C) 2013 Intel Corporation. All rights reserved. * Author: diff --git a/arch/x86/x86.h b/arch/x86/x86_features.h similarity index 84% rename from arch/x86/x86.h rename to arch/x86/x86_features.h index 2e56c5d567..97630ab6e6 100644 --- a/arch/x86/x86.h +++ b/arch/x86/x86_features.h @@ -1,10 +1,10 @@ -/* x86.h -- check for CPU features +/* x86_features.h -- check for CPU features * Copyright (C) 2013 Intel Corporation Jim Kukunas * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifndef CPU_H_ -#define CPU_H_ +#ifndef X86_FEATURES_H_ +#define X86_FEATURES_H_ extern int x86_cpu_has_avx2; extern int x86_cpu_has_avx512; diff --git a/configure b/configure index 93b109b7ca..126124a6c4 100755 --- a/configure +++ b/configure @@ -1479,8 +1479,8 @@ case "${ARCH}" in CFLAGS="${CFLAGS} -DX86_FEATURES" SFLAGS="${SFLAGS} -DX86_FEATURES" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} x86.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} x86.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} x86_features.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} x86_features.lo" check_avx2_intrinsics @@ -1601,8 +1601,8 @@ case "${ARCH}" in if test $without_optimizations -eq 0; then CFLAGS="${CFLAGS} -DARM_FEATURES" SFLAGS="${SFLAGS} -DARM_FEATURES" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} armfeature.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} armfeature.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} arm_features.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} arm_features.lo" if test $LINUX -eq 1; then cat > $test.c < $test.c < #ifdef X86_FEATURES -# include "arch/x86/x86.h" +# include "arch/x86/x86_features.h" #endif /* This is not a general purpose replacement for __builtin_ctz. The function expects that value is != 0 @@ -37,7 +37,7 @@ static __forceinline unsigned long long __builtin_ctzll(uint64_t value) { return trailing_zero; } #define HAVE_BUILTIN_CTZLL -#endif // Microsoft AMD64 +#endif // Microsoft AMD64 #endif // Microsoft AMD64/IA64/x86/ARM/ARM64 test #endif // _MSC_VER & !clang @@ -73,7 +73,7 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { out.val[3] = vqsubq_u16(a.val[3], b); \ } while (0) -/* Have to check for hard float ABI on GCC/clang, but not +/* Have to check for hard float ABI on GCC/clang, but not * on MSVC (we don't compile for the soft float ABI on windows) */ #if !defined(ARM_NEON_HASLD4) && (defined(__ARM_FP) || defined(_MSC_VER)) @@ -102,4 +102,4 @@ static inline void vst1q_u16_x4(uint16_t *p, uint16x8x4_t a) { #endif // HASLD4 check and hard float #endif // ARM_NEON_SLIDEHASH -#endif // include guard FALLBACK_BUILTINS_H +#endif // include guard FALLBACK_BUILTINS_H diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 1dc0815a3b..4df6f3d080 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -45,7 +45,7 @@ SUFFIX = OBJS = \ adler32.obj \ - armfeature.obj \ + arm_features.obj \ chunkset.obj \ compare256.obj \ compress.obj \ @@ -181,7 +181,7 @@ SRCDIR = $(TOP) # Keep the dependences in sync with top-level Makefile.in adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h -functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86.h +functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86_features.h gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 7628b617fe..4cc902888d 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -48,7 +48,7 @@ SUFFIX = OBJS = \ adler32.obj \ - armfeature.obj \ + arm_features.obj \ chunkset.obj \ compare256.obj \ compress.obj \ @@ -192,7 +192,7 @@ $(TOP)/zconf$(SUFFIX).h: zconf SRCDIR = $(TOP) # Keep the dependences in sync with top-level Makefile.in adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h -functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86.h +functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86_features.h gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 0059606c5a..56b97dbc8e 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -84,7 +84,7 @@ OBJS = \ trees.obj \ uncompr.obj \ zutil.obj \ - x86.obj \ + x86_features.obj \ # !if "$(ZLIB_COMPAT)" != "" WITH_GZFILEOP = yes @@ -183,7 +183,7 @@ $(TOP)/zconf$(SUFFIX).h: zconf SRCDIR = $(TOP) # Keep the dependences in sync with top-level Makefile.in adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h -functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86.h +functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86_features.h gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h gzwrite.obj: $(SRCDIR)/gzwrite.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h From a877c415af8ffb4921ed659c11c6e51ceceaedb1 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 26 Jan 2022 17:58:52 -0800 Subject: [PATCH 261/798] Only define CPU variants that require deflate_state when deflate.h has previously been included. This allows us to include cpu_features.h without including zlib.h or name mangling. --- cpu_features.h | 3 ++- test/benchmarks/benchmark_slidehash.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cpu_features.h b/cpu_features.h index 6ae66a25e2..89d4a5d992 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -6,7 +6,6 @@ #ifndef CPU_FEATURES #define CPU_FEATURES -#include "deflate.h" #include "crc32_fold.h" #if defined(X86_FEATURES) @@ -128,6 +127,7 @@ extern uint32_t compare256_unaligned_avx2(const uint8_t *src0, const uint8_t *sr #endif #endif +#ifdef DEFLATE_H_ /* insert_string */ extern void insert_string_c(deflate_state *const s, const uint32_t str, uint32_t count); #ifdef X86_SSE42_CRC_HASH @@ -201,5 +201,6 @@ extern uint32_t update_hash_sse4(deflate_state *const s, uint32_t h, uint32_t va #elif defined(ARM_ACLE_CRC_HASH) extern uint32_t update_hash_acle(deflate_state *const s, uint32_t h, uint32_t val); #endif +#endif #endif diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index 7e6557365c..195e7475e1 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -11,8 +11,8 @@ extern "C" { # include "zbuild.h" # include "zutil.h" # include "zutil_p.h" -# include "cpu_features.h" # include "deflate.h" +# include "cpu_features.h" } #include From 405f11bfbf973022f575350bb6873ae847be549d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 3 Feb 2022 17:57:31 -0800 Subject: [PATCH 262/798] Remove duplicate header includes. --- arch/x86/crc32_fold_pclmulqdq.c | 1 - crc32.c | 1 - crc32_comb.c | 1 - deflate_medium.c | 1 - test/benchmarks/benchmark_adler32.cc | 2 -- test/benchmarks/benchmark_compare256.cc | 2 -- test/benchmarks/benchmark_crc32.cc | 2 -- test/benchmarks/benchmark_main.cc | 2 -- test/benchmarks/benchmark_slidehash.cc | 6 ++---- test/fuzz/fuzzer_example_flush.c | 4 ---- 10 files changed, 2 insertions(+), 20 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 2548bfbea3..1ac90b34be 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -19,7 +19,6 @@ #ifdef X86_PCLMULQDQ_CRC #include "../../zbuild.h" -#include #include #include #include // _mm_extract_epi32 diff --git a/crc32.c b/crc32.c index b962fb6b50..493c00c9d4 100644 --- a/crc32.c +++ b/crc32.c @@ -11,7 +11,6 @@ #include "zbuild.h" #include "zendian.h" -#include #include "deflate.h" #include "functable.h" #include "crc32_tbl.h" diff --git a/crc32_comb.c b/crc32_comb.c index 7a6b68a90c..832dbbbc22 100644 --- a/crc32_comb.c +++ b/crc32_comb.c @@ -10,7 +10,6 @@ */ #include "zbuild.h" -#include #include "deflate.h" #include "crc32_p.h" #include "crc32_comb_tbl.h" diff --git a/deflate_medium.c b/deflate_medium.c index c8d3e7701f..1bb21c245b 100644 --- a/deflate_medium.c +++ b/deflate_medium.c @@ -7,7 +7,6 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ #ifndef NO_MEDIUM_STRATEGY -#include #include "zbuild.h" #include "deflate.h" #include "deflate_p.h" diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index c3fc46dc0c..780c0a2161 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -3,9 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include #include -#include #include #include diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 0166816d04..09a81883d3 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -3,9 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include #include -#include #include diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index 68ad3f0f17..57f8fd86d7 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -3,9 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include #include -#include #include #include diff --git a/test/benchmarks/benchmark_main.cc b/test/benchmarks/benchmark_main.cc index fa8195e083..600ac22814 100644 --- a/test/benchmarks/benchmark_main.cc +++ b/test/benchmarks/benchmark_main.cc @@ -3,9 +3,7 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include #include -#include #include diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index 195e7475e1..516da80b76 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -3,10 +3,10 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include -#include #include +#include + extern "C" { # include "zbuild.h" # include "zutil.h" @@ -15,8 +15,6 @@ extern "C" { # include "cpu_features.h" } -#include - #define MAX_RANDOM_INTS 32768 class slide_hash: public benchmark::Fixture { diff --git a/test/fuzz/fuzzer_example_flush.c b/test/fuzz/fuzzer_example_flush.c index 5546a6535b..baa6988e36 100644 --- a/test/fuzz/fuzzer_example_flush.c +++ b/test/fuzz/fuzzer_example_flush.c @@ -1,9 +1,5 @@ #include -#include -#include -#include #include -#include #include "zbuild.h" #ifdef ZLIB_COMPAT From 66c6a63475f8f28b4c569d28e168ef4db94f1db2 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 3 Feb 2022 19:13:59 -0800 Subject: [PATCH 263/798] Fixed short name for CPU features header guard. --- cpu_features.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpu_features.h b/cpu_features.h index 89d4a5d992..51a2f39e92 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -3,8 +3,8 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifndef CPU_FEATURES -#define CPU_FEATURES +#ifndef CPU_FEATURES_H_ +#define CPU_FEATURES_H_ #include "crc32_fold.h" From 5eefff644e382305a7b64f061344aecb73fad88b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 6 Feb 2022 10:06:02 -0800 Subject: [PATCH 264/798] Remove unnecessary zutil.h includes. --- arch/arm/adler32_neon.c | 2 +- arch/arm/arm_features.c | 2 +- arch/arm/chunkset_neon.c | 1 - arch/arm/crc32_acle.c | 2 +- arch/power/adler32_power8.c | 1 - arch/power/adler32_vmx.c | 4 ++-- arch/power/chunkset_power8.c | 3 +-- arch/power/crc32_constants.h | 2 +- arch/power/crc32_power8.c | 2 +- arch/power/power_features.c | 2 +- arch/s390/crc32-vx.c | 2 +- arch/s390/dfltcc_deflate.c | 1 - arch/s390/s390_features.c | 2 +- arch/s390/s390_features.h | 2 -- 14 files changed, 11 insertions(+), 17 deletions(-) diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index adda6f61d8..8f49344404 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -10,7 +10,7 @@ #else # include #endif -#include "../../zutil.h" +#include "../../zbuild.h" #include "../../adler32_p.h" static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) { diff --git a/arch/arm/arm_features.c b/arch/arm/arm_features.c index bef9b290ad..195c94992d 100644 --- a/arch/arm/arm_features.c +++ b/arch/arm/arm_features.c @@ -1,4 +1,4 @@ -#include "../../zutil.h" +#include "../../zbuild.h" #if defined(__linux__) # include diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index e0ad3e04ea..1e173b9075 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -9,7 +9,6 @@ # include #endif #include "../../zbuild.h" -#include "../../zutil.h" typedef uint8x16_t chunk_t; diff --git a/arch/arm/crc32_acle.c b/arch/arm/crc32_acle.c index 88ba6c38c6..6f6ed45373 100644 --- a/arch/arm/crc32_acle.c +++ b/arch/arm/crc32_acle.c @@ -9,7 +9,7 @@ #ifndef _MSC_VER # include #endif -#include "../../zutil.h" +#include "../../zbuild.h" uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len) { Z_REGISTER uint32_t c; diff --git a/arch/power/adler32_power8.c b/arch/power/adler32_power8.c index fc4086322e..f39f00246c 100644 --- a/arch/power/adler32_power8.c +++ b/arch/power/adler32_power8.c @@ -40,7 +40,6 @@ #include #include "zbuild.h" -#include "zutil.h" #include "adler32_p.h" /* Vector across sum unsigned int (saturate). */ diff --git a/arch/power/adler32_vmx.c b/arch/power/adler32_vmx.c index 3b5c3e2f7e..6b7d9153b4 100644 --- a/arch/power/adler32_vmx.c +++ b/arch/power/adler32_vmx.c @@ -7,7 +7,7 @@ #ifdef PPC_VMX_ADLER32 #include -#include "zutil.h" +#include "zbuild.h" #include "adler32_p.h" #define vmx_zero() (vec_splat_u32(0)) @@ -35,7 +35,7 @@ static void vmx_accum32(uint32_t *s, const unsigned char *buf, size_t len) { vector unsigned int pair_vec = vec_ld(0, s); adacc = vec_perm(pair_vec, pair_vec, s0_perm); s2acc = vec_slo(pair_vec, shift_vec); - + vector unsigned int zero = vmx_zero(); vector unsigned int s3acc = zero; vector unsigned int s3acc_0 = zero; diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index a76f66334c..e66de9ed29 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -4,8 +4,7 @@ #ifdef POWER8_VSX_CHUNKSET #include -#include "zbuild.h" -#include "zutil.h" +#include "../../zbuild.h" typedef vector unsigned char chunk_t; diff --git a/arch/power/crc32_constants.h b/arch/power/crc32_constants.h index 7b0ec93b4a..8c8f2153b6 100644 --- a/arch/power/crc32_constants.h +++ b/arch/power/crc32_constants.h @@ -7,7 +7,7 @@ */ #include "zendian.h" -#include "zutil.h" +#include "zbuild.h" /* Reduce 262144 kbits to 1024 bits */ static const __vector unsigned long long vcrc_const[255] ALIGNED_(16) = { diff --git a/arch/power/crc32_power8.c b/arch/power/crc32_power8.c index 17414b394e..c418ed4f48 100644 --- a/arch/power/crc32_power8.c +++ b/arch/power/crc32_power8.c @@ -27,7 +27,7 @@ #include #include "zendian.h" -#include "zutil.h" +#include "zbuild.h" #include "crc32_constants.h" #include "crc32_tbl.h" diff --git a/arch/power/power_features.c b/arch/power/power_features.c index 60c5e53f2f..9186b40d83 100644 --- a/arch/power/power_features.c +++ b/arch/power/power_features.c @@ -5,7 +5,7 @@ */ #include -#include "../../zutil.h" +#include "../../zbuild.h" #include "power_features.h" Z_INTERNAL int power_cpu_has_altivec = 0; diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index 3465a57323..e7a6109502 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -12,7 +12,7 @@ * relicensed under the zlib license. */ -#include "zutil.h" +#include "../../zbuild.h" #include "crc32_p.h" #include diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index 519f97ea59..c498e3ecaf 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -14,7 +14,6 @@ */ #include "zbuild.h" -#include "zutil.h" #include "deflate.h" #include "trees_emit.h" #include "dfltcc_deflate.h" diff --git a/arch/s390/s390_features.c b/arch/s390/s390_features.c index 1051d116a0..465fe0f376 100644 --- a/arch/s390/s390_features.c +++ b/arch/s390/s390_features.c @@ -1,4 +1,4 @@ -#include "zutil.h" +#include "../../zbuild.h" #include "s390_features.h" #include diff --git a/arch/s390/s390_features.h b/arch/s390/s390_features.h index 1e27b23865..5ab9e92ee7 100644 --- a/arch/s390/s390_features.h +++ b/arch/s390/s390_features.h @@ -1,8 +1,6 @@ #ifndef S390_FEATURES_H_ #define S390_FEATURES_H_ -#include "zutil.h" - extern int s390_cpu_has_vx; void Z_INTERNAL s390_check_features(void); From be30c77ea90efa553b9c185300a6b3e86bcab7e6 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Mon, 7 Feb 2022 17:54:41 +0200 Subject: [PATCH 265/798] Update NMake GitHub Actions to use Visual Studio 2022 Enterprise. --- .github/workflows/nmake.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index 27c76a06dc..d02065ff76 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -9,40 +9,40 @@ jobs: matrix: include: - name: Windows NMake x86 - os: windows-latest + os: windows-2022 makefile: win32/Makefile.msc vc-vars: x86 - name: Windows NMake x64 compat - os: windows-latest + os: windows-2022 makefile: win32/Makefile.msc vc-vars: x86_amd64 additional-args: ZLIB_COMPAT=yes - name: Windows NMake x64 sprefix - os: windows-latest + os: windows-2022 makefile: win32/Makefile.msc vc-vars: x86_amd64 additional-args: SYMBOL_PREFIX=zTest_ - name: Windows NMake x64 sprefix compat - os: windows-latest + os: windows-2022 makefile: win32/Makefile.msc vc-vars: x86_amd64 additional-args: ZLIB_COMPAT=yes SYMBOL_PREFIX=zTest_ - name: Windows NMake x64 - os: windows-latest + os: windows-2022 makefile: win32/Makefile.msc vc-vars: x86_amd64 - name: Windows NMake ARM No Test - os: windows-latest + os: windows-2022 makefile: win32/Makefile.arm vc-vars: x86_arm - name: Windows NMake ARM64 No Test - os: windows-latest + os: windows-2022 makefile: win32/Makefile.a64 vc-vars: x86_arm64 @@ -53,7 +53,7 @@ jobs: - name: Compile source code shell: cmd run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} - name: Run test cases @@ -61,6 +61,6 @@ jobs: # Don't run tests on Windows ARM if: contains(matrix.vc-vars, 'arm') == false run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ${{ matrix.vc-vars }} nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} test nmake -f ${{ matrix.makefile }} ${{ matrix.additional-args }} testdll From 498fac54e81b173d7b5bbc53f2f6c5716203a271 Mon Sep 17 00:00:00 2001 From: Deniz Bahadir Date: Thu, 23 Dec 2021 01:13:03 +0100 Subject: [PATCH 266/798] Fix compilation with clang-cl on windows Do not include (system) headers when processing these headers with the resource compiler, because it might trip over the headers coming from LLVM. --- zlib-ng.h.in | 2 ++ zlib.h.in | 2 ++ 2 files changed, 4 insertions(+) diff --git a/zlib-ng.h.in b/zlib-ng.h.in index 30deabf1d4..9274f75e6f 100644 --- a/zlib-ng.h.in +++ b/zlib-ng.h.in @@ -33,6 +33,7 @@ # error Include zlib-ng.h for zlib-ng API or zlib.h for zlib-compat API but not both #endif +#ifndef RC_INVOKED #include "zconf-ng.h" #include @@ -40,6 +41,7 @@ #ifndef ZCONFNG_H # error Missing zconf-ng.h add binary output directory to include directories #endif +#endif /* RC_INVOKED */ #ifdef __cplusplus extern "C" { diff --git a/zlib.h.in b/zlib.h.in index 1c2944cef4..d170e25c9c 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -34,6 +34,7 @@ # error Include zlib-ng.h for zlib-ng API or zlib.h for zlib-compat API but not both #endif +#ifndef RC_INVOKED #include "zconf.h" #include @@ -42,6 +43,7 @@ #ifndef ZCONF_H # error Missing zconf.h add binary output directory to include directories #endif +#endif /* RC_INVOKED */ #ifdef __cplusplus extern "C" { From 2fb95de5e89e622db8de8fbfabb713edf86c688b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 9 Jan 2022 14:58:53 -0800 Subject: [PATCH 267/798] Simplify chunk_t type to uint64_t with memcpy calls. --- chunkset.c | 34 +++------------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/chunkset.c b/chunkset.c index 4cc70771f6..cfc6e87f8b 100644 --- a/chunkset.c +++ b/chunkset.c @@ -4,14 +4,7 @@ #include "zbuild.h" -/* Define 8 byte chunks differently depending on unaligned support */ -#if defined(UNALIGNED64_OK) typedef uint64_t chunk_t; -#elif defined(UNALIGNED_OK) -typedef struct chunk_t { uint32_t u32[2]; } chunk_t; -#else -typedef struct chunk_t { uint8_t u8[8]; } chunk_t; -#endif #define CHUNK_SIZE 8 @@ -20,38 +13,17 @@ typedef struct chunk_t { uint8_t u8[8]; } chunk_t; #define HAVE_CHUNKMEMSET_8 static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - *chunk = 0x0101010101010101 * (uint8_t)*from; -#elif defined(UNALIGNED_OK) - chunk->u32[0] = 0x01010101 * (uint8_t)*from; - chunk->u32[1] = chunk->u32[0]; -#else memset(chunk, *from, sizeof(chunk_t)); -#endif } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { -#if defined(UNALIGNED64_OK) - uint32_t half_chunk; - memcpy(&half_chunk, from, sizeof(half_chunk)); - *chunk = 0x0000000100000001 * (uint64_t)half_chunk; -#elif defined(UNALIGNED_OK) - memcpy(&chunk->u32[0], from, sizeof(chunk->u32[0])); - chunk->u32[1] = chunk->u32[0]; -#else - uint8_t *chunkptr = (uint8_t *)chunk; - memcpy(chunkptr, from, sizeof(uint32_t)); - memcpy(chunkptr+4, from, sizeof(uint32_t)); -#endif + uint8_t *dest = (uint8_t *)chunk; + memcpy(dest, from, sizeof(uint32_t)); + memcpy(dest+4, from, sizeof(uint32_t)); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { -#if defined(UNALIGNED_OK) && !defined(UNALIGNED64_OK) - memcpy(&chunk->u32[0], from, sizeof(chunk->u32[0])); - memcpy(&chunk->u32[1], from+4, sizeof(chunk->u32[1])); -#else memcpy(chunk, from, sizeof(uint64_t)); -#endif } static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { From 363a95fb9b8c4bef7225164fa1deb5481a35c3c0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 9 Jan 2022 15:01:23 -0800 Subject: [PATCH 268/798] Introduce zmemcpy to use unaligned access for architectures we know support unaligned access, otherwise use memcpy. --- arch/arm/chunkset_neon.c | 6 +++--- arch/power/chunkset_power8.c | 6 +++--- chunkset.c | 10 +++++----- chunkset_tpl.h | 6 +++--- compare256.c | 8 ++++---- deflate.h | 10 +++++----- inffast.c | 2 +- insert_string_tpl.h | 4 ++-- match_tpl.h | 12 ++++++------ zbuild.h | 15 +++++++++++++++ 10 files changed, 47 insertions(+), 32 deletions(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 1e173b9075..2ca8ce07e5 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -25,19 +25,19 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { uint16_t tmp; - memcpy(&tmp, from, 2); + zmemcpy_2(&tmp, from); *chunk = vreinterpretq_u8_u16(vdupq_n_u16(tmp)); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { uint32_t tmp; - memcpy(&tmp, from, 4); + zmemcpy_4(&tmp, from); *chunk = vreinterpretq_u8_u32(vdupq_n_u32(tmp)); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { uint64_t tmp; - memcpy(&tmp, from, 8); + zmemcpy_8(&tmp, from); *chunk = vreinterpretq_u8_u64(vdupq_n_u64(tmp)); } diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index e66de9ed29..52734cb2df 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -21,19 +21,19 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { uint16_t tmp; - memcpy(&tmp, from, 2); + zmemcpy_2(&tmp, from); *chunk = (vector unsigned char)vec_splats(tmp); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { uint32_t tmp; - memcpy(&tmp, from, 4); + zmemcpy_4(&tmp, from); *chunk = (vector unsigned char)vec_splats(tmp); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { uint64_t tmp; - memcpy(&tmp, from, 8); + zmemcpy_8(&tmp, from); *chunk = (vector unsigned char)vec_splats(tmp); } diff --git a/chunkset.c b/chunkset.c index cfc6e87f8b..14c913ee6a 100644 --- a/chunkset.c +++ b/chunkset.c @@ -18,20 +18,20 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { uint8_t *dest = (uint8_t *)chunk; - memcpy(dest, from, sizeof(uint32_t)); - memcpy(dest+4, from, sizeof(uint32_t)); + zmemcpy_4(dest, from); + zmemcpy_4(dest+4, from); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { - memcpy(chunk, from, sizeof(uint64_t)); + zmemcpy_8(chunk, from); } static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { - chunkmemset_8((uint8_t *)s, chunk); + zmemcpy_8(chunk, (uint8_t *)s); } static inline void storechunk(uint8_t *out, chunk_t *chunk) { - memcpy(out, chunk, sizeof(uint64_t)); + zmemcpy_8(out, chunk); } #define CHUNKSIZE chunksize_c diff --git a/chunkset_tpl.h b/chunkset_tpl.h index dced2895d8..8e6f566443 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -60,20 +60,20 @@ Z_INTERNAL uint8_t* CHUNKCOPY_SAFE(uint8_t *out, uint8_t const *from, unsigned l #endif #if CHUNK_SIZE >= 8 while (len >= 8) { - memcpy(out, from, 8); + zmemcpy_8(out, from); out += 8; from += 8; len -= 8; } #endif if (len >= 4) { - memcpy(out, from, 4); + zmemcpy_4(out, from); out += 4; from += 4; len -= 4; } if (len >= 2) { - memcpy(out, from, 2); + zmemcpy_2(out, from); out += 2; from += 2; len -= 2; diff --git a/compare256.c b/compare256.c index 68c0cf5431..1b693f274f 100644 --- a/compare256.c +++ b/compare256.c @@ -101,8 +101,8 @@ static inline uint32_t compare256_unaligned_32_static(const uint8_t *src0, const do { uint32_t sv, mv, diff; - memcpy(&sv, src0, sizeof(sv)); - memcpy(&mv, src1, sizeof(mv)); + zmemcpy_4(&sv, src0); + zmemcpy_4(&mv, src1); diff = sv ^ mv; if (diff) { @@ -141,8 +141,8 @@ static inline uint32_t compare256_unaligned_64_static(const uint8_t *src0, const do { uint64_t sv, mv, diff; - memcpy(&sv, src0, sizeof(sv)); - memcpy(&mv, src1, sizeof(mv)); + zmemcpy_8(&sv, src0); + zmemcpy_8(&mv, src1); diff = sv ^ mv; if (diff) { diff --git a/deflate.h b/deflate.h index 7f4eb43f9f..87108914ee 100644 --- a/deflate.h +++ b/deflate.h @@ -305,7 +305,7 @@ static inline void put_short(deflate_state *s, uint16_t w) { #if BYTE_ORDER == BIG_ENDIAN w = ZSWAP16(w); #endif - memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); + zmemcpy_2(&s->pending_buf[s->pending], &w); s->pending += 2; } @@ -317,7 +317,7 @@ static inline void put_short_msb(deflate_state *s, uint16_t w) { #if BYTE_ORDER == LITTLE_ENDIAN w = ZSWAP16(w); #endif - memcpy(&s->pending_buf[s->pending], &w, sizeof(w)); + zmemcpy_2(&s->pending_buf[s->pending], &w); s->pending += 2; } @@ -329,7 +329,7 @@ static inline void put_uint32(deflate_state *s, uint32_t dw) { #if BYTE_ORDER == BIG_ENDIAN dw = ZSWAP32(dw); #endif - memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); + zmemcpy_4(&s->pending_buf[s->pending], &dw); s->pending += 4; } @@ -341,7 +341,7 @@ static inline void put_uint32_msb(deflate_state *s, uint32_t dw) { #if BYTE_ORDER == LITTLE_ENDIAN dw = ZSWAP32(dw); #endif - memcpy(&s->pending_buf[s->pending], &dw, sizeof(dw)); + zmemcpy_4(&s->pending_buf[s->pending], &dw); s->pending += 4; } @@ -353,7 +353,7 @@ static inline void put_uint64(deflate_state *s, uint64_t lld) { #if BYTE_ORDER == BIG_ENDIAN lld = ZSWAP64(lld); #endif - memcpy(&s->pending_buf[s->pending], &lld, sizeof(lld)); + zmemcpy_8(&s->pending_buf[s->pending], &lld); s->pending += 8; } diff --git a/inffast.c b/inffast.c index 899534f0dc..58cbad7ef9 100644 --- a/inffast.c +++ b/inffast.c @@ -15,7 +15,7 @@ /* Load 64 bits from IN and place the bytes at offset BITS in the result. */ static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { uint64_t chunk; - memcpy(&chunk, in, sizeof(chunk)); + zmemcpy_8(&chunk, in); #if BYTE_ORDER == LITTLE_ENDIAN return chunk << bits; diff --git a/insert_string_tpl.h b/insert_string_tpl.h index 7d3e46c897..643a5e0e31 100644 --- a/insert_string_tpl.h +++ b/insert_string_tpl.h @@ -29,9 +29,9 @@ # define HASH_CALC_MASK HASH_MASK #endif #ifndef HASH_CALC_READ -# ifdef UNALIGNED_OK +# if BYTE_ORDER == LITTLE_ENDIAN # define HASH_CALC_READ \ - memcpy(&val, strstart, sizeof(val)); + zmemcpy_4(&val, strstart); # else # define HASH_CALC_READ \ val = ((uint32_t)(strstart[0])); \ diff --git a/match_tpl.h b/match_tpl.h index 853a4ad32f..49b9e724aa 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -74,11 +74,11 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif #ifdef UNALIGNED64_OK - memcpy(scan_start, scan, sizeof(uint64_t)); - memcpy(scan_end, scan+offset, sizeof(uint64_t)); + zmemcpy_8(scan_start, scan); + zmemcpy_8(scan_end, scan+offset); #elif defined(UNALIGNED_OK) - memcpy(scan_start, scan, sizeof(uint32_t)); - memcpy(scan_end, scan+offset, sizeof(uint32_t)); + zmemcpy_4(scan_start, scan); + zmemcpy_4(scan_end, scan+offset); #else scan_end[0] = *(scan+offset); scan_end[1] = *(scan+offset+1); @@ -201,9 +201,9 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #endif #ifdef UNALIGNED64_OK - memcpy(scan_end, scan+offset, sizeof(uint64_t)); + zmemcpy_8(scan_end, scan+offset); #elif defined(UNALIGNED_OK) - memcpy(scan_end, scan+offset, sizeof(uint32_t)); + zmemcpy_4(scan_end, scan+offset); #else scan_end[0] = *(scan+offset); scan_end[1] = *(scan+offset+1); diff --git a/zbuild.h b/zbuild.h index d2b6a922dd..5789eb06d5 100644 --- a/zbuild.h +++ b/zbuild.h @@ -194,4 +194,19 @@ # define Tracecv(c, x) #endif +#ifdef UNALIGNED_OK +# define zmemcpy_2(dest, src) *((uint16_t *)dest) = *((uint16_t *)src) +# define zmemcpy_4(dest, src) *((uint32_t *)dest) = *((uint32_t *)src) +# if UINTPTR_MAX == UINT64_MAX +# define zmemcpy_8(dest, src) *((uint64_t *)dest) = *((uint64_t *)src) +# else +# define zmemcpy_8(dest, src) ((uint32_t *)dest)[0] = *((uint32_t *)src)[0] \ + ((uint32_t *)dest)[1] = *((uint32_t *)src)[1] +# endif +#else +# define zmemcpy_2(dest, src) memcpy(dest, src, 2) +# define zmemcpy_4(dest, src) memcpy(dest, src, 4) +# define zmemcpy_8(dest, src) memcpy(dest, src, 8) +#endif + #endif From ab6665b1bee170c27d229899ed23e6053ebd900b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 26 Jan 2022 10:51:23 -0800 Subject: [PATCH 269/798] Introduce zmemcmp to use unaligned access for architectures we know support unaligned access, otherwise use memcmp. --- deflate_quick.c | 2 +- match_tpl.h | 12 ++++++------ zbuild.h | 29 +++++++++++++++++++++-------- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/deflate_quick.c b/deflate_quick.c index a214a7fe13..a3162675ed 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -92,7 +92,7 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { const uint8_t *str_start = s->window + s->strstart; const uint8_t *match_start = s->window + hash_head; - if (*(uint16_t *)str_start == *(uint16_t *)match_start) { + if (zmemcmp_2(str_start, match_start) == 0) { match_len = functable.compare256(str_start+2, match_start+2) + 2; if (match_len >= WANT_MIN_MATCH) { diff --git a/match_tpl.h b/match_tpl.h index 49b9e724aa..3fc71c15a0 100644 --- a/match_tpl.h +++ b/match_tpl.h @@ -145,24 +145,24 @@ Z_INTERNAL uint32_t LONGEST_MATCH(deflate_state *const s, Pos cur_match) { #ifdef UNALIGNED_OK if (best_len < sizeof(uint32_t)) { for (;;) { - if (*(uint16_t *)(mbase_end+cur_match) == *(uint16_t *)scan_end && - *(uint16_t *)(mbase_start+cur_match) == *(uint16_t *)scan_start) + if (zmemcmp_2(mbase_end+cur_match, scan_end) == 0 && + zmemcmp_2(mbase_start+cur_match, scan_start) == 0) break; GOTO_NEXT_CHAIN; } # ifdef UNALIGNED64_OK } else if (best_len >= sizeof(uint64_t)) { for (;;) { - if (*(uint64_t *)(mbase_end+cur_match) == *(uint64_t *)scan_end && - *(uint64_t *)(mbase_start+cur_match) == *(uint64_t *)scan_start) + if (zmemcmp_8(mbase_end+cur_match, scan_end) == 0 && + zmemcmp_8(mbase_start+cur_match, scan_start) == 0) break; GOTO_NEXT_CHAIN; } # endif } else { for (;;) { - if (*(uint32_t *)(mbase_end+cur_match) == *(uint32_t *)scan_end && - *(uint32_t *)(mbase_start+cur_match) == *(uint32_t *)scan_start) + if (zmemcmp_4(mbase_end+cur_match, scan_end) == 0 && + zmemcmp_4(mbase_start+cur_match, scan_start) == 0) break; GOTO_NEXT_CHAIN; } diff --git a/zbuild.h b/zbuild.h index 5789eb06d5..08bc7ef612 100644 --- a/zbuild.h +++ b/zbuild.h @@ -194,19 +194,32 @@ # define Tracecv(c, x) #endif +/* Force compiler to emit unaligned memory accesses if unaligned access is supported + on the architecture, otherwise don't assume unaligned access is supported. Older + compilers don't optimize memcpy and memcmp calls to unaligned access instructions + when it is supported on the architecture resulting in significant performance impact. + Newer compilers might optimize memcpy but not all optimize memcmp for all integer types. */ #ifdef UNALIGNED_OK -# define zmemcpy_2(dest, src) *((uint16_t *)dest) = *((uint16_t *)src) -# define zmemcpy_4(dest, src) *((uint32_t *)dest) = *((uint32_t *)src) +# define zmemcpy_2(dest, src) (*((uint16_t *)(dest)) = *((uint16_t *)(src))) +# define zmemcmp_2(str1, str2) (*((uint16_t *)(str1)) != *((uint16_t *)(str2))) +# define zmemcpy_4(dest, src) (*((uint32_t *)(dest)) = *((uint32_t *)(src))) +# define zmemcmp_4(str1, str2) (*((uint32_t *)(str1)) != *((uint32_t *)(str2))) # if UINTPTR_MAX == UINT64_MAX -# define zmemcpy_8(dest, src) *((uint64_t *)dest) = *((uint64_t *)src) +# define zmemcpy_8(dest, src) (*((uint64_t *)(dest)) = *((uint64_t *)(src))) +# define zmemcmp_8(str1, str2) (*((uint64_t *)(str1)) != *((uint64_t *)(str2))) # else -# define zmemcpy_8(dest, src) ((uint32_t *)dest)[0] = *((uint32_t *)src)[0] \ - ((uint32_t *)dest)[1] = *((uint32_t *)src)[1] +# define zmemcpy_8(dest, src) (((uint32_t *)(dest))[0] = ((uint32_t *)(src))[0], \ + ((uint32_t *)(dest))[1] = ((uint32_t *)(src))[1]) +# define zmemcmp_8(str1, str2) (((uint32_t *)(str1))[0] != ((uint32_t *)(str2))[0] || \ + ((uint32_t *)(str1))[1] != ((uint32_t *)(str2))[1]) # endif #else -# define zmemcpy_2(dest, src) memcpy(dest, src, 2) -# define zmemcpy_4(dest, src) memcpy(dest, src, 4) -# define zmemcpy_8(dest, src) memcpy(dest, src, 8) +# define zmemcpy_2(dest, src) memcpy(dest, src, 2) +# define zmemcmp_2(str1, str2) memcmp(str1, str2, 2) +# define zmemcpy_4(dest, src) memcpy(dest, src, 4) +# define zmemcmp_4(str1, str2) memcmp(str1, str2, 4) +# define zmemcpy_8(dest, src) memcpy(dest, src, 8) +# define zmemcmp_8(str1, str2) memcmp(str1, str2, 8) #endif #endif From eaa00cd791b01fc9712c66d8d523fc088480e22f Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sat, 22 Jan 2022 22:49:04 -0500 Subject: [PATCH 270/798] Write an SSE2 optimized compare256 The SSE4 variant uses the unfortunate string comparison instructions from SSE4.2 which not only don't work on as many CPUs but, are often slower than the SSE2 counterparts except in very specific circumstances. This version should be ~2x faster than unaligned_64 for larger strings and about half the performance of AVX2 comparisons on identical hardware. This version is meant to supplement pre AVX hardware. Because of this, we're performing 1 extra load + compare at the beginning. In the event that we're doing a full 256 byte comparison (completely equal strings), this will result in 2 extra SIMD comparisons if the inputs are unaligned. Given that the loads will be absorbed by L1, this isn't super likely to be a giant penalty but for something like a core-i first or second gen, where unaligned loads aren't nearly as expensive, this going to be _marginally_ slower in the worst case. This allows us to have half the loads be aligned, so that the compiler can elide the load and compare by using a register relative pcmpeqb. --- CMakeLists.txt | 2 +- arch/x86/Makefile.in | 7 ++ arch/x86/compare256_sse2.c | 97 +++++++++++++++++++++++++ configure | 4 +- cpu_features.h | 9 +++ functable.c | 12 +++ test/benchmarks/benchmark_compare256.cc | 3 + 7 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 arch/x86/compare256_sse2.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 472cf2f092..8d340087fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -802,7 +802,7 @@ if(WITH_OPTIM) check_sse2_intrinsics() if(HAVE_SSE2_INTRIN) add_definitions(-DX86_SSE2 -DX86_SSE2_CHUNKSET -DX86_SSE2_SLIDEHASH) - set(SSE2_SRCS ${ARCHDIR}/chunkset_sse2.c ${ARCHDIR}/slide_hash_sse2.c) + set(SSE2_SRCS ${ARCHDIR}/chunkset_sse2.c ${ARCHDIR}/compare256_sse2.c ${ARCHDIR}/slide_hash_sse2.c) list(APPEND ZLIB_ARCH_SRCS ${SSE2_SRCS}) if(NOT ${ARCH} MATCHES "x86_64") set_property(SOURCE ${SSE2_SRCS} PROPERTY COMPILE_FLAGS "${SSE2FLAG} ${NOLTOFLAG}") diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 9ef328ebef..389fc2f328 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -33,6 +33,7 @@ all: \ chunkset_avx.o chunkset_avx.lo \ chunkset_sse2.o chunkset_sse2.lo \ compare256_avx2.o compare256_avx2.lo \ + compare256_sse2.o compare256_sse2.lo \ compare256_sse42.o compare256_sse42.lo \ insert_string_sse42.o insert_string_sse42.lo \ crc32_fold_pclmulqdq.o crc32_fold_pclmulqdq.lo \ @@ -64,6 +65,12 @@ compare256_avx2.o: compare256_avx2.lo: $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_avx2.c +compare256_sse2.o: + $(CC) $(CFLAGS) $(SSE2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse2.c + +compare256_sse2.lo: + $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse2.c + compare256_sse42.o: $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse42.c diff --git a/arch/x86/compare256_sse2.c b/arch/x86/compare256_sse2.c new file mode 100644 index 0000000000..44d893d982 --- /dev/null +++ b/arch/x86/compare256_sse2.c @@ -0,0 +1,97 @@ +/* compare256_sse2.c -- SSE2 version of compare256 + * Copyright Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" +#include "../../zutil.h" + +#include "fallback_builtins.h" + +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) + +#include + +static inline uint32_t compare256_unaligned_sse2_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + int align_offset = ((uintptr_t)src0) & 15; + const uint8_t *end0 = src0 + 256; + const uint8_t *end1 = src1 + 256; + __m128i xmm_src0, xmm_src1, xmm_cmp; + + /* Do the first load unaligned, than all subsequent ones we have at least + * one aligned load. Sadly aligning both loads is probably unrealistic */ + xmm_src0 = _mm_loadu_si128((__m128i*)src0); + xmm_src1 = _mm_loadu_si128((__m128i*)src1); + xmm_cmp = _mm_cmpeq_epi8(xmm_src0, xmm_src1); + + unsigned mask = (unsigned)_mm_movemask_epi8(xmm_cmp); + + /* Compiler _may_ turn this branch into a ptest + movemask, + * since a lot of those uops are shared and fused */ + if (mask != 0xFFFF) { + uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); + return len + match_byte; + } + + int align_adv = 16 - align_offset; + len += align_adv; + src0 += align_adv; + src1 += align_adv; + + /* Do a flooring division (should just be a shift right) */ + int num_iter = (256 - len) / 16; + + for (int i = 0; i < num_iter; ++i) { + xmm_src0 = _mm_load_si128((__m128i*)src0); + xmm_src1 = _mm_loadu_si128((__m128i*)src1); + xmm_cmp = _mm_cmpeq_epi8(xmm_src0, xmm_src1); + + mask = (unsigned)_mm_movemask_epi8(xmm_cmp); + + /* Compiler _may_ turn this branch into a ptest + movemask, + * since a lot of those uops are shared and fused */ + if (mask != 0xFFFF) { + uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); + return len + match_byte; + } + + len += 16, src0 += 16, src1 += 16; + } + + if (align_offset) { + src0 = end0 - 16; + src1 = end1 - 16; + len = 256 - 16; + + xmm_src0 = _mm_loadu_si128((__m128i*)src0); + xmm_src1 = _mm_loadu_si128((__m128i*)src1); + xmm_cmp = _mm_cmpeq_epi8(xmm_src0, xmm_src1); + + mask = (unsigned)_mm_movemask_epi8(xmm_cmp); + + if (mask != 0xFFFF) { + uint32_t match_byte = (uint32_t)__builtin_ctz(~mask); + return len + match_byte; + } + } + + return 256; +} + +Z_INTERNAL uint32_t compare256_unaligned_sse2(const uint8_t *src0, const uint8_t *src1) { + return compare256_unaligned_sse2_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_unaligned_sse2 +#define COMPARE256 compare256_unaligned_sse2_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_unaligned_sse2 +#define COMPARE256 compare256_unaligned_sse2_static + +#include "match_tpl.h" + +#endif diff --git a/configure b/configure index 126124a6c4..3ea2fe65e9 100755 --- a/configure +++ b/configure @@ -1553,8 +1553,8 @@ case "${ARCH}" in if test ${HAVE_SSE2_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" SFLAGS="${SFLAGS} -DX86_SSE2 -DX86_SSE2_CHUNKSET" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse2.o slide_hash_sse2.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse2.lo slide_hash_sse2.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse2.o compare256_sse2.o slide_hash_sse2.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse2.lo compare256_sse2.lo slide_hash_sse2.lo" if test $forcesse2 -eq 1; then CFLAGS="${CFLAGS} -DX86_NOCHECK_SSE2" diff --git a/cpu_features.h b/cpu_features.h index 51a2f39e92..1f25433660 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -119,6 +119,9 @@ extern uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1 #ifdef UNALIGNED64_OK extern uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1); #endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t compare256_unaligned_sse2(const unsigned char *src0, const unsigned char *src1); +#endif #ifdef X86_SSE42_CMP_STR extern uint32_t compare256_unaligned_sse4(const uint8_t *src0, const uint8_t *src1); #endif @@ -144,6 +147,9 @@ extern uint32_t longest_match_unaligned_32(deflate_state *const s, Pos cur_match #ifdef UNALIGNED64_OK extern uint32_t longest_match_unaligned_64(deflate_state *const s, Pos cur_match); #endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_unaligned_sse2(deflate_state *const s, Pos cur_match); +#endif #ifdef X86_SSE42_CMP_STR extern uint32_t longest_match_unaligned_sse4(deflate_state *const s, Pos cur_match); #endif @@ -160,6 +166,9 @@ extern uint32_t longest_match_slow_unaligned_32(deflate_state *const s, Pos cur_ #ifdef UNALIGNED64_OK extern uint32_t longest_match_slow_unaligned_64(deflate_state *const s, Pos cur_match); #endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) +extern uint32_t longest_match_slow_unaligned_sse2(deflate_state *const s, Pos cur_match); +#endif #ifdef X86_SSE42_CMP_STR extern uint32_t longest_match_slow_unaligned_sse4(deflate_state *const s, Pos cur_match); #endif diff --git a/functable.c b/functable.c index 19d7258e1e..78866a7922 100644 --- a/functable.c +++ b/functable.c @@ -106,6 +106,10 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { # else functable.longest_match = &longest_match_unaligned_16; # endif +# if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_sse2) + functable.longest_match = &longest_match_unaligned_sse2; +# endif # ifdef X86_SSE42_CMP_STR if (x86_cpu_has_sse42) functable.longest_match = &longest_match_unaligned_sse4; @@ -131,6 +135,10 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc # else functable.longest_match_slow = &longest_match_slow_unaligned_16; # endif +# if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_sse2) + functable.longest_match = &longest_match_slow_unaligned_sse2; +# endif # ifdef X86_SSE42_CMP_STR if (x86_cpu_has_sse42) functable.longest_match_slow = &longest_match_slow_unaligned_sse4; @@ -408,6 +416,10 @@ Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { # else functable.compare256 = &compare256_unaligned_16; # endif +# if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_sse2) + functable.compare256 = &compare256_unaligned_sse2; +# endif # ifdef X86_SSE42_CMP_STR if (x86_cpu_has_sse42) functable.compare256 = &compare256_unaligned_sse4; diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 09a81883d3..010453497a 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -72,6 +72,9 @@ BENCHMARK_COMPARE256(unaligned_64, compare256_unaligned_64, 1); #endif #endif +#ifdef X86_SSE2 +BENCHMARK_COMPARE256(unaligned_sse2, compare256_unaligned_sse2, x86_cpu_has_sse2); +#endif #ifdef X86_SSE42_CMP_STR BENCHMARK_COMPARE256(unaligned_sse4, compare256_unaligned_sse4, x86_cpu_has_sse42); #endif From b3260fd0c82c8210668399d53c3277b01cb18a07 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 23 Jan 2022 00:18:17 -0500 Subject: [PATCH 271/798] Axe the SSE4 compare256 functions --- CMakeLists.txt | 7 --- README.md | 2 +- arch/x86/Makefile.in | 7 --- arch/x86/compare256_sse2.c | 1 - arch/x86/compare256_sse42.c | 71 ------------------------- configure | 8 --- cpu_features.h | 11 +--- functable.c | 12 ----- test/benchmarks/benchmark_compare256.cc | 3 -- win32/Makefile.msc | 2 +- 10 files changed, 3 insertions(+), 121 deletions(-) delete mode 100644 arch/x86/compare256_sse42.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d340087fb..000f3ad9bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -787,13 +787,6 @@ if(WITH_OPTIM) add_definitions(-DX86_SSE42_CRC_INTRIN) endif() endif() - if(HAVE_SSE42CMPSTR_INTRIN) - add_definitions(-DX86_SSE42_CMP_STR) - set(SSE42_SRCS ${ARCHDIR}/compare256_sse42.c) - add_feature_info(SSE42_COMPARE256 1 "Support SSE4.2 optimized compare256, using \"${SSE42FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) - set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") - endif() if(NOT HAVE_SSE42CRC_INLINE_ASM AND NOT HAVE_SSE42CRC_INTRIN AND NOT HAVE_SSE42CMPSTR_INTRIN) set(WITH_SSE4 OFF) endif() diff --git a/README.md b/README.md index d70ac82729..3c4fd00b64 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Features * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, ACLE, & IBM Z * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX - * Compare256 implementations using SSE4.2 & AVX2 + * Compare256 implementations using SSE2 & AVX2 * Inflate chunk copying using SSE2, AVX, Neon & VSX * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 389fc2f328..2b90e2ad83 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -34,7 +34,6 @@ all: \ chunkset_sse2.o chunkset_sse2.lo \ compare256_avx2.o compare256_avx2.lo \ compare256_sse2.o compare256_sse2.lo \ - compare256_sse42.o compare256_sse42.lo \ insert_string_sse42.o insert_string_sse42.lo \ crc32_fold_pclmulqdq.o crc32_fold_pclmulqdq.lo \ crc32_fold_vpclmulqdq.o crc32_fold_vpclmulqdq.lo \ @@ -71,12 +70,6 @@ compare256_sse2.o: compare256_sse2.lo: $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse2.c -compare256_sse42.o: - $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse42.c - -compare256_sse42.lo: - $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_sse42.c - insert_string_sse42.o: $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/insert_string_sse42.c diff --git a/arch/x86/compare256_sse2.c b/arch/x86/compare256_sse2.c index 44d893d982..bd5d62cf7b 100644 --- a/arch/x86/compare256_sse2.c +++ b/arch/x86/compare256_sse2.c @@ -4,7 +4,6 @@ */ #include "../../zbuild.h" -#include "../../zutil.h" #include "fallback_builtins.h" diff --git a/arch/x86/compare256_sse42.c b/arch/x86/compare256_sse42.c deleted file mode 100644 index 37a847c45c..0000000000 --- a/arch/x86/compare256_sse42.c +++ /dev/null @@ -1,71 +0,0 @@ -/* compare256_sse42.c -- SSE4.2 version of compare256 - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * Authors: - * Wajdi Feghali - * Jim Guilford - * Vinodh Gopal - * Erdinc Ozturk - * Jim Kukunas - * - * Portions are Copyright (C) 2016 12Sided Technology, LLC. - * Author: - * Phil Vachon - * - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zbuild.h" - -#ifdef X86_SSE42_CMP_STR - -#include -#ifdef _MSC_VER -# include -#endif - -/* UNALIGNED_OK, SSE4.2 intrinsic comparison */ -static inline uint32_t compare256_unaligned_sse4_static(const uint8_t *src0, const uint8_t *src1) { - uint32_t len = 0; - - do { - #define cmp_mode _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH | _SIDD_NEGATIVE_POLARITY - __m128i xmm_src0, xmm_src1; - uint32_t ret; - - xmm_src0 = _mm_loadu_si128((__m128i *)src0); - xmm_src1 = _mm_loadu_si128((__m128i *)src1); - ret = (uint32_t)_mm_cmpestri(xmm_src0, 16, xmm_src1, 16, cmp_mode); - if (_mm_cmpestrc(xmm_src0, 16, xmm_src1, 16, cmp_mode)) { - return len + ret; - } - src0 += 16, src1 += 16, len += 16; - - xmm_src0 = _mm_loadu_si128((__m128i *)src0); - xmm_src1 = _mm_loadu_si128((__m128i *)src1); - ret = (uint32_t)_mm_cmpestri(xmm_src0, 16, xmm_src1, 16, cmp_mode); - if (_mm_cmpestrc(xmm_src0, 16, xmm_src1, 16, cmp_mode)) { - return len + ret; - } - src0 += 16, src1 += 16, len += 16; - } while (len < 256); - - return 256; -} - -Z_INTERNAL uint32_t compare256_unaligned_sse4(const uint8_t *src0, const uint8_t *src1) { - return compare256_unaligned_sse4_static(src0, src1); -} - -#define LONGEST_MATCH longest_match_unaligned_sse4 -#define COMPARE256 compare256_unaligned_sse4_static - -#include "match_tpl.h" - -#define LONGEST_MATCH_SLOW -#define LONGEST_MATCH longest_match_slow_unaligned_sse4 -#define COMPARE256 compare256_unaligned_sse4_static - -#include "match_tpl.h" - -#endif diff --git a/configure b/configure index 3ea2fe65e9..328e1821d8 100755 --- a/configure +++ b/configure @@ -1540,14 +1540,6 @@ case "${ARCH}" in ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse42.lo" fi - if test ${HAVE_SSE42CMPSTR_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE42_CMP_STR" - SFLAGS="${SFLAGS} -DX86_SSE42_CMP_STR" - - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} compare256_sse42.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} compare256_sse42.lo" - fi - check_sse2_intrinsics if test ${HAVE_SSE2_INTRIN} -eq 1; then diff --git a/cpu_features.h b/cpu_features.h index 1f25433660..c0223ae159 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -120,10 +120,7 @@ extern uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1 extern uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1); #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t compare256_unaligned_sse2(const unsigned char *src0, const unsigned char *src1); -#endif -#ifdef X86_SSE42_CMP_STR -extern uint32_t compare256_unaligned_sse4(const uint8_t *src0, const uint8_t *src1); +extern uint32_t compare256_unaligned_sse2(const uint8_t *src0, const uint8_t *src1); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) extern uint32_t compare256_unaligned_avx2(const uint8_t *src0, const uint8_t *src1); @@ -150,9 +147,6 @@ extern uint32_t longest_match_unaligned_64(deflate_state *const s, Pos cur_match #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) extern uint32_t longest_match_unaligned_sse2(deflate_state *const s, Pos cur_match); #endif -#ifdef X86_SSE42_CMP_STR -extern uint32_t longest_match_unaligned_sse4(deflate_state *const s, Pos cur_match); -#endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) extern uint32_t longest_match_unaligned_avx2(deflate_state *const s, Pos cur_match); #endif @@ -169,9 +163,6 @@ extern uint32_t longest_match_slow_unaligned_64(deflate_state *const s, Pos cur_ #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) extern uint32_t longest_match_slow_unaligned_sse2(deflate_state *const s, Pos cur_match); #endif -#ifdef X86_SSE42_CMP_STR -extern uint32_t longest_match_slow_unaligned_sse4(deflate_state *const s, Pos cur_match); -#endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) extern uint32_t longest_match_slow_unaligned_avx2(deflate_state *const s, Pos cur_match); #endif diff --git a/functable.c b/functable.c index 78866a7922..c84f55e42b 100644 --- a/functable.c +++ b/functable.c @@ -110,10 +110,6 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { if (x86_cpu_has_sse2) functable.longest_match = &longest_match_unaligned_sse2; # endif -# ifdef X86_SSE42_CMP_STR - if (x86_cpu_has_sse42) - functable.longest_match = &longest_match_unaligned_sse4; -# endif # if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) functable.longest_match = &longest_match_unaligned_avx2; @@ -139,10 +135,6 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc if (x86_cpu_has_sse2) functable.longest_match = &longest_match_slow_unaligned_sse2; # endif -# ifdef X86_SSE42_CMP_STR - if (x86_cpu_has_sse42) - functable.longest_match_slow = &longest_match_slow_unaligned_sse4; -# endif # if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) functable.longest_match_slow = &longest_match_slow_unaligned_avx2; @@ -420,10 +412,6 @@ Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { if (x86_cpu_has_sse2) functable.compare256 = &compare256_unaligned_sse2; # endif -# ifdef X86_SSE42_CMP_STR - if (x86_cpu_has_sse42) - functable.compare256 = &compare256_unaligned_sse4; -# endif # if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) functable.compare256 = &compare256_unaligned_avx2; diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 010453497a..5a8a98b2dd 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -75,9 +75,6 @@ BENCHMARK_COMPARE256(unaligned_64, compare256_unaligned_64, 1); #ifdef X86_SSE2 BENCHMARK_COMPARE256(unaligned_sse2, compare256_unaligned_sse2, x86_cpu_has_sse2); #endif -#ifdef X86_SSE42_CMP_STR -BENCHMARK_COMPARE256(unaligned_sse4, compare256_unaligned_sse4, x86_cpu_has_sse42); -#endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) BENCHMARK_COMPARE256(unaligned_avx2, compare256_unaligned_avx2, x86_cpu_has_avx2); #endif diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 56b97dbc8e..3d8f1b2e3e 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -55,7 +55,7 @@ OBJS = \ chunkset_sse2.obj \ compare256.obj \ compare256_avx2.obj \ - compare256_sse42.obj \ + compare256_sse2.obj \ compress.obj \ cpu_features.obj \ crc32.obj \ From 7b201fe9c5fc5b1ffd24a05a42182fc86b4aa251 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 18 Feb 2022 01:42:59 +0200 Subject: [PATCH 272/798] [AArch64] Add missing LD4 test for configure. --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 328e1821d8..7c6b769b41 100755 --- a/configure +++ b/configure @@ -1804,6 +1804,8 @@ EOF fi if test $without_optimizations -eq 0; then + check_neon_ld4_intrinsics + CFLAGS="${CFLAGS} -DARM_FEATURES" SFLAGS="${SFLAGS} -DARM_FEATURES" ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} arm_features.o" From 319755304904e9f65644d0e2f5504c123f68794e Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Fri, 18 Feb 2022 08:27:18 +0200 Subject: [PATCH 273/798] Don't use -march=native when doing LD4 test for ARM/AArch64. --- configure | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 7c6b769b41..0ff33c34ce 100755 --- a/configure +++ b/configure @@ -1170,6 +1170,13 @@ EOF } check_neon_ld4_intrinsics() { + if test $buildneon -eq 1 && test $native -eq 0; then + if test "$CC_ARCH" = "aarch64" || test "$CC_ARCH" = "aarch64_be"; then + neonflag="-march=armv8-a+simd" + elif test $MFPU_NEON_AVAILABLE -eq 1; then + neonflag="-mfpu=neon" + fi + fi cat > $test.c << EOF #ifdef _M_ARM64 # include @@ -1183,7 +1190,7 @@ int main(void) { return 0; } EOF - if try $CC -c $CFLAGS -march=native $test.c; then + if try $CC -c $CFLAGS $neonflag $test.c; then NEON_HAS_LD4=1 echo "check whether compiler supports 4 wide register loads ... Yes." | tee -a configure.log else From 321028cde93dac9f47b9b92ad186c4cbffb77cf2 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Mon, 21 Feb 2022 16:46:18 -0500 Subject: [PATCH 274/798] Prevent stale stub functions from being called in deflate_slow Just in case this is the very first call to longest match, we should instead assign the function pointer instead of the function itself. This way, by the time it leaves the stub, the function pointer gets reassigned. This was found incidentally while debugging something else. --- deflate_slow.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/deflate_slow.c b/deflate_slow.c index b8beec9ccd..20fa0f39ac 100644 --- a/deflate_slow.c +++ b/deflate_slow.c @@ -19,12 +19,12 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { int bflush; /* set if current block must be flushed */ int64_t dist; uint32_t match_len; - match_func longest_match; + match_func *longest_match; if (s->max_chain_length <= 1024) - longest_match = functable.longest_match; + longest_match = &functable.longest_match; else - longest_match = functable.longest_match_slow; + longest_match = &functable.longest_match_slow; /* Process the input block. */ for (;;) { @@ -61,7 +61,7 @@ Z_INTERNAL block_state deflate_slow(deflate_state *s, int flush) { * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ - match_len = longest_match(s, hash_head); + match_len = (*longest_match)(s, hash_head); /* longest_match() sets match_start */ if (match_len <= 5 && (s->strategy == Z_FILTERED)) { From 6bdbbc26cebd75175ceb2fd4c27d8a63ebedf54d Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Sun, 6 Feb 2022 21:00:49 +0100 Subject: [PATCH 275/798] IBM Z: Install Codecov dependencies on the self-hosted builder --- arch/s390/self-hosted-builder/actions-runner.Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/s390/self-hosted-builder/actions-runner.Dockerfile b/arch/s390/self-hosted-builder/actions-runner.Dockerfile index 8b9f60945f..5e247fd9d3 100644 --- a/arch/s390/self-hosted-builder/actions-runner.Dockerfile +++ b/arch/s390/self-hosted-builder/actions-runner.Dockerfile @@ -16,9 +16,12 @@ RUN apt-get update && apt-get -y install \ gcc \ git \ jq \ + libxml2-dev \ + libxslt-dev \ ninja-build \ python-is-python3 \ python3 \ + python3-dev \ python3-pip # amd64 dependencies. From 4f27974e5f6e993724a932ebffe2180baea93647 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 11 Feb 2022 17:23:31 -0800 Subject: [PATCH 276/798] Switch to using Codecov GitHub Action. --- .github/workflows/cmake.yml | 34 ++++++++++++++++++++-------------- .github/workflows/pigz.yml | 32 ++++++++++++++++---------------- tools/codecov-upload.sh | 9 --------- 3 files changed, 36 insertions(+), 39 deletions(-) delete mode 100644 tools/codecov-upload.sh diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index f45a2261c1..d5d7c389e9 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -432,20 +432,25 @@ jobs: TSAN_OPTIONS: ${{ matrix.tsan-options || 'verbosity=0' }}:abort_on_error=1 LSAN_OPTIONS: ${{ matrix.lsan-options || 'verbosity=0' }}:abort_on_error=1 - - name: Upload coverage report - if: matrix.codecov && ( env.CODECOV_TOKEN_SECRET != '' || github.repository == 'zlib-ng/zlib-ng' ) + - name: Generate coverage report + if: matrix.codecov shell: bash run: | - python -u -m pip install --user codecov - bash tools/codecov-upload.sh + python3 -u -m pip install --user gcovr + python3 -m gcovr --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root ${{ matrix.build-src-dir || '.' }} --xml --output coverage.xml --verbose + + - name: Upload coverage report + uses: codecov/codecov-action@v2 + if: matrix.codecov && (env.CODECOV_TOKEN != '' || github.repository == 'zlib-ng/zlib-ng') + with: + token: ${{ secrets.CODECOV_TOKEN || 'e4fdf847-f541-4ab1-9d50-3d27e5913906' }} + flags: ${{ matrix.codecov }} + name: ${{ matrix.name }} + directory: ${{ matrix.build-src-dir || '.' }} + verbose: true + fail_ci_if_error: true env: - # Codecov does not yet support GitHub Actions - CODECOV_TOKEN_SECRET: "${{secrets.CODECOV_TOKEN}}" - CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN || 'e4fdf847-f541-4ab1-9d50-3d27e5913906' }}" - CODECOV_FLAGS: "${{ matrix.codecov }}" - CODECOV_NAME: "${{ matrix.name }}" - CODECOV_EXEC: "${{ matrix.gcov-exec || 'gcov' }}" - CODECOV_DIR: "${{ matrix.build-dir || '.' }}" + CODECOV_TOKEN: "${{secrets.CODECOV_TOKEN}}" - name: Upload build errors uses: actions/upload-artifact@v2 @@ -453,7 +458,8 @@ jobs: with: name: ${{ matrix.name }} (cmake) path: | - ${{ matrix.build-dir || '.' }}/CMakeFiles/CMakeOutput.log - ${{ matrix.build-dir || '.' }}/CMakeFiles/CMakeError.log - ${{ matrix.build-dir || '.' }}/Testing/Temporary/* + **/CMakeFiles/CMakeOutput.log + **/CMakeFiles/CMakeError.log + **/Testing/Temporary/* + coverage.xml retention-days: 30 diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index c36cfafa70..5f4d662001 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -65,11 +65,6 @@ jobs: sudo apt-get update sudo apt-get install -y ${{ matrix.packages }} - - name: Install codecov.io tools - if: matrix.codecov - run: | - python -u -m pip install codecov - - name: Generate project files run: | cd test/pigz @@ -90,19 +85,23 @@ jobs: cd test/pigz ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '2' }} - - name: Upload coverage report - if: matrix.codecov && ( env.CODECOV_TOKEN_SECRET != '' || github.repository == 'zlib-ng/zlib-ng' ) - shell: bash + - name: Generate coverage report + if: matrix.codecov run: | - bash tools/codecov-upload.sh + python3 -u -m pip install --user gcovr + python3 -m gcovr --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root . --xml --output coverage.xml --verbose + + - name: Upload coverage report + uses: codecov/codecov-action@v2 + if: matrix.codecov && (env.CODECOV_TOKEN != '' || github.repository == 'zlib-ng/zlib-ng') + with: + token: ${{ secrets.CODECOV_TOKEN || 'e4fdf847-f541-4ab1-9d50-3d27e5913906' }} + flags: ${{ matrix.codecov }} + name: ${{ matrix.name }} + verbose: true + fail_ci_if_error: true env: - # Codecov does not yet support GitHub Actions - CODECOV_TOKEN_SECRET: "${{secrets.CODECOV_TOKEN}}" - CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN || 'e4fdf847-f541-4ab1-9d50-3d27e5913906' }}" - CODECOV_FLAGS: "${{ matrix.codecov }}" - CODECOV_NAME: "${{ matrix.name }}" - CODECOV_EXEC: "${{ matrix.gcov-exec || 'gcov' }}" - CODECOV_DIR: "." + CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}} - name: Upload build errors uses: actions/upload-artifact@v2 @@ -113,4 +112,5 @@ jobs: **/CMakeFiles/CMakeOutput.log **/CMakeFiles/CMakeError.log **/Testing/Temporary/* + coverage.xml retention-days: 30 diff --git a/tools/codecov-upload.sh b/tools/codecov-upload.sh deleted file mode 100644 index e3a48aab76..0000000000 --- a/tools/codecov-upload.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -set -ux -cd "$CODECOV_DIR" -python -m codecov --required --flags "$CODECOV_FLAGS" --name "$CODECOV_NAME" --gcov-exec="$CODECOV_EXEC" -if [ $? -ne 0 ]; then - sleep 30 - python -m codecov --required --flags "$CODECOV_FLAGS" --name "$CODECOV_NAME" --gcov-exec="$CODECOV_EXEC" --tries=25 -fi -exit $? From 81e546391bc56be1c24cdd827ea19ee54a836584 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 12 Feb 2022 08:10:17 -0800 Subject: [PATCH 277/798] Added codecov yaml configuration to repository. --- .codecov.yaml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .codecov.yaml diff --git a/.codecov.yaml b/.codecov.yaml new file mode 100644 index 0000000000..50ad857b57 --- /dev/null +++ b/.codecov.yaml @@ -0,0 +1,26 @@ +codecov: + max_report_age: off + notify: + wait_for_ci: false + require_ci_to_pass: false +comment: + require_base: false + require_head: false +coverage: + status: + project: + default: + threshold: 0.07 +fixes: +- '/home/actions-runner/_work/zlib-ng/zlib-ng::' +- '/home/actions-runner/_work/zlib-ng/zlib-ng/build/::' +ignore: +- usr/include/.* +- /usr/include/.* +- /build/usr/include/.* +- usr/lib/.* +- /usr/lib/.* +- /build/usr/lib/.* +- usr/lib64/.* +- /usr/lib64/.* +- /build/usr/lib64/.* \ No newline at end of file From fb109aa90042663198c6595cb9ae7fa8db69b0e5 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 23 Feb 2022 07:16:19 -0800 Subject: [PATCH 278/798] Exclude unreachable branches from code coverage report. --- .github/workflows/cmake.yml | 2 +- .github/workflows/pigz.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index d5d7c389e9..c6ec222d3f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -437,7 +437,7 @@ jobs: shell: bash run: | python3 -u -m pip install --user gcovr - python3 -m gcovr --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root ${{ matrix.build-src-dir || '.' }} --xml --output coverage.xml --verbose + python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root ${{ matrix.build-src-dir || '.' }} --xml --output coverage.xml --verbose - name: Upload coverage report uses: codecov/codecov-action@v2 diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 5f4d662001..5c97878258 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -89,7 +89,7 @@ jobs: if: matrix.codecov run: | python3 -u -m pip install --user gcovr - python3 -m gcovr --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root . --xml --output coverage.xml --verbose + python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root . --xml --output coverage.xml --verbose - name: Upload coverage report uses: codecov/codecov-action@v2 From 5945d8720a2ee81fd3a9ba45f390eeb925628745 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 23 Feb 2022 09:44:00 -0800 Subject: [PATCH 279/798] Use multiple threads when running gcovr. --- .github/workflows/cmake.yml | 2 +- .github/workflows/pigz.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index c6ec222d3f..247c7f1aa3 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -437,7 +437,7 @@ jobs: shell: bash run: | python3 -u -m pip install --user gcovr - python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root ${{ matrix.build-src-dir || '.' }} --xml --output coverage.xml --verbose + python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root ${{ matrix.build-src-dir || '.' }} --xml --output coverage.xml -j 3 --verbose - name: Upload coverage report uses: codecov/codecov-action@v2 diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 5c97878258..46d549f45e 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -89,7 +89,7 @@ jobs: if: matrix.codecov run: | python3 -u -m pip install --user gcovr - python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root . --xml --output coverage.xml --verbose + python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root . --xml --output coverage.xml -j 3 --verbose - name: Upload coverage report uses: codecov/codecov-action@v2 From b8fed54be0b5528bf186af2d50e56da86435ec02 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Fri, 11 Feb 2022 15:53:00 +0100 Subject: [PATCH 280/798] Fix compilation of benchmark when compiler supports, but does not default to enable C++11 or higher. --- test/benchmarks/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index 2e87df49d6..e68f54259b 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.12) include(FetchContent) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) enable_language(CXX) # Search for Google benchmark package From 2b1a033f5efcf70ec6193c674628e3c4ba691248 Mon Sep 17 00:00:00 2001 From: Hans Kristian Rosbach Date: Wed, 23 Feb 2022 21:31:11 +0100 Subject: [PATCH 281/798] Run libpng tests on push in addition to pull-requests. Also run oss-fuzz on push to certain branches. --- .github/workflows/fuzz.yml | 12 +++++++++++- .github/workflows/libpng.yml | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index e7ddaea5b5..cd647086ff 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -1,5 +1,15 @@ name: CI Fuzz -on: [pull_request] +on: + pull_request: + push: + branches: + - stable + - develop + - pre-release + - '2.*' + tags: + - '*' + jobs: Fuzzing: runs-on: ubuntu-latest diff --git a/.github/workflows/libpng.yml b/.github/workflows/libpng.yml index b3d989f7be..a519460cce 100644 --- a/.github/workflows/libpng.yml +++ b/.github/workflows/libpng.yml @@ -1,5 +1,5 @@ name: CI Libpng -on: [pull_request] +on: [push, pull_request] jobs: pngtest: name: Ubuntu Clang From cd37e12f72e8b4265bf890072c2c1193991c6890 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sat, 5 Feb 2022 16:15:46 -0500 Subject: [PATCH 282/798] Improve sse41 adler32 performance Rather than doing opportunistic aligned loads, we can do scalar unaligned loads into our two halves of the checksum until we hit alignment. Then, we can subtract from the max number of sums for the first run through the loop. This allows us to force aligned loads for unaligned buffers (likely a common case for arbitrary runs of memory). This is not meaningful after Nehalem but pre-Nehalem architectures it makes a substantial difference to performance and is more foolproof than hoping for an aligned buffer. Improvement is around 44-50% for unaligned worst case scenarios. --- arch/x86/adler32_sse41.c | 130 ++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 55 deletions(-) diff --git a/arch/x86/adler32_sse41.c b/arch/x86/adler32_sse41.c index 87386e9460..718be0f707 100644 --- a/arch/x86/adler32_sse41.c +++ b/arch/x86/adler32_sse41.c @@ -50,63 +50,83 @@ Z_INTERNAL uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size const __m128i dot3v = _mm_set1_epi16(1); const __m128i zero = _mm_setzero_si128(); - __m128i vs1 = _mm_cvtsi32_si128(adler); - __m128i vs2 = _mm_cvtsi32_si128(sum2); + __m128i vbuf, vs1_0, vs3, vs1, vs2, v_sad_sum1, v_short_sum2, vsum2; + + /* If our buffer is unaligned (likely), make the determination whether + * or not there's enough of a buffer to consume to make the scalar, aligning + * additions worthwhile or if it's worth it to just eat the cost of an unaligned + * load. This is a pretty simple test, just test if 16 - the remainder + len is + * < 16 */ + int max_iters = NMAX; + int rem = (uintptr_t)buf & 15; + int align_offset = 16 - rem; + int k = 0; + if (rem) { + if (len < 16 + align_offset) { + /* Let's eat the cost of this one unaligned load so that + * we don't completely skip over the vectorization. Doing + * 16 bytes at a time unaligned is is better than 16 + <= 15 + * sums */ + vbuf = _mm_loadu_si128((__m128i*)buf); + len -= 16; + buf += 16; + vs1 = _mm_cvtsi32_si128(adler); + vs2 = _mm_cvtsi32_si128(sum2); + vs3 = _mm_setzero_si128(); + vs1_0 = vs1; + goto unaligned_jmp; + } + + for (int i = 0; i < align_offset; ++i) { + adler += *(buf++); + sum2 += adler; + } + + /* lop off the max number of sums based on the scalar sums done + * above */ + len -= align_offset; + max_iters -= align_offset; + } + while (len >= 16) { - __m128i vs1_0 = vs1; - __m128i vs3 = _mm_setzero_si128(); - - int k = (len < NMAX ? (int)len : NMAX); - k -= k % 16; - len -= k; - - /* Aligned version of the loop */ - if (((uintptr_t)buf & 15) == 0) { - while (k >= 16) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - __m128i vbuf = _mm_load_si128((__m128i*)buf); - buf += 16; - k -= 16; - - __m128i v_sad_sum1 = _mm_sad_epu8(vbuf, zero); - vs1 = _mm_add_epi32(v_sad_sum1, vs1); - vs3 = _mm_add_epi32(vs1_0, vs3); - __m128i v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); - __m128i vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vs2 = _mm_add_epi32(vsum2, vs2); - vs1_0 = vs1; - } - } else { - while (k >= 16) { - __m128i vbuf = _mm_loadu_si128((__m128i*)buf); - buf += 16; - k -= 16; - - __m128i v_sad_sum1 = _mm_sad_epu8(vbuf, zero); - vs1 = _mm_add_epi32(v_sad_sum1, vs1); - vs3 = _mm_add_epi32(vs1_0, vs3); - __m128i v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); - __m128i vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vs2 = _mm_add_epi32(vsum2, vs2); - vs1_0 = vs1; - } - } - - vs3 = _mm_slli_epi32(vs3, 4); - vs2 = _mm_add_epi32(vs2, vs3); - - /* We don't actually need to do a full horizontal sum, since psadbw is actually doing - * a partial reduction sum implicitly and only summing to integers in vector positions - * 0 and 2. This saves us some contention on the shuffle port(s) */ - adler = partial_hsum(vs1) % BASE; - sum2 = hsum(vs2) % BASE; - - vs1 = _mm_cvtsi32_si128(adler); - vs2 = _mm_cvtsi32_si128(sum2); + vs1 = _mm_cvtsi32_si128(adler); + vs2 = _mm_cvtsi32_si128(sum2); + vs3 = _mm_setzero_si128(); + vs1_0 = vs1; + + k = (len < max_iters ? (int)len : max_iters); + k -= k % 16; + len -= k; + + while (k >= 16) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_load_si128((__m128i*)buf); + buf += 16; + k -= 16; + +unaligned_jmp: + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + vs3 = _mm_slli_epi32(vs3, 4); + vs2 = _mm_add_epi32(vs2, vs3); + + /* We don't actually need to do a full horizontal sum, since psadbw is actually doing + * a partial reduction sum implicitly and only summing to integers in vector positions + * 0 and 2. This saves us some contention on the shuffle port(s) */ + adler = partial_hsum(vs1) % BASE; + sum2 = hsum(vs2) % BASE; + max_iters = NMAX; } /* Process tail (len < 16). */ From f7d284c68b08560a6903fe88c7bc63fedfbbc421 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Wed, 16 Feb 2022 09:42:40 -0500 Subject: [PATCH 283/798] Unlocked more ILP in SSE variant of adler checksum This helps uarchs such as sandybridge more than Yorkfield, but there were some measurable gains on a Core 2 Quad Q9650 as well. We can sum to two separate vs2 variables and add them back together at the end, allowing for some overlapping multiply-adds. This was only about a 9-12% gain on the Q9650 but it nearly doubled performance on cascade lake and is likely to have appreciable gains on everything in between those two. --- arch/x86/adler32_sse41.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/arch/x86/adler32_sse41.c b/arch/x86/adler32_sse41.c index 718be0f707..602f8ec1de 100644 --- a/arch/x86/adler32_sse41.c +++ b/arch/x86/adler32_sse41.c @@ -46,11 +46,13 @@ Z_INTERNAL uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); - const __m128i dot2v = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); + const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); const __m128i dot3v = _mm_set1_epi16(1); const __m128i zero = _mm_setzero_si128(); - __m128i vbuf, vs1_0, vs3, vs1, vs2, v_sad_sum1, v_short_sum2, vsum2; + __m128i vbuf, vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, + vbuf_0, v_sad_sum2, vsum2, vsum2_0; /* If our buffer is unaligned (likely), make the determination whether * or not there's enough of a buffer to consume to make the scalar, aligning @@ -93,12 +95,43 @@ Z_INTERNAL uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size vs1 = _mm_cvtsi32_si128(adler); vs2 = _mm_cvtsi32_si128(sum2); vs3 = _mm_setzero_si128(); + vs2_0 = _mm_setzero_si128(); vs1_0 = vs1; k = (len < max_iters ? (int)len : max_iters); k -= k % 16; len -= k; + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_load_si128((__m128i*)buf); + vbuf_0 = _mm_load_si128((__m128i*)(buf + 16)); + buf += 32; + k -= 32; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + + vs1 = _mm_add_epi32(v_sad_sum2, vs1); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); + vs2 = _mm_add_epi32(vsum2, vs2); + vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); + vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); + vs1_0 = vs1; + } + + vs2 = _mm_add_epi32(vs2_0, vs2); + vs3 = _mm_slli_epi32(vs3, 5); + vs2 = _mm_add_epi32(vs3, vs2); + vs3 = _mm_setzero_si128(); + while (k >= 16) { /* vs1 = adler + sum(c[i]) @@ -112,7 +145,7 @@ Z_INTERNAL uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size v_sad_sum1 = _mm_sad_epu8(vbuf, zero); vs1 = _mm_add_epi32(v_sad_sum1, vs1); vs3 = _mm_add_epi32(vs1_0, vs3); - v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); vs2 = _mm_add_epi32(vsum2, vs2); vs1_0 = vs1; From 43dbfd6709fb3a8028430ea30f3da88fbeb3ced9 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sat, 12 Feb 2022 10:26:50 -0500 Subject: [PATCH 284/798] Improved adler32 NEON performance by 30-47% We unlocked some ILP by allowing for independent sums in the loop and reducing these sums outside of the loop. Additionally, the multiplication by 32 (now 64) is moved outside of this loop. Similar to the chromium implementation, this code does straight 8 bit -> 16 bit additions and defers the fused multiply accumulate outside of the loop. However, by unrolling by another factor of 2, the code is measurably faster. The code does fused multiply accmulates back to as many scratch registers we have room for in order to maximize ILP for the 16 integer FMAs that need to occur. The compiler seems to order them such that the destination register is the same register as the previous instruction, so perhaps it's not actually able to overlap or maybe the -A73's pipeline is reordering these instructions, anyway. On the Odroid-N2, the Cortex-A73 cores are ~30-44% faster on the adler32 benchmark, and the Cortex-A53 cores are anywhere from 34-47% faster. --- arch/arm/adler32_neon.c | 170 +++++++++++++++++++++++++++++++--------- fallback_builtins.h | 17 ++++ 2 files changed, 149 insertions(+), 38 deletions(-) diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index 8f49344404..dfbd54def9 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -1,7 +1,8 @@ /* Copyright (C) 1995-2011, 2016 Mark Adler * Copyright (C) 2017 ARM Holdings Inc. - * Author: Adenilson Cavalcanti - * + * Authors: + * Adenilson Cavalcanti + * Adam Stylinski * For conditions of distribution and use, see copyright notice in zlib.h */ #ifdef ARM_NEON_ADLER32 @@ -12,50 +13,124 @@ #endif #include "../../zbuild.h" #include "../../adler32_p.h" +#include "../../fallback_builtins.h" static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) { - static const uint8_t taps[32] = { + static const uint16_t ALIGNED_(16) taps[64] = { + 64, 63, 62, 61, 60, 59, 58, 57, + 56, 55, 54, 53, 52, 51, 50, 49, + 48, 47, 46, 45, 44, 43, 42, 41, + 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, - 16, 15, 14, 13, 12, 11, 10, 9, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; - uint32x2_t adacc2, s2acc2, as; - uint8x16_t t0 = vld1q_u8(taps), t1 = vld1q_u8(taps + 16); + uint32x4_t adacc = vdupq_n_u32(0); + uint32x4_t s2acc = vdupq_n_u32(0); + uint32x4_t s2acc_0 = vdupq_n_u32(0); + uint32x4_t s2acc_1 = vdupq_n_u32(0); + uint32x4_t s2acc_2 = vdupq_n_u32(0); - uint32x4_t adacc = vdupq_n_u32(0), s2acc = vdupq_n_u32(0); adacc = vsetq_lane_u32(s[0], adacc, 0); s2acc = vsetq_lane_u32(s[1], s2acc, 0); - while (len >= 2) { - uint8x16_t d0 = vld1q_u8(buf), d1 = vld1q_u8(buf + 16); - uint16x8_t adler, sum2; - s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 5)); - adler = vpaddlq_u8( d0); - adler = vpadalq_u8(adler, d1); - sum2 = vmull_u8( vget_low_u8(t0), vget_low_u8(d0)); - sum2 = vmlal_u8(sum2, vget_high_u8(t0), vget_high_u8(d0)); - sum2 = vmlal_u8(sum2, vget_low_u8(t1), vget_low_u8(d1)); - sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d1)); - adacc = vpadalq_u16(adacc, adler); - s2acc = vpadalq_u16(s2acc, sum2); - len -= 2; - buf += 32; + uint32x4_t s3acc = vdupq_n_u32(0); + uint32x4_t adacc_prev = adacc; + + uint16x8_t s2_0, s2_1, s2_2, s2_3; + s2_0 = s2_1 = s2_2 = s2_3 = vdupq_n_u16(0); + + uint16x8_t s2_4, s2_5, s2_6, s2_7; + s2_4 = s2_5 = s2_6 = s2_7 = vdupq_n_u16(0); + + int num_iter = len >> 2; + int rem = len & 3; + + for (int i = 0; i < num_iter; ++i) { + uint8x16x4_t d0_d3 = vld1q_u8_x4(buf); + + /* Unfortunately it doesn't look like there's a direct sum 8 bit to 32 + * bit instruction, we'll have to make due summing to 16 bits first */ + uint16x8x2_t hsum, hsum_fold; + hsum.val[0] = vpaddlq_u8(d0_d3.val[0]); + hsum.val[1] = vpaddlq_u8(d0_d3.val[1]); + + hsum_fold.val[0] = vpadalq_u8(hsum.val[0], d0_d3.val[2]); + hsum_fold.val[1] = vpadalq_u8(hsum.val[1], d0_d3.val[3]); + + adacc = vpadalq_u16(adacc, hsum_fold.val[0]); + s3acc = vaddq_u32(s3acc, adacc_prev); + adacc = vpadalq_u16(adacc, hsum_fold.val[1]); + + /* If we do straight widening additions to the 16 bit values, we don't incur + * the usual penalties of a pairwise add. We can defer the multiplications + * until the very end. These will not overflow because we are incurring at + * most 408 loop iterations (NMAX / 64), and a given lane is only going to be + * summed into once. This means for the maximum input size, the largest value + * we will see is 255 * 102 = 26010, safely under uint16 max */ + s2_0 = vaddw_u8(s2_0, vget_low_u8(d0_d3.val[0])); + s2_1 = vaddw_high_u8(s2_1, d0_d3.val[0]); + s2_2 = vaddw_u8(s2_2, vget_low_u8(d0_d3.val[1])); + s2_3 = vaddw_high_u8(s2_3, d0_d3.val[1]); + s2_4 = vaddw_u8(s2_4, vget_low_u8(d0_d3.val[2])); + s2_5 = vaddw_high_u8(s2_5, d0_d3.val[2]); + s2_6 = vaddw_u8(s2_6, vget_low_u8(d0_d3.val[3])); + s2_7 = vaddw_high_u8(s2_7, d0_d3.val[3]); + + adacc_prev = adacc; + buf += 64; } - while (len > 0) { - uint8x16_t d0 = vld1q_u8(buf); - uint16x8_t adler, sum2; - s2acc = vaddq_u32(s2acc, vshlq_n_u32(adacc, 4)); - adler = vpaddlq_u8(d0); - sum2 = vmull_u8( vget_low_u8(t1), vget_low_u8(d0)); - sum2 = vmlal_u8(sum2, vget_high_u8(t1), vget_high_u8(d0)); - adacc = vpadalq_u16(adacc, adler); - s2acc = vpadalq_u16(s2acc, sum2); - buf += 16; - len--; + s3acc = vshlq_n_u32(s3acc, 6); + + if (rem) { + uint32x4_t s3acc_0 = vdupq_n_u32(0); + while (rem--) { + uint8x16_t d0 = vld1q_u8(buf); + uint16x8_t adler; + adler = vpaddlq_u8(d0); + s2_6 = vaddw_u8(s2_6, vget_low_u8(d0)); + s2_7 = vaddw_high_u8(s2_7, d0); + adacc = vpadalq_u16(adacc, adler); + s3acc_0 = vaddq_u32(s3acc_0, adacc_prev); + adacc_prev = adacc; + buf += 16; + } + + s3acc_0 = vshlq_n_u32(s3acc_0, 4); + s3acc = vaddq_u32(s3acc_0, s3acc); } + uint16x8x4_t t0_t3 = vld1q_u16_x4(taps); + uint16x8x4_t t4_t7 = vld1q_u16_x4(taps + 32); + + s2acc = vmlal_high_u16(s2acc, t0_t3.val[0], s2_0); + s2acc_0 = vmlal_u16(s2acc_0, vget_low_u16(t0_t3.val[0]), vget_low_u16(s2_0)); + s2acc_1 = vmlal_high_u16(s2acc_1, t0_t3.val[1], s2_1); + s2acc_2 = vmlal_u16(s2acc_2, vget_low_u16(t0_t3.val[1]), vget_low_u16(s2_1)); + + s2acc = vmlal_high_u16(s2acc, t0_t3.val[2], s2_2); + s2acc_0 = vmlal_u16(s2acc_0, vget_low_u16(t0_t3.val[2]), vget_low_u16(s2_2)); + s2acc_1 = vmlal_high_u16(s2acc_1, t0_t3.val[3], s2_3); + s2acc_2 = vmlal_u16(s2acc_2, vget_low_u16(t0_t3.val[3]), vget_low_u16(s2_3)); + + s2acc = vmlal_high_u16(s2acc, t4_t7.val[0], s2_4); + s2acc_0 = vmlal_u16(s2acc_0, vget_low_u16(t4_t7.val[0]), vget_low_u16(s2_4)); + s2acc_1 = vmlal_high_u16(s2acc_1, t4_t7.val[1], s2_5); + s2acc_2 = vmlal_u16(s2acc_2, vget_low_u16(t4_t7.val[1]), vget_low_u16(s2_5)); + + s2acc = vmlal_high_u16(s2acc, t4_t7.val[2], s2_6); + s2acc_0 = vmlal_u16(s2acc_0, vget_low_u16(t4_t7.val[2]), vget_low_u16(s2_6)); + s2acc_1 = vmlal_high_u16(s2acc_1, t4_t7.val[3], s2_7); + s2acc_2 = vmlal_u16(s2acc_2, vget_low_u16(t4_t7.val[3]), vget_low_u16(s2_7)); + + s2acc = vaddq_u32(s2acc_0, s2acc); + s2acc_2 = vaddq_u32(s2acc_1, s2acc_2); + s2acc = vaddq_u32(s2acc, s2acc_2); + + uint32x2_t adacc2, s2acc2, as; + s2acc = vaddq_u32(s2acc, s3acc); adacc2 = vpadd_u32(vget_low_u32(adacc), vget_high_u32(adacc)); s2acc2 = vpadd_u32(vget_low_u32(s2acc), vget_high_u32(s2acc)); as = vpadd_u32(adacc2, s2acc2); @@ -91,7 +166,6 @@ uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t pair[2]; int n = NMAX; unsigned int done = 0; - unsigned int i; /* Split Adler-32 into component sums, it can be supplied by * the caller sites (e.g. in a PNG file). @@ -99,18 +173,37 @@ uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len) { pair[0] = adler; pair[1] = sum2; - for (i = 0; i < len; i += n) { - if ((i + n) > len) - n = (int)(len - i); + /* If memory is not SIMD aligned, do scalar sums to an aligned + * offset, provided that doing so doesn't completely eliminate + * SIMD operation. Aligned loads are still faster on ARM, even + * though there's no explicit aligned load instruction */ + unsigned int align_offset = ((uintptr_t)buf & 15); + unsigned int align_adj = (align_offset) ? 16 - align_offset : 0; + + if (align_offset && len >= (16 + align_adj)) { + NEON_handle_tail(pair, buf, align_adj); + n -= align_adj; + done += align_adj; + + } else { + /* If here, we failed the len criteria test, it wouldn't be + * worthwhile to do scalar aligning sums */ + align_adj = 0; + } + + while (done < len) { + int remaining = (int)(len - done); + n = MIN(remaining, (done == align_adj) ? n : NMAX); if (n < 16) break; - NEON_accum32(pair, buf + i, n / 16); + NEON_accum32(pair, buf + done, n >> 4); pair[0] %= BASE; pair[1] %= BASE; - done += (n / 16) * 16; + int actual_nsums = (n >> 4) << 4; + done += actual_nsums; } /* Handle the tail elements. */ @@ -123,4 +216,5 @@ uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t len) { /* D = B * 65536 + A, see: https://en.wikipedia.org/wiki/Adler-32. */ return (pair[1] << 16) | pair[0]; } + #endif diff --git a/fallback_builtins.h b/fallback_builtins.h index 3554b6cc3d..8abec2fad7 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -64,6 +64,14 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { #endif // __AVX2__ +#if defined(ARM_NEON_ADLER32) && !defined(__aarch64__) +/* Compatibility shim for the _high family of functions */ +#define vmull_high_u8(a, b) vmull_u8(vget_high_u8(a), vget_high_u8(b)) +#define vmlal_high_u8(a, b, c) vmlal_u8(a, vget_high_u8(b), vget_high_u8(c)) +#define vmlal_high_u16(a, b, c) vmlal_u16(a, vget_high_u16(b), vget_high_u16(c)) +#define vaddw_high_u8(a, b) vaddw_u8(a, vget_high_u8(b)) +#endif + #ifdef ARM_NEON_SLIDEHASH #define vqsubq_u16_x4_x1(out, a, b) do { \ @@ -93,6 +101,15 @@ static inline uint16x8x4_t vld1q_u16_x4(uint16_t *a) { return ret; } +static inline uint8x16x4_t vld1q_u8_x4(uint8_t *a) { + uint8x16x4_t ret = (uint8x16x4_t) {{ + vld1q_u8(a), + vld1q_u8(a+16), + vld1q_u8(a+32), + vld1q_u8(a+48)}}; + return ret; +} + static inline void vst1q_u16_x4(uint16_t *p, uint16x8x4_t a) { vst1q_u16(p, a.val[0]); vst1q_u16(p + 8, a.val[1]); From 2a19125a7d66fc82c18543aea3dc3c0654785f53 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 8 Feb 2022 17:09:30 -0500 Subject: [PATCH 285/798] Use pclmulqdq accelerated CRC for exported function We were already using this internally for our CRC calculations, however the exported function to CRC checksum any arbitrary stream of bytes was still using a generic C based version that leveraged tables. This function is now called when len is at least 64 bytes. --- arch/x86/crc32_fold_pclmulqdq.c | 137 +++++++++++++++++++++++++++++ arch/x86/crc32_fold_vpclmulqdq.c | 98 +++++++++++++++++++++ cpu_features.h | 2 + functable.c | 3 + test/benchmarks/benchmark_crc32.cc | 8 +- 5 files changed, 241 insertions(+), 7 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 1ac90b34be..1a7e77f0e8 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -6,6 +6,7 @@ * https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf * * Copyright (C) 2013 Intel Corporation. All rights reserved. + * Copyright (C) 2016 Marian Beermann (support for initial value) * Authors: * Wajdi Feghali * Jim Guilford @@ -24,12 +25,18 @@ #include // _mm_extract_epi32 #include "x86_features.h" +#include "cpu_features.h" #include "../../crc32_fold.h" +#include "../../crc32_p.h" +#include #ifdef X86_VPCLMULQDQ_CRC extern size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len); +extern size_t fold_16_vpclmulqdq_nocp(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, __m128i init_crc, + int32_t first); #endif static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3) { @@ -380,6 +387,124 @@ Z_INTERNAL void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const u crc32_fold_save_partial((__m128i *)crc->fold, xmm_crc_part); } +#define ONCE(op) if (first) { \ + first = 0; \ + (op); \ +} +#define XOR_INITIAL(where) ONCE(where = _mm_xor_si128(where, xmm_initial)) + +Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { + unsigned long algn_diff; + __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; + __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3, xmm_crc_part; + __m128i xmm_initial = _mm_cvtsi32_si128(init_crc); + int32_t first = 1; + + /* Technically the CRC functions don't even call this for input < 64, but a bare minimum of 31 + * bytes of input is needed for the aligning load that occurs. If there's an initial CRC, to + * carry it forward through the folded CRC there must be 16 - src % 16 + 16 bytes available, which + * by definition can be up to 15 bytes + one full vector load. */ + assert(len >= 31); + crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + algn_diff = ((uintptr_t)16 - ((uintptr_t)src & 0xF)) & 0xF; + if (algn_diff) { + if (algn_diff >= 4) { + xmm_crc_part = _mm_loadu_si128((__m128i *)src); + + src += algn_diff; + len -= algn_diff; + + XOR_INITIAL(xmm_crc_part); + partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + } else { + xmm_t0 = _mm_loadu_si128((__m128i*)src); + xmm_crc_part = _mm_loadu_si128((__m128i*)src + 1); + XOR_INITIAL(xmm_t0); + fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + partial_fold(algn_diff, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + + src += (algn_diff + 16); + len -= (algn_diff + 16); + } + } + + xmm_crc_part = _mm_setzero_si128(); + +#ifdef X86_VPCLMULQDQ_CRC + if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { + size_t n = fold_16_vpclmulqdq_nocp(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, src, len, + xmm_initial, first); + first = 0; + + len -= n; + src += n; + } +#endif + + while (len >= 64) { + crc32_fold_load((__m128i *)src, &xmm_t0, &xmm_t1, &xmm_t2, &xmm_t3); + XOR_INITIAL(xmm_t0); + fold_4(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc0 = _mm_xor_si128(xmm_crc0, xmm_t0); + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t1); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t2); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t3); + + src += 64; + len -= 64; + } + + /* + * len = num bytes left - 64 + */ + if (len >= 48) { + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + xmm_t2 = _mm_load_si128((__m128i *)src + 2); + XOR_INITIAL(xmm_t0); + + fold_3(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc1 = _mm_xor_si128(xmm_crc1, xmm_t0); + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); + len -= 48; + src += 48; + } else if (len >= 32) { + xmm_t0 = _mm_load_si128((__m128i *)src); + xmm_t1 = _mm_load_si128((__m128i *)src + 1); + XOR_INITIAL(xmm_t0); + + fold_2(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t0); + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t1); + + len -= 32; + src += 32; + } else if (len >= 16) { + xmm_t0 = _mm_load_si128((__m128i *)src); + XOR_INITIAL(xmm_t0); + + fold_1(&xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + + xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t0); + + len -= 16; + src += 16; + } + + if (len) { + memcpy(&xmm_crc_part, src, len); + partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); + } + + crc32_fold_save((__m128i *)crc->fold, xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3); +} + static const unsigned ALIGNED_(16) crc_k[] = { 0xccaa009e, 0x00000000, /* rk1 */ 0x751997d0, 0x00000001, /* rk2 */ @@ -462,4 +587,16 @@ Z_INTERNAL uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc) { return crc->value; } +uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len) { + /* For lens < 64, crc32_byfour method is faster. The CRC32 instruction for + * these short lengths might also prove to be effective */ + if (len < 64) + return crc32_byfour(crc32, buf, len); + + crc32_fold ALIGNED_(16) crc_state; + crc32_fold_reset_pclmulqdq(&crc_state); + crc32_fold_pclmulqdq(&crc_state, buf, len, crc32); + return crc32_fold_final_pclmulqdq(&crc_state); +} + #endif diff --git a/arch/x86/crc32_fold_vpclmulqdq.c b/arch/x86/crc32_fold_vpclmulqdq.c index 5272aed013..dfcdc8a8cc 100644 --- a/arch/x86/crc32_fold_vpclmulqdq.c +++ b/arch/x86/crc32_fold_vpclmulqdq.c @@ -5,9 +5,16 @@ #ifdef X86_VPCLMULQDQ_CRC #include "../../zbuild.h" +#include "../../fallback_builtins.h" #include +#define ONCE(op) if (first) { \ + first = 0; \ + (op); \ +} +#define XOR_INITIAL(where) ONCE(where = _mm512_xor_si512(where, zmm_initial)) + size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2, __m128i *xmm_crc3, uint8_t *dst, const uint8_t *src, size_t len) { size_t len_tmp = len; @@ -105,4 +112,95 @@ size_t fold_16_vpclmulqdq(__m128i *xmm_crc0, __m128i *xmm_crc1, return (len_tmp - len); // return n bytes processed } + +size_t fold_16_vpclmulqdq_nocp(__m128i *xmm_crc0, __m128i *xmm_crc1, + __m128i *xmm_crc2, __m128i *xmm_crc3, const uint8_t *src, size_t len, + __m128i init_crc, int32_t first) { + size_t len_tmp = len; + __m512i zmm_t0, zmm_t1, zmm_t2, zmm_t3; + __m512i zmm_crc0, zmm_crc1, zmm_crc2, zmm_crc3; + __m512i z0, z1, z2, z3; + __m512i zmm_initial = _mm512_zextsi128_si512(init_crc); + const __m512i zmm_fold4 = _mm512_set4_epi32( + 0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); + const __m512i zmm_fold16 = _mm512_set4_epi32( + 0x00000001, 0x1542778a, 0x00000001, 0x322d1430); + + // zmm register init + zmm_crc0 = _mm512_setzero_si512(); + zmm_t0 = _mm512_loadu_si512((__m512i *)src); + XOR_INITIAL(zmm_t0); + zmm_crc1 = _mm512_loadu_si512((__m512i *)src + 1); + zmm_crc2 = _mm512_loadu_si512((__m512i *)src + 2); + zmm_crc3 = _mm512_loadu_si512((__m512i *)src + 3); + + /* already have intermediate CRC in xmm registers + * fold4 with 4 xmm_crc to get zmm_crc0 + */ + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc0, 0); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc1, 1); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc2, 2); + zmm_crc0 = _mm512_inserti32x4(zmm_crc0, *xmm_crc3, 3); + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); + + len -= 256; + src += 256; + + // fold-16 loops + while (len >= 256) { + zmm_t0 = _mm512_loadu_si512((__m512i *)src); + zmm_t1 = _mm512_loadu_si512((__m512i *)src + 1); + zmm_t2 = _mm512_loadu_si512((__m512i *)src + 2); + zmm_t3 = _mm512_loadu_si512((__m512i *)src + 3); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x01); + z1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x01); + z2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x01); + z3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x01); + + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold16, 0x10); + zmm_crc1 = _mm512_clmulepi64_epi128(zmm_crc1, zmm_fold16, 0x10); + zmm_crc2 = _mm512_clmulepi64_epi128(zmm_crc2, zmm_fold16, 0x10); + zmm_crc3 = _mm512_clmulepi64_epi128(zmm_crc3, zmm_fold16, 0x10); + + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc1 = _mm512_xor_si512(z1, zmm_crc1); + zmm_crc2 = _mm512_xor_si512(z2, zmm_crc2); + zmm_crc3 = _mm512_xor_si512(z3, zmm_crc3); + + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_t0); + zmm_crc1 = _mm512_xor_si512(zmm_crc1, zmm_t1); + zmm_crc2 = _mm512_xor_si512(zmm_crc2, zmm_t2); + zmm_crc3 = _mm512_xor_si512(zmm_crc3, zmm_t3); + + len -= 256; + src += 256; + } + // zmm_crc[0,1,2,3] -> zmm_crc0 + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc1); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc2); + + z0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x01); + zmm_crc0 = _mm512_clmulepi64_epi128(zmm_crc0, zmm_fold4, 0x10); + zmm_crc0 = _mm512_xor_si512(z0, zmm_crc0); + zmm_crc0 = _mm512_xor_si512(zmm_crc0, zmm_crc3); + + // zmm_crc0 -> xmm_crc[0, 1, 2, 3] + *xmm_crc0 = _mm512_extracti32x4_epi32(zmm_crc0, 0); + *xmm_crc1 = _mm512_extracti32x4_epi32(zmm_crc0, 1); + *xmm_crc2 = _mm512_extracti32x4_epi32(zmm_crc0, 2); + *xmm_crc3 = _mm512_extracti32x4_epi32(zmm_crc0, 3); + + return (len_tmp - len); // return n bytes processed +} #endif diff --git a/cpu_features.h b/cpu_features.h index c0223ae159..54b798b930 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -54,7 +54,9 @@ extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t #ifdef X86_PCLMULQDQ_CRC extern uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc); extern void crc32_fold_copy_pclmulqdq(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +extern void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); extern uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc); +extern uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len); #endif /* memory chunking */ diff --git a/functable.c b/functable.c index c84f55e42b..5147d3f8d9 100644 --- a/functable.c +++ b/functable.c @@ -393,6 +393,9 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t #elif defined(S390_CRC32_VX) if (s390_cpu_has_vx) functable.crc32 = &s390_crc32_vx; +#elif defined(X86_PCLMULQDQ_CRC) + if (x86_cpu_has_pclmulqdq) + functable.crc32 = &crc32_pclmulqdq; #endif return functable.crc32(crc, buf, len); diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index 57f8fd86d7..07c238862e 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -66,11 +66,5 @@ BENCHMARK_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07); BENCHMARK_CRC32(vx, s390_crc32_vx, s390_cpu_has_vx); #elif defined(X86_PCLMULQDQ_CRC) /* CRC32 fold does a memory copy while hashing */ -uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len) { - crc32_fold ALIGNED_(16) crc_state; - crc32_fold_reset_pclmulqdq(&crc_state); - crc32_fold_copy_pclmulqdq(&crc_state, (uint8_t *)buf, buf, len); - return crc32_fold_final_pclmulqdq(&crc_state); -} BENCHMARK_CRC32(pclmulqdq, crc32_pclmulqdq, x86_cpu_has_pclmulqdq); -#endif \ No newline at end of file +#endif From 4c63726c022c66cc2541c6f87f66837dd162a019 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Mon, 21 Feb 2022 00:17:07 -0500 Subject: [PATCH 286/798] Adding some application-specific benchmarks So far there's only added png encode and decode with predictably compressible bytes. This gives us a rough idea of more holistic impacts of performance improvements (and regressions). An interesting thing found with this, when compared with stock zlib, we're slower for png decoding at levels 8 & 9. When we are slower, we are spending a fair amount of time in the chunk copy function. This probably merits a closer look. This code creates optionally an alternative benchmark binary that links with an alternative static zlib implementation. This can be used to quickly compare between different forks. --- CMakeLists.txt | 2 + test/benchmarks/CMakeLists.txt | 49 ++++++++ test/benchmarks/README.md | 30 ++++- test/benchmarks/benchmark_main.cc | 4 + test/benchmarks/benchmark_png_decode.cc | 126 ++++++++++++++++++++ test/benchmarks/benchmark_png_encode.cc | 54 +++++++++ test/benchmarks/benchmark_png_shared.h | 146 ++++++++++++++++++++++++ 7 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 test/benchmarks/benchmark_png_decode.cc create mode 100644 test/benchmarks/benchmark_png_encode.cc create mode 100644 test/benchmarks/benchmark_png_shared.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 000f3ad9bd..5d453a9be4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,7 @@ option(ZLIB_ENABLE_TESTS "Build test binaries" ON) option(ZLIB_DUAL_LINK "Dual link tests against system zlib" OFF) option(WITH_FUZZERS "Build test/fuzz" OFF) option(WITH_BENCHMARKS "Build test/benchmarks" OFF) +option(WITH_BENCHMARK_APPS "Build application benchmarks" OFF) option(WITH_OPTIM "Build with optimisation" ON) option(WITH_REDUCED_MEM "Reduced memory usage for special cases (reduces performance)" OFF) option(WITH_NEW_STRATEGIES "Use new strategies" ON) @@ -1456,6 +1457,7 @@ add_feature_info(ZLIB_DUAL_LINK ZLIB_DUAL_LINK "Dual link tests against system z add_feature_info(WITH_SANITIZER WITH_SANITIZER "Enable sanitizer support") add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz") add_feature_info(WITH_BENCHMARKS WITH_BENCHMARKS "Build test/benchmarks") +add_feature_info(WITH_BENCHMARK_APPS WITH_BENCHMARK_APPS "Build application benchmarks") add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation") add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies") add_feature_info(WITH_NATIVE_INSTRUCTIONS WITH_NATIVE_INSTRUCTIONS diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index e68f54259b..df1df49731 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -44,3 +44,52 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME benchmark_zlib COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) endif() + +if(WITH_BENCHMARK_APPS) + option(BUILD_ALT_BENCH "Link against alternative zlib implementation" OFF) + + # Search for libpng package + find_package(PNG QUIET) + + if(NOT PNG_FOUND) + FetchContent_Declare(PNG + GIT_REPOSITORY https://github.com/glennrp/libpng.git) + FetchContent_MakeAvailable(PNG) + FetchContent_GetProperties(PNG) + + if(NOT PNG_POPULATED) + FetchContent_Populate(PNG) + endif() + endif() + + set(BENCH_APP_SRCS + benchmark_png_encode.cc + benchmark_png_decode.cc + benchmark_main.cc + ) + + add_executable(benchmark_zlib_apps ${BENCH_APP_SRCS}) + + if(DEFINED BUILD_ALT_BENCH) + set(ZLIB_ALT_LIB "libz.a" CACHE FILEPATH "Optional alternative zlib implementation (defaults to stock zlib)") + add_executable(benchmark_zlib_apps_alt ${BENCH_APP_SRCS}) + target_link_libraries(benchmark_zlib_apps_alt libpng.a ${ZLIB_ALT_LIB} benchmark::benchmark) + target_compile_definitions(benchmark_zlib_apps_alt PRIVATE BUILD_ALT=1) + target_include_directories(benchmark_zlib_apps_alt PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${PNG_INCLUDE_DIR} + ${benchmark_SOURCE_DIR}/benchmark/include) + endif() + + target_include_directories(benchmark_zlib_apps PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${PNG_INCLUDE_DIR} + ${benchmark_SOURCE_DIR}/benchmark/include) + + # We need the static png library if we're statically linking to zlib, + # otherwise it will resolve these things in the system provided dynamic + # libraries (likely linked to stock zlib) + target_link_libraries(benchmark_zlib_apps libpng.a zlibstatic benchmark::benchmark) +endif() diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md index b005027e07..5dce7f51bc 100644 --- a/test/benchmarks/README.md +++ b/test/benchmarks/README.md @@ -1,5 +1,4 @@ ## Benchmarks - These benchmarks are written using [Google Benchmark](https://github.com/google/benchmark). *Repetitions* @@ -17,3 +16,32 @@ To filter out which benchmarks are performed use: ``` --benchmark_filter="adler32*" ``` + +There are two different benchmarks, micro and macro. + +### Benchmark benchmark_zlib +These are microbenchmarks intended to test lower level subfunctions of the library. + +Benchmarks include impelementations of: + - Adler32 + - CRC + - 256 byte comparisons + - SIMD accelerated "slide hash" routine + +By default these benchmarks report things on the nanosecond scale and are small enough +to measure very minute diferences. + +### Benchmark benchmark_zlib_apps +These benchmarks measure applications of zlib as a whole. Currently the only examples +are PNG encoding and decoding. The PNG encode and decode tests leveraging procedurally +generated and highly compressible image data. + +Additionally, a test called `png_decode_realistic` that will decode any RGB 8 BPP encoded +set of PNGs in the working directory under a directory named "test_pngs" with files named +{0..1}.png. If these images do not exist, they will error out and the benchmark will move +on to the next set of benchmarks. + +*benchmark_zlib_apps_alt* + +The user can compile a comparison benchmark application linking to any zlib-compatible +implementation of his or her choosing. diff --git a/test/benchmarks/benchmark_main.cc b/test/benchmarks/benchmark_main.cc index 600ac22814..ee8b614897 100644 --- a/test/benchmarks/benchmark_main.cc +++ b/test/benchmarks/benchmark_main.cc @@ -7,13 +7,17 @@ #include +#ifndef BUILD_ALT extern "C" { # include "zbuild.h" # include "cpu_features.h" } +#endif int main(int argc, char** argv) { +#ifndef BUILD_ALT cpu_check_features(); +#endif ::benchmark::Initialize(&argc, argv); ::benchmark::RunSpecifiedBenchmarks(); diff --git a/test/benchmarks/benchmark_png_decode.cc b/test/benchmarks/benchmark_png_decode.cc new file mode 100644 index 0000000000..c037976c8c --- /dev/null +++ b/test/benchmarks/benchmark_png_decode.cc @@ -0,0 +1,126 @@ +#include +#include +#include "benchmark_png_shared.h" +#include + +class png_decode: public benchmark::Fixture { +protected: + png_dat inpng[10]; + + /* Backing this on the heap is a more realistic benchmark */ + uint8_t *output_img_buf = NULL; + +public: + /* Let's make the vanilla version have something extremely compressible */ + virtual void init_img(png_bytep img_bytes, size_t width, size_t height) { + init_compressible(img_bytes, width*height); + } + + void SetUp(const ::benchmark::State& state) { + output_img_buf = (uint8_t*)malloc(IMWIDTH * IMHEIGHT * 3); + assert(output_img_buf != NULL); + init_img(output_img_buf, IMWIDTH, IMHEIGHT); + + /* First we need to author the png bytes to be decoded */ + for (int i = 0; i < 10; ++i) { + inpng[i] = {NULL, 0, 0}; + encode_png(output_img_buf, &inpng[i], i, IMWIDTH, IMHEIGHT); + } + } + + /* State in this circumstance will convey the compression level */ + void Bench(benchmark::State &state) { + for (auto _ : state) { + int compress_lvl = state.range(0); + png_parse_dat in = { inpng[compress_lvl].buf }; + uint32_t width, height; + decode_png(&in, (png_bytepp)&output_img_buf, IMWIDTH * IMHEIGHT * 3, width, height); + } + } + + void TearDown(const ::benchmark::State &state) { + free(output_img_buf); + for (int i = 0; i < 10; ++i) { + free(inpng[i].buf); + } + } +}; + +class png_decode_realistic: public png_decode { +private: + bool test_files_found = false; + +public: + void SetUp(const ::benchmark::State &state) { + output_img_buf = NULL; + output_img_buf = (uint8_t*)malloc(IMWIDTH * IMHEIGHT * 3); + /* Let's take all the images at different compression levels and jam their bytes into buffers */ + char test_fname[25]; + FILE *files[10]; + + /* Set all to NULL */ + memset(files, 0, sizeof(FILE*)); + + for (size_t i = 0; i < 10; ++i) { + sprintf(test_fname, "test_pngs/%1lu.png", i); + FILE *in_img = fopen(test_fname, "r"); + if (in_img == NULL) { + for (size_t j = 0; j < i; ++j) { + if (files[j]) + fclose(files[j]); + } + + /* For proper cleanup */ + for (size_t j = i; j < 10; ++j) { + inpng[i] = { NULL, 0, 0 }; + } + + return; + } + files[i] = in_img; + } + + test_files_found = true; + /* Now that we've established we have all the png files, let's read all of their bytes into buffers */ + for (size_t i = 0; i < 10; ++i) { + FILE *in_file = files[i]; + fseek(in_file, 0, SEEK_END); + size_t num_bytes = ftell(in_file); + rewind(in_file); + + uint8_t *raw_file = (uint8_t*)malloc(num_bytes); + if (raw_file == NULL) + abort(); + + inpng[i].buf = raw_file; + inpng[i].len = num_bytes; + inpng[i].buf_rem = 0; + + size_t bytes_read = fread(raw_file, 1, num_bytes, in_file); + if (bytes_read != num_bytes) { + fprintf(stderr, "couldn't read all of the bytes for file test_pngs/%lu.png", i); + abort(); + } + + fclose(in_file); + } + } + + void Bench(benchmark::State &state) { + if (!test_files_found) { + state.SkipWithError("Test imagery in test_pngs not found"); + } + + png_decode::Bench(state); + } +}; + +BENCHMARK_DEFINE_F(png_decode, png_decode)(benchmark::State &state) { + Bench(state); +} +BENCHMARK_REGISTER_F(png_decode, png_decode)->DenseRange(0, 9, 1)->Unit(benchmark::kMicrosecond); + +BENCHMARK_DEFINE_F(png_decode_realistic, png_decode_realistic)(benchmark::State &state) { + Bench(state); +} +BENCHMARK_REGISTER_F(png_decode_realistic, png_decode_realistic)->DenseRange(0, 9, 1)->Unit(benchmark::kMicrosecond); diff --git a/test/benchmarks/benchmark_png_encode.cc b/test/benchmarks/benchmark_png_encode.cc new file mode 100644 index 0000000000..f1c597d36b --- /dev/null +++ b/test/benchmarks/benchmark_png_encode.cc @@ -0,0 +1,54 @@ +#include +#include +#include +#include "benchmark_png_shared.h" + +#define IMWIDTH 1024 +#define IMHEIGHT 1024 + +class png_encode: public benchmark::Fixture { +private: + png_dat outpng; + + /* Backing this on the heap is a more realistic benchmark */ + uint8_t *input_img_buf = NULL; + +public: + /* Let's make the vanilla version have something extremely compressible */ + virtual void init_img(png_bytep img_bytes, size_t width, size_t height) { + init_compressible(img_bytes, width * height); + } + + void SetUp(const ::benchmark::State& state) { + input_img_buf = (uint8_t*)malloc(IMWIDTH * IMHEIGHT * 3); + outpng.buf = (uint8_t*)malloc(IMWIDTH * IMHEIGHT * 3); + /* Using malloc rather than zng_alloc so that we can call realloc. + * IMWIDTH * IMHEIGHT is likely to be more than enough bytes, though, + * given that a simple run length encoding already pretty much can + * reduce to this */ + outpng.len = 0; + outpng.buf_rem = IMWIDTH * IMHEIGHT * 3; + assert(input_img_buf != NULL); + assert(outpng.buf != NULL); + init_img(input_img_buf, IMWIDTH, IMHEIGHT); + } + + /* State in this circumstance will convey the compression level */ + void Bench(benchmark::State &state) { + for (auto _ : state) { + encode_png((png_bytep)input_img_buf, &outpng, state.range(0), IMWIDTH, IMHEIGHT); + outpng.buf_rem = outpng.len; + outpng.len = 0; + } + } + + void TearDown(const ::benchmark::State &state) { + free(input_img_buf); + free(outpng.buf); + } +}; + +BENCHMARK_DEFINE_F(png_encode, encode_compressible)(benchmark::State &state) { + Bench(state); +} +BENCHMARK_REGISTER_F(png_encode, encode_compressible)->DenseRange(0, 9, 1)->Unit(benchmark::kMicrosecond); diff --git a/test/benchmarks/benchmark_png_shared.h b/test/benchmarks/benchmark_png_shared.h new file mode 100644 index 0000000000..1b29d3be9c --- /dev/null +++ b/test/benchmarks/benchmark_png_shared.h @@ -0,0 +1,146 @@ +#pragma once + +#include +#include +#include + +#define IMWIDTH 1024 +#define IMHEIGHT 1024 + +extern "C" { +# include +} + +typedef struct _png_dat { + uint8_t *buf; + int64_t len; + size_t buf_rem; +} png_dat; + +typedef struct _png_parse_dat { + uint8_t *cur_pos; +} png_parse_dat; + +/* Write a customized write callback so that we write back to an in-memory buffer. + * This allows the testing to not involve disk IO */ +static void png_write_cb(png_structp pngp, png_bytep data, png_size_t len) { + png_dat *dat = (png_dat*)png_get_io_ptr(pngp); + size_t curSize = dat->len + len; + + /* realloc double the requested buffer size to prevent excessive reallocs */ + if (dat->buf_rem < len) { + dat->buf = (uint8_t*)realloc(dat->buf, dat->len + dat->buf_rem + 2 * len); + + if (!dat->buf) { + /* Pretty unlikely but we'll put it here just in case */ + fprintf(stderr, "realloc failed, exiting\n"); + exit(1); + } + + dat->buf_rem += 2 * len; + } + + memcpy(dat->buf + dat->len, data, len); + dat->len = curSize; + dat->buf_rem -= len; +} + +static void init_compressible(png_bytep buf, size_t num_pix) { + /* It doesn't actually matter what we make this, but for + * the sake of a reasonable test image, let's make this + * be a stripe of R, G, & B, with no alpha channel */ + int32_t i = 0; + int32_t red_stop = num_pix / 3; + int32_t blue_stop = 2 * num_pix / 3; + int32_t green_stop = num_pix; + + for (int32_t x = 0; i < red_stop; x += 3, ++i) { + buf[x] = 255; + buf[x + 1] = 0; + buf[x + 2] = 0; + } + + for (int32_t x = 3 * i; i < blue_stop; x+= 3, ++i) { + buf[x] = 0; + buf[x + 1] = 255; + buf[x + 2] = 0; + } + + for (int32_t x = 3 * i; i < green_stop; x += 3, ++i) { + buf[x] = 0; + buf[x + 1] = 0; + buf[x + 2] = 255; + } +} + +static inline void encode_png(png_bytep buf, png_dat *outpng, int32_t comp_level, uint32_t width, uint32_t height) { + png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + /* Most of this error handling is _likely_ not necessary. Likewise it's likely + * a lot of this stuff can be done in the setup function to avoid measuring this + * fixed setup time, but for now we'll do it here */ + if (!png) abort(); + + png_infop info = png_create_info_struct(png); + if (!info) abort(); + + png_set_write_fn(png, outpng, png_write_cb, NULL); + png_bytep *png_row_ptrs = new png_bytep[height]; + for (int i = 0; i < IMHEIGHT; ++i) { + png_row_ptrs[i] = (png_bytep)&buf[3*i*width]; + } + + png_set_IHDR(png, info, IMWIDTH, IMHEIGHT, 8, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png, info); + png_set_compression_level(png, comp_level); + png_set_filter(png, 0, PNG_FILTER_NONE); + png_write_image(png, (png_bytepp)png_row_ptrs); + png_write_end(png, NULL); + png_destroy_write_struct(&png, &info); + delete[] png_row_ptrs; +} + +static void read_from_pngdat(png_structp png, png_bytep out, png_size_t bytes_to_read) { + png_parse_dat *io = (png_parse_dat*)png_get_io_ptr(png); + memcpy(out, io->cur_pos, bytes_to_read); + io->cur_pos += bytes_to_read; +} + +static inline int decode_png(png_parse_dat *dat, png_bytepp out_bytes, size_t in_size, uint32_t &width, uint32_t &height) { + png_structp png = NULL; + png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png) abort(); + png_infop info = NULL; + info = png_create_info_struct(png); + if (!info) abort(); + + png_set_read_fn(png, dat, read_from_pngdat); + png_read_info(png, info); + + int bit_depth = 0, color_type = -1; + png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + + size_t im_size = width * height * bit_depth/8; + if (color_type != PNG_COLOR_TYPE_RGB) { + fprintf(stderr, "expected an 8 bpp RGB image\n"); + abort(); + } + + if (im_size > in_size) { + *out_bytes = (png_bytep)realloc(*out_bytes, im_size); + } + + png_bytep *out_rows = new png_bytep[height]; + for (size_t i = 0; i < height; ++i) + out_rows[i] = *out_bytes + (width*i); + + png_read_rows(png, out_rows, NULL, IMHEIGHT); + png_destroy_read_struct(&png, &info, NULL); + delete[] out_rows; + + return im_size; +} From 10a49e391e48475279e15073ad770df55ef0beb3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 9 Mar 2022 14:50:41 -0800 Subject: [PATCH 287/798] Fixed inftrees.c should be compiled with infcover when zlib is a shared library. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d453a9be4..9b68cc60da 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1236,7 +1236,7 @@ if(ZLIB_ENABLE_TESTS) target_link_libraries(switchlevels zlib) add_simple_test_executable(infcover) - if(NOT BUILD_SHARED_LIBS) + if(NOT DEFINED BUILD_SHARED_LIBS OR BUILD_SHARED_LIBS) target_sources(infcover PRIVATE inftrees.c) endif() From 5bbc3c3a7ab32e13c4af7e150b50aa3573c4573e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 9 Mar 2022 14:57:22 -0800 Subject: [PATCH 288/798] Added ClangCl instances to GitHub Actions workflow. --- .github/workflows/cmake.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 247c7f1aa3..1a50b0ea3b 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -334,6 +334,14 @@ jobs: compiler: cl cmake-args: -A ARM64 + - name: Windows ClangCl Win32 + os: windows-latest + cmake-args: -T ClangCl -A Win32 + + - name: Windows ClangCl Win64 + os: windows-latest + cmake-args: -T ClangCl -A x64 + - name: Windows GCC os: windows-latest compiler: gcc From e1d7d9eaf7dadb08da2220f0c010984ca7b8e72c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 6 Feb 2022 09:52:27 -0800 Subject: [PATCH 289/798] Implement unit testing using Google Test framework. --- .gitignore | 4 +- CMakeLists.txt | 19 +- Makefile.in | 28 +- test/CMakeLists.txt | 44 +++ test/Makefile.in | 2 +- test/{test_adler32.c => test_adler32.cc} | 358 ++++++++++-------- test/test_compress.cc | 33 ++ test/test_crc32.c | 197 ---------- test/test_crc32.cc | 219 +++++++++++ test/test_deflate_bound.cc | 53 +++ test/test_deflate_copy.cc | 60 +++ test/test_deflate_dict.cc | 54 +++ test/test_deflate_hash_head_0.cc | 83 ++++ test/test_deflate_header.cc | 68 ++++ test/test_deflate_params.cc | 143 +++++++ test/test_deflate_pending.cc | 66 ++++ test/test_deflate_prime.cc | 91 +++++ ...valid.c => test_deflate_quick_bi_valid.cc} | 38 +- ...pen.c => test_deflate_quick_block_open.cc} | 59 +-- test/test_deflate_tune.cc | 56 +++ test/test_dict.cc | 95 +++++ test/test_gzio.cc | 105 +++++ test/test_hash_head_0.c | 110 ------ ...late_adler32.c => test_inflate_adler32.cc} | 41 +- test/test_inflate_sync.cc | 75 ++++ test/test_large_buffers.cc | 87 +++++ test/test_main.cc | 17 + test/test_shared.h | 2 + test/test_small_buffers.cc | 69 ++++ test/test_version.cc | 27 ++ 30 files changed, 1704 insertions(+), 599 deletions(-) create mode 100644 test/CMakeLists.txt rename test/{test_adler32.c => test_adler32.cc} (66%) create mode 100644 test/test_compress.cc delete mode 100644 test/test_crc32.c create mode 100644 test/test_crc32.cc create mode 100644 test/test_deflate_bound.cc create mode 100644 test/test_deflate_copy.cc create mode 100644 test/test_deflate_dict.cc create mode 100644 test/test_deflate_hash_head_0.cc create mode 100644 test/test_deflate_header.cc create mode 100644 test/test_deflate_params.cc create mode 100644 test/test_deflate_pending.cc create mode 100644 test/test_deflate_prime.cc rename test/{test_deflate_quick_bi_valid.c => test_deflate_quick_bi_valid.cc} (84%) rename test/{test_deflate_quick_block_open.c => test_deflate_quick_block_open.cc} (71%) create mode 100644 test/test_deflate_tune.cc create mode 100644 test/test_dict.cc create mode 100644 test/test_gzio.cc delete mode 100644 test/test_hash_head_0.c rename test/{test_inflate_adler32.c => test_inflate_adler32.cc} (52%) create mode 100644 test/test_inflate_sync.cc create mode 100644 test/test_large_buffers.cc create mode 100644 test/test_main.cc create mode 100644 test/test_shared.h create mode 100644 test/test_small_buffers.cc create mode 100644 test/test_version.cc diff --git a/.gitignore b/.gitignore index ff0a590957..239171c2d6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,11 +13,11 @@ *.gcno *.gcov -/test_adler32 -/test_crc32 +/benchmark_zlib /example /example64 /examplesh +/gtest_zlib /libz.so* /libz-ng.so* /makefixed diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b68cc60da..d88ca32e8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1165,6 +1165,12 @@ endif() option(ZLIB_ENABLE_TESTS "Build test binaries" ON) if(ZLIB_ENABLE_TESTS) enable_testing() + + add_subdirectory(test) + if(WITH_BENCHMARKS) + add_subdirectory(test/benchmarks) + endif() + macro(configure_test_executable target) target_include_directories(${target} PUBLIC "$" @@ -1188,15 +1194,6 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME ${target} COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) endmacro() - file(GLOB TEST_SRCS - LIST_DIRECTORIES false - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/test - ${CMAKE_CURRENT_SOURCE_DIR}/test/test_*.c) - - foreach(TEST_SRC ${TEST_SRCS}) - get_filename_component(TEST_NAME ${TEST_SRC} NAME_WE) - add_simple_test_executable(${TEST_NAME}) - endforeach() if(NOT WIN32 AND ZLIB_COMPAT) add_simple_test_executable(CVE-2003-0107) @@ -1303,10 +1300,6 @@ if(ZLIB_ENABLE_TESTS) endforeach() endif() - if(WITH_BENCHMARKS) - add_subdirectory(test/benchmarks) - endif() - macro(test_minigzip name path) # Construct compression arguments for minigzip set(compress_args -k -c) diff --git a/Makefile.in b/Makefile.in index e7ad5a6506..2b8269099b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -154,7 +154,7 @@ PIC_OBJS = $(PIC_OBJC) all: static shared -static: test_adler32$(EXE) test_crc32$(EXE) example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) +static: example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) shared: examplesh$(EXE) minigzipsh$(EXE) @@ -263,12 +263,6 @@ maketrees.o: makecrct.o: $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/tools/makecrct.c -test_adler32.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/test_adler32.c - -test_crc32.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/test_crc32.c - zlibrc.o: win32/zlib$(SUFFIX)1.rc $(RC) $(RCFLAGS) -o $@ win32/zlib$(SUFFIX)1.rc @@ -323,17 +317,12 @@ ifneq ($(STRIP),) $(STRIP) $@ endif -test_adler32$(EXE): test_adler32.o $(OBJG) $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test_adler32.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) +minigzipsh$(EXE): minigzip.o $(OBJG) $(SHAREDTARGET) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(OBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) ifneq ($(STRIP),) $(STRIP) $@ endif -test_crc32$(EXE): test_crc32.o $(STATICLIB) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test_crc32.o $(TEST_LIBS) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif examplesh$(EXE): example.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ example.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) @@ -341,12 +330,6 @@ ifneq ($(STRIP),) $(STRIP) $@ endif -minigzipsh$(EXE): minigzip.o $(PIC_TESTOBJG) $(SHAREDTARGET) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(PIC_TESTOBJG) $(SHAREDTARGET) $(LDSHAREDLIBC) -ifneq ($(STRIP),) - $(STRIP) $@ -endif - makefixed$(EXE): makefixed.o $(OBJG) $(STATICLIB) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ makefixed.o $(OBJG) $(TEST_LIBS) $(LDSHAREDLIBC) ifneq ($(STRIP),) @@ -427,10 +410,7 @@ clean: @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) clean; fi @if [ -f test/Makefile ]; then $(MAKE) -C test clean; fi rm -f *.o *.lo *~ \ - test_adler32$(EXE) test_crc32$(EXE) example$(EXE) minigzip$(EXE) \ - examplesh$(EXE) minigzipsh$(EXE) \ - fuzzer_checksum$(EXE) fuzzer_compress$(EXE) fuzzer_example_small$(EXE) fuzzer_example_large$(EXE) \ - fuzzer_example_flush$(EXE) fuzzer_example_dict$(EXE) fuzzer_minigzip$(EXE) \ + example$(EXE) minigzip$(EXE) minigzipsh$(EXE) fuzzer_*$(EXE) \ infcover makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) \ $(STATICLIB) $(IMPORTLIB) $(SHAREDLIB) $(SHAREDLIBV) $(SHAREDLIBM) \ foo.gz so_locations \ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000000..973e9f9399 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.12) + +include(FetchContent) + +enable_language(CXX) + +# Google test requires at least C++11 +set(CMAKE_CXX_STANDARD 11) + +# Prevent overriding the parent project's compiler/linker settings for Windows +set(gtest_force_shared_crt ON CACHE BOOL + "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) +# Disable pthreads for simplicity +set(gtest_disable_pthreads ON CACHE BOOL + "Disable uses of pthreads in gtest." FORCE) + +# Fetch Google test source code from official repository +FetchContent_Declare(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG main) + +FetchContent_GetProperties(googletest) +if(NOT googletest_POPULATED) + FetchContent_Populate(googletest) + add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() + +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/test_*.cc) + +add_executable(gtest_zlib ${TEST_SRCS}) + +target_include_directories(gtest_zlib PRIVATE + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR}) + +target_link_libraries(gtest_zlib zlibstatic gtest) + +if(ZLIB_ENABLE_TESTS) + add_test(NAME gtest_zlib + COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) +endif() diff --git a/test/Makefile.in b/test/Makefile.in index a32d0adf8d..de72edc0f4 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -48,7 +48,7 @@ endif teststatic: check_cross_dep @TMPST=tmpst_$$$$; \ HELLOST=tmphellost_$$$$; \ - if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${QEMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${QEMU_RUN} ../example$(EXE) $$TMPST && ${QEMU_RUN} ../test_adler32$(EXE) && ${QEMU_RUN} ../test_crc32$(EXE); then \ + if echo hello world | ${QEMU_RUN} ../minigzip$(EXE) > $$HELLOST && ${QEMU_RUN} ../minigzip$(EXE) -d < $$HELLOST && ${QEMU_RUN} ../example$(EXE) $$TMPST; then \ echo ' *** zlib test OK ***'; \ else \ echo ' *** zlib test FAILED ***'; exit 1; \ diff --git a/test/test_adler32.c b/test/test_adler32.cc similarity index 66% rename from test/test_adler32.c rename to test/test_adler32.cc index 56e8c0ca11..fa113da5ae 100644 --- a/test/test_adler32.c +++ b/test/test_adler32.cc @@ -4,32 +4,24 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - #include +#include +#include + +extern "C" { +# include "zbuild.h" +# include "cpu_features.h" +} + +#include typedef struct { - uint32_t line; uint32_t adler; const uint8_t *buf; uint32_t len; uint32_t expect; } adler32_test; -void test_adler32(uint32_t adler, const uint8_t *buf, uint32_t len, uint32_t chk, uint32_t line) { - uint32_t res = PREFIX(adler32)(adler, buf, len); - if (res != chk) { - fprintf(stderr, "FAIL [%d]: adler32 returned 0x%08X expected 0x%08X\n", - line, res, chk); - exit(1); - } -} - static const uint8_t long_string[5552] = { 'q','j','d','w','q','4','8','m','B','u','k','J','V','U','z','V','V','f','M','j','i','q','S','W','L','5','G','n','F','S','P','Q', 'Q','D','i','6','m','E','9','Z','a','A','P','h','9','d','r','b','5','t','X','U','U','L','w','q','e','k','E','H','6','W','7','k', @@ -207,157 +199,191 @@ static const uint8_t long_string[5552] = { 'y','K','B','A','5','2','7','b','y','R','K','q','A','u','3','J'}; static const adler32_test tests[] = { - {__LINE__, 0x1, (const uint8_t *)0x0, 0, 0x1}, - {__LINE__, 0x1, (const uint8_t *)"", 1, 0x10001}, - {__LINE__, 0x1, (const uint8_t *)"a", 1, 0x620062}, - {__LINE__, 0x1, (const uint8_t *)"abacus", 6, 0x8400270}, - {__LINE__, 0x1, (const uint8_t *)"backlog", 7, 0xb1f02d4}, - {__LINE__, 0x1, (const uint8_t *)"campfire", 8, 0xea10348}, - {__LINE__, 0x1, (const uint8_t *)"delta", 5, 0x61a020b}, - {__LINE__, 0x1, (const uint8_t *)"executable", 10, 0x16fa0423}, - {__LINE__, 0x1, (const uint8_t *)"file", 4, 0x41401a1}, - {__LINE__, 0x1, (const uint8_t *)"greatest", 8, 0xefa0360}, - {__LINE__, 0x1, (const uint8_t *)"inverter", 8, 0xf6f0370}, - {__LINE__, 0x1, (const uint8_t *)"jigsaw", 6, 0x8bd0286}, - {__LINE__, 0x1, (const uint8_t *)"karate", 6, 0x8a50279}, - {__LINE__, 0x1, (const uint8_t *)"landscape", 9, 0x126a03ac}, - {__LINE__, 0x1, (const uint8_t *)"machine", 7, 0xb5302d6}, - {__LINE__, 0x1, (const uint8_t *)"nanometer", 9, 0x12d803ca}, - {__LINE__, 0x1, (const uint8_t *)"oblivion", 8, 0xf220363}, - {__LINE__, 0x1, (const uint8_t *)"panama", 6, 0x8a1026f}, - {__LINE__, 0x1, (const uint8_t *)"quest", 5, 0x6970233}, - {__LINE__, 0x1, (const uint8_t *)"resource", 8, 0xf8d0369}, - {__LINE__, 0x1, (const uint8_t *)"secret", 6, 0x8d10287}, - {__LINE__, 0x1, (const uint8_t *)"ultimate", 8, 0xf8d0366}, - {__LINE__, 0x1, (const uint8_t *)"vector", 6, 0x8fb0294}, - {__LINE__, 0x1, (const uint8_t *)"walrus", 6, 0x918029f}, - {__LINE__, 0x1, (const uint8_t *)"xeno", 4, 0x45e01bb}, - {__LINE__, 0x1, (const uint8_t *)"yelling", 7, 0xbfe02f5}, - {__LINE__, 0x1, (const uint8_t *)"zero", 4, 0x46e01c1}, - {__LINE__, 0x1, (const uint8_t *)"4BJD7PocN1VqX0jXVpWB", 20, 0x3eef064d}, - {__LINE__, 0x1, (const uint8_t *)"F1rPWI7XvDs6nAIRx41l", 20, 0x425d065f}, - {__LINE__, 0x1, (const uint8_t *)"ldhKlsVkPFOveXgkGtC2", 20, 0x4f1a073e}, - {__LINE__, 0x1, (const uint8_t *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x42290650}, - {__LINE__, 0x1, (const uint8_t *)"0l1tw7GOcem06Ddu7yn4", 20, 0x43fd0690}, - {__LINE__, 0x1, (const uint8_t *)"MCr47CjPIn9R1IvE1Tm5", 20, 0x3f770609}, - {__LINE__, 0x1, (const uint8_t *)"UcixbzPKTIv0SvILHVdO", 20, 0x4c7c0703}, - {__LINE__, 0x1, (const uint8_t *)"dGnAyAhRQDsWw0ESou24", 20, 0x48ac06b7}, - {__LINE__, 0x1, (const uint8_t *)"di0nvmY9UYMYDh0r45XT", 20, 0x489a0698}, - {__LINE__, 0x1, (const uint8_t *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x44a906e6}, - {__LINE__, 0x1, (const uint8_t *)"ZhrANFIiIvRnqClIVyeD", 20, 0x4a29071c}, - {__LINE__, 0x1, (const uint8_t *)"v7Q9ehzioTOVeDIZioT1", 20, 0x4a7706f9}, - {__LINE__, 0x1, (const uint8_t *)"Yod5hEeKcYqyhfXbhxj2", 20, 0x4ce60769}, - {__LINE__, 0x1, (const uint8_t *)"GehSWY2ay4uUKhehXYb0", 20, 0x48ae06e5}, - {__LINE__, 0x1, (const uint8_t *)"kwytJmq6UqpflV8Y8GoE", 20, 0x51d60750}, - {__LINE__, 0x1, (const uint8_t *)"70684206568419061514", 20, 0x2b100414}, - {__LINE__, 0x1, (const uint8_t *)"42015093765128581010", 20, 0x2a550405}, - {__LINE__, 0x1, (const uint8_t *)"88214814356148806939", 20, 0x2b450423}, - {__LINE__, 0x1, (const uint8_t *)"43472694284527343838", 20, 0x2b460421}, - {__LINE__, 0x1, (const uint8_t *)"49769333513942933689", 20, 0x2bc1042b}, - {__LINE__, 0x1, (const uint8_t *)"54979784887993251199", 20, 0x2ccd043d}, - {__LINE__, 0x1, (const uint8_t *)"58360544869206793220", 20, 0x2b68041a}, - {__LINE__, 0x1, (const uint8_t *)"27347953487840714234", 20, 0x2b84041d}, - {__LINE__, 0x1, (const uint8_t *)"07650690295365319082", 20, 0x2afa0417}, - {__LINE__, 0x1, (const uint8_t *)"42655507906821911703", 20, 0x2aff0412}, - {__LINE__, 0x1, (const uint8_t *)"29977409200786225655", 20, 0x2b8d0420}, - {__LINE__, 0x1, (const uint8_t *)"85181542907229116674", 20, 0x2b140419}, - {__LINE__, 0x1, (const uint8_t *)"87963594337989416799", 20, 0x2c8e043f}, - {__LINE__, 0x1, (const uint8_t *)"21395988329504168551", 20, 0x2b68041f}, - {__LINE__, 0x1, (const uint8_t *)"51991013580943379423", 20, 0x2af10417}, - {__LINE__, 0x1, (const uint8_t *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x7c9d0841}, - {__LINE__, 0x1, (const uint8_t *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0x71060751}, - {__LINE__, 0x1, (const uint8_t *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0x7095070a}, - {__LINE__, 0x1, (const uint8_t *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x82530815}, - {__LINE__, 0x1, (const uint8_t *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x61250661}, - {__LINE__, 0x1, (const uint8_t *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x642006a3}, - {__LINE__, 0x1, (const uint8_t *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x674206cb}, - {__LINE__, 0x1, (const uint8_t *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x67670680}, - {__LINE__, 0x1, (const uint8_t *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0x7547070f}, - {__LINE__, 0x1, (const uint8_t *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x69ea06ee}, - {__LINE__, 0x1, (const uint8_t *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0x1b01e92}, - {__LINE__, 0x1, (const uint8_t *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xfbdb1e96}, - {__LINE__, 0x1, (const uint8_t *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0x47a61ec8}, - {__LINE__, 0x1, (const uint8_t *)long_string, 5552, 0x8b81718f}, - {__LINE__, 0x7a30360d, (const uint8_t *)0x0, 0, 0x1}, - {__LINE__, 0x6fd767ee, (const uint8_t *)"", 1, 0xd7c567ee}, - {__LINE__, 0xefeb7589, (const uint8_t *)"a", 1, 0x65e475ea}, - {__LINE__, 0x61cf7e6b, (const uint8_t *)"abacus", 6, 0x60b880da}, - {__LINE__, 0xdc712e2, (const uint8_t *)"backlog", 7, 0x9d0d15b5}, - {__LINE__, 0xad23c7fd, (const uint8_t *)"campfire", 8, 0xfbfecb44}, - {__LINE__, 0x85cb2317, (const uint8_t *)"delta", 5, 0x3b622521}, - {__LINE__, 0x9eed31b0, (const uint8_t *)"executable", 10, 0xa6db35d2}, - {__LINE__, 0xb94f34ca, (const uint8_t *)"file", 4, 0x9096366a}, - {__LINE__, 0xab058a2, (const uint8_t *)"greatest", 8, 0xded05c01}, - {__LINE__, 0x5bff2b7a, (const uint8_t *)"inverter", 8, 0xc7452ee9}, - {__LINE__, 0x605c9a5f, (const uint8_t *)"jigsaw", 6, 0x7899ce4}, - {__LINE__, 0x51bdeea5, (const uint8_t *)"karate", 6, 0xf285f11d}, - {__LINE__, 0x85c21c79, (const uint8_t *)"landscape", 9, 0x98732024}, - {__LINE__, 0x97216f56, (const uint8_t *)"machine", 7, 0xadf4722b}, - {__LINE__, 0x18444af2, (const uint8_t *)"nanometer", 9, 0xcdb34ebb}, - {__LINE__, 0xbe6ce359, (const uint8_t *)"oblivion", 8, 0xe8b7e6bb}, - {__LINE__, 0x843071f1, (const uint8_t *)"panama", 6, 0x389e745f}, - {__LINE__, 0xf2480c60, (const uint8_t *)"quest", 5, 0x36c90e92}, - {__LINE__, 0x2d2feb3d, (const uint8_t *)"resource", 8, 0x9705eea5}, - {__LINE__, 0x7490310a, (const uint8_t *)"secret", 6, 0xa3a63390}, - {__LINE__, 0x97d247d4, (const uint8_t *)"ultimate", 8, 0xe6154b39}, - {__LINE__, 0x93cf7599, (const uint8_t *)"vector", 6, 0x5e87782c}, - {__LINE__, 0x73c84278, (const uint8_t *)"walrus", 6, 0xbc84516}, - {__LINE__, 0x228a87d1, (const uint8_t *)"xeno", 4, 0x4646898b}, - {__LINE__, 0xa7a048d0, (const uint8_t *)"yelling", 7, 0xb1654bc4}, - {__LINE__, 0x1f0ded40, (const uint8_t *)"zero", 4, 0xd8a4ef00}, - {__LINE__, 0xa804a62f, (const uint8_t *)"4BJD7PocN1VqX0jXVpWB", 20, 0xe34eac7b}, - {__LINE__, 0x508fae6a, (const uint8_t *)"F1rPWI7XvDs6nAIRx41l", 20, 0x33f2b4c8}, - {__LINE__, 0xe5adaf4f, (const uint8_t *)"ldhKlsVkPFOveXgkGtC2", 20, 0xe7b1b68c}, - {__LINE__, 0x67136a40, (const uint8_t *)"5KKnGOOrs8BvJ35iKTOS", 20, 0xf6a0708f}, - {__LINE__, 0xb00c4a10, (const uint8_t *)"0l1tw7GOcem06Ddu7yn4", 20, 0xbd8f509f}, - {__LINE__, 0x2e0c84b5, (const uint8_t *)"MCr47CjPIn9R1IvE1Tm5", 20, 0xcc298abd}, - {__LINE__, 0x81238d44, (const uint8_t *)"UcixbzPKTIv0SvILHVdO", 20, 0xd7809446}, - {__LINE__, 0xf853aa92, (const uint8_t *)"dGnAyAhRQDsWw0ESou24", 20, 0x9525b148}, - {__LINE__, 0x5a692325, (const uint8_t *)"di0nvmY9UYMYDh0r45XT", 20, 0x620029bc}, - {__LINE__, 0x3275b9f, (const uint8_t *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x70916284}, - {__LINE__, 0x38371feb, (const uint8_t *)"ZhrANFIiIvRnqClIVyeD", 20, 0xd52706}, - {__LINE__, 0xafc8bf62, (const uint8_t *)"v7Q9ehzioTOVeDIZioT1", 20, 0xeeb4c65a}, - {__LINE__, 0x9b07db73, (const uint8_t *)"Yod5hEeKcYqyhfXbhxj2", 20, 0xde3e2db}, - {__LINE__, 0xe75b214, (const uint8_t *)"GehSWY2ay4uUKhehXYb0", 20, 0x4171b8f8}, - {__LINE__, 0x72d0fe6f, (const uint8_t *)"kwytJmq6UqpflV8Y8GoE", 20, 0xa66a05cd}, - {__LINE__, 0xf857a4b1, (const uint8_t *)"70684206568419061514", 20, 0x1f9a8c4}, - {__LINE__, 0x54b8e14, (const uint8_t *)"42015093765128581010", 20, 0x49c19218}, - {__LINE__, 0xd6aa5616, (const uint8_t *)"88214814356148806939", 20, 0xbbfc5a38}, - {__LINE__, 0x11e63098, (const uint8_t *)"43472694284527343838", 20, 0x93434b8}, - {__LINE__, 0xbe92385, (const uint8_t *)"49769333513942933689", 20, 0xfe1827af}, - {__LINE__, 0x49511de0, (const uint8_t *)"54979784887993251199", 20, 0xcba8221c}, - {__LINE__, 0x3db13bc1, (const uint8_t *)"58360544869206793220", 20, 0x14643fda}, - {__LINE__, 0xbb899bea, (const uint8_t *)"27347953487840714234", 20, 0x1604a006}, - {__LINE__, 0xf6cd9436, (const uint8_t *)"07650690295365319082", 20, 0xb69f984c}, - {__LINE__, 0x9109e6c3, (const uint8_t *)"42655507906821911703", 20, 0xc43eead4}, - {__LINE__, 0x75770fc, (const uint8_t *)"29977409200786225655", 20, 0x707751b}, - {__LINE__, 0x69b1d19b, (const uint8_t *)"85181542907229116674", 20, 0xf5bdd5b3}, - {__LINE__, 0xc6132975, (const uint8_t *)"87963594337989416799", 20, 0x2fed2db3}, - {__LINE__, 0xd58cb00c, (const uint8_t *)"21395988329504168551", 20, 0xc2a2b42a}, - {__LINE__, 0xb63b8caa, (const uint8_t *)"51991013580943379423", 20, 0xdf0590c0}, - {__LINE__, 0x8a45a2b8, (const uint8_t *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x1980aaf8}, - {__LINE__, 0xcbe95b78, (const uint8_t *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0xf58662c8}, - {__LINE__, 0x4ef8a54b, (const uint8_t *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0x1f65ac54}, - {__LINE__, 0x76ad267a, (const uint8_t *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x7b792e8e}, - {__LINE__, 0x569e613c, (const uint8_t *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x1d61679c}, - {__LINE__, 0x36aa61da, (const uint8_t *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x12ec687c}, - {__LINE__, 0xf67222df, (const uint8_t *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x740329a9}, - {__LINE__, 0x74b34fd3, (const uint8_t *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x374c5652}, - {__LINE__, 0x351fd770, (const uint8_t *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xeadfde7e}, - {__LINE__, 0xc45aef77, (const uint8_t *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x3fcbf664}, - {__LINE__, 0xd034ea71, (const uint8_t *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0x6b080911}, - {__LINE__, 0xdeadc0de, (const uint8_t *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0x355fdf73}, - {__LINE__, 0xba5eba11, (const uint8_t *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xb48bd8d8}, - {__LINE__, 0x7712aa45, (const uint8_t *)long_string, 5552, 0x7dc51be2}, + {0x1, (const uint8_t *)0x0, 0, 0x1}, + {0x1, (const uint8_t *)"", 1, 0x10001}, + {0x1, (const uint8_t *)"a", 1, 0x620062}, + {0x1, (const uint8_t *)"abacus", 6, 0x8400270}, + {0x1, (const uint8_t *)"backlog", 7, 0xb1f02d4}, + {0x1, (const uint8_t *)"campfire", 8, 0xea10348}, + {0x1, (const uint8_t *)"delta", 5, 0x61a020b}, + {0x1, (const uint8_t *)"executable", 10, 0x16fa0423}, + {0x1, (const uint8_t *)"file", 4, 0x41401a1}, + {0x1, (const uint8_t *)"greatest", 8, 0xefa0360}, + {0x1, (const uint8_t *)"inverter", 8, 0xf6f0370}, + {0x1, (const uint8_t *)"jigsaw", 6, 0x8bd0286}, + {0x1, (const uint8_t *)"karate", 6, 0x8a50279}, + {0x1, (const uint8_t *)"landscape", 9, 0x126a03ac}, + {0x1, (const uint8_t *)"machine", 7, 0xb5302d6}, + {0x1, (const uint8_t *)"nanometer", 9, 0x12d803ca}, + {0x1, (const uint8_t *)"oblivion", 8, 0xf220363}, + {0x1, (const uint8_t *)"panama", 6, 0x8a1026f}, + {0x1, (const uint8_t *)"quest", 5, 0x6970233}, + {0x1, (const uint8_t *)"resource", 8, 0xf8d0369}, + {0x1, (const uint8_t *)"secret", 6, 0x8d10287}, + {0x1, (const uint8_t *)"ultimate", 8, 0xf8d0366}, + {0x1, (const uint8_t *)"vector", 6, 0x8fb0294}, + {0x1, (const uint8_t *)"walrus", 6, 0x918029f}, + {0x1, (const uint8_t *)"xeno", 4, 0x45e01bb}, + {0x1, (const uint8_t *)"yelling", 7, 0xbfe02f5}, + {0x1, (const uint8_t *)"zero", 4, 0x46e01c1}, + {0x1, (const uint8_t *)"4BJD7PocN1VqX0jXVpWB", 20, 0x3eef064d}, + {0x1, (const uint8_t *)"F1rPWI7XvDs6nAIRx41l", 20, 0x425d065f}, + {0x1, (const uint8_t *)"ldhKlsVkPFOveXgkGtC2", 20, 0x4f1a073e}, + {0x1, (const uint8_t *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x42290650}, + {0x1, (const uint8_t *)"0l1tw7GOcem06Ddu7yn4", 20, 0x43fd0690}, + {0x1, (const uint8_t *)"MCr47CjPIn9R1IvE1Tm5", 20, 0x3f770609}, + {0x1, (const uint8_t *)"UcixbzPKTIv0SvILHVdO", 20, 0x4c7c0703}, + {0x1, (const uint8_t *)"dGnAyAhRQDsWw0ESou24", 20, 0x48ac06b7}, + {0x1, (const uint8_t *)"di0nvmY9UYMYDh0r45XT", 20, 0x489a0698}, + {0x1, (const uint8_t *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x44a906e6}, + {0x1, (const uint8_t *)"ZhrANFIiIvRnqClIVyeD", 20, 0x4a29071c}, + {0x1, (const uint8_t *)"v7Q9ehzioTOVeDIZioT1", 20, 0x4a7706f9}, + {0x1, (const uint8_t *)"Yod5hEeKcYqyhfXbhxj2", 20, 0x4ce60769}, + {0x1, (const uint8_t *)"GehSWY2ay4uUKhehXYb0", 20, 0x48ae06e5}, + {0x1, (const uint8_t *)"kwytJmq6UqpflV8Y8GoE", 20, 0x51d60750}, + {0x1, (const uint8_t *)"70684206568419061514", 20, 0x2b100414}, + {0x1, (const uint8_t *)"42015093765128581010", 20, 0x2a550405}, + {0x1, (const uint8_t *)"88214814356148806939", 20, 0x2b450423}, + {0x1, (const uint8_t *)"43472694284527343838", 20, 0x2b460421}, + {0x1, (const uint8_t *)"49769333513942933689", 20, 0x2bc1042b}, + {0x1, (const uint8_t *)"54979784887993251199", 20, 0x2ccd043d}, + {0x1, (const uint8_t *)"58360544869206793220", 20, 0x2b68041a}, + {0x1, (const uint8_t *)"27347953487840714234", 20, 0x2b84041d}, + {0x1, (const uint8_t *)"07650690295365319082", 20, 0x2afa0417}, + {0x1, (const uint8_t *)"42655507906821911703", 20, 0x2aff0412}, + {0x1, (const uint8_t *)"29977409200786225655", 20, 0x2b8d0420}, + {0x1, (const uint8_t *)"85181542907229116674", 20, 0x2b140419}, + {0x1, (const uint8_t *)"87963594337989416799", 20, 0x2c8e043f}, + {0x1, (const uint8_t *)"21395988329504168551", 20, 0x2b68041f}, + {0x1, (const uint8_t *)"51991013580943379423", 20, 0x2af10417}, + {0x1, (const uint8_t *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x7c9d0841}, + {0x1, (const uint8_t *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0x71060751}, + {0x1, (const uint8_t *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0x7095070a}, + {0x1, (const uint8_t *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x82530815}, + {0x1, (const uint8_t *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x61250661}, + {0x1, (const uint8_t *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x642006a3}, + {0x1, (const uint8_t *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x674206cb}, + {0x1, (const uint8_t *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x67670680}, + {0x1, (const uint8_t *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0x7547070f}, + {0x1, (const uint8_t *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x69ea06ee}, + {0x1, (const uint8_t *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0x1b01e92}, + {0x1, (const uint8_t *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xfbdb1e96}, + {0x1, (const uint8_t *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0x47a61ec8}, + {0x1, (const uint8_t *)long_string, 5552, 0x8b81718f}, + {0x7a30360d, (const uint8_t *)0x0, 0, 0x1}, + {0x6fd767ee, (const uint8_t *)"", 1, 0xd7c567ee}, + {0xefeb7589, (const uint8_t *)"a", 1, 0x65e475ea}, + {0x61cf7e6b, (const uint8_t *)"abacus", 6, 0x60b880da}, + {0xdc712e2, (const uint8_t *)"backlog", 7, 0x9d0d15b5}, + {0xad23c7fd, (const uint8_t *)"campfire", 8, 0xfbfecb44}, + {0x85cb2317, (const uint8_t *)"delta", 5, 0x3b622521}, + {0x9eed31b0, (const uint8_t *)"executable", 10, 0xa6db35d2}, + {0xb94f34ca, (const uint8_t *)"file", 4, 0x9096366a}, + {0xab058a2, (const uint8_t *)"greatest", 8, 0xded05c01}, + {0x5bff2b7a, (const uint8_t *)"inverter", 8, 0xc7452ee9}, + {0x605c9a5f, (const uint8_t *)"jigsaw", 6, 0x7899ce4}, + {0x51bdeea5, (const uint8_t *)"karate", 6, 0xf285f11d}, + {0x85c21c79, (const uint8_t *)"landscape", 9, 0x98732024}, + {0x97216f56, (const uint8_t *)"machine", 7, 0xadf4722b}, + {0x18444af2, (const uint8_t *)"nanometer", 9, 0xcdb34ebb}, + {0xbe6ce359, (const uint8_t *)"oblivion", 8, 0xe8b7e6bb}, + {0x843071f1, (const uint8_t *)"panama", 6, 0x389e745f}, + {0xf2480c60, (const uint8_t *)"quest", 5, 0x36c90e92}, + {0x2d2feb3d, (const uint8_t *)"resource", 8, 0x9705eea5}, + {0x7490310a, (const uint8_t *)"secret", 6, 0xa3a63390}, + {0x97d247d4, (const uint8_t *)"ultimate", 8, 0xe6154b39}, + {0x93cf7599, (const uint8_t *)"vector", 6, 0x5e87782c}, + {0x73c84278, (const uint8_t *)"walrus", 6, 0xbc84516}, + {0x228a87d1, (const uint8_t *)"xeno", 4, 0x4646898b}, + {0xa7a048d0, (const uint8_t *)"yelling", 7, 0xb1654bc4}, + {0x1f0ded40, (const uint8_t *)"zero", 4, 0xd8a4ef00}, + {0xa804a62f, (const uint8_t *)"4BJD7PocN1VqX0jXVpWB", 20, 0xe34eac7b}, + {0x508fae6a, (const uint8_t *)"F1rPWI7XvDs6nAIRx41l", 20, 0x33f2b4c8}, + {0xe5adaf4f, (const uint8_t *)"ldhKlsVkPFOveXgkGtC2", 20, 0xe7b1b68c}, + {0x67136a40, (const uint8_t *)"5KKnGOOrs8BvJ35iKTOS", 20, 0xf6a0708f}, + {0xb00c4a10, (const uint8_t *)"0l1tw7GOcem06Ddu7yn4", 20, 0xbd8f509f}, + {0x2e0c84b5, (const uint8_t *)"MCr47CjPIn9R1IvE1Tm5", 20, 0xcc298abd}, + {0x81238d44, (const uint8_t *)"UcixbzPKTIv0SvILHVdO", 20, 0xd7809446}, + {0xf853aa92, (const uint8_t *)"dGnAyAhRQDsWw0ESou24", 20, 0x9525b148}, + {0x5a692325, (const uint8_t *)"di0nvmY9UYMYDh0r45XT", 20, 0x620029bc}, + {0x3275b9f, (const uint8_t *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x70916284}, + {0x38371feb, (const uint8_t *)"ZhrANFIiIvRnqClIVyeD", 20, 0xd52706}, + {0xafc8bf62, (const uint8_t *)"v7Q9ehzioTOVeDIZioT1", 20, 0xeeb4c65a}, + {0x9b07db73, (const uint8_t *)"Yod5hEeKcYqyhfXbhxj2", 20, 0xde3e2db}, + {0xe75b214, (const uint8_t *)"GehSWY2ay4uUKhehXYb0", 20, 0x4171b8f8}, + {0x72d0fe6f, (const uint8_t *)"kwytJmq6UqpflV8Y8GoE", 20, 0xa66a05cd}, + {0xf857a4b1, (const uint8_t *)"70684206568419061514", 20, 0x1f9a8c4}, + {0x54b8e14, (const uint8_t *)"42015093765128581010", 20, 0x49c19218}, + {0xd6aa5616, (const uint8_t *)"88214814356148806939", 20, 0xbbfc5a38}, + {0x11e63098, (const uint8_t *)"43472694284527343838", 20, 0x93434b8}, + {0xbe92385, (const uint8_t *)"49769333513942933689", 20, 0xfe1827af}, + {0x49511de0, (const uint8_t *)"54979784887993251199", 20, 0xcba8221c}, + {0x3db13bc1, (const uint8_t *)"58360544869206793220", 20, 0x14643fda}, + {0xbb899bea, (const uint8_t *)"27347953487840714234", 20, 0x1604a006}, + {0xf6cd9436, (const uint8_t *)"07650690295365319082", 20, 0xb69f984c}, + {0x9109e6c3, (const uint8_t *)"42655507906821911703", 20, 0xc43eead4}, + {0x75770fc, (const uint8_t *)"29977409200786225655", 20, 0x707751b}, + {0x69b1d19b, (const uint8_t *)"85181542907229116674", 20, 0xf5bdd5b3}, + {0xc6132975, (const uint8_t *)"87963594337989416799", 20, 0x2fed2db3}, + {0xd58cb00c, (const uint8_t *)"21395988329504168551", 20, 0xc2a2b42a}, + {0xb63b8caa, (const uint8_t *)"51991013580943379423", 20, 0xdf0590c0}, + {0x8a45a2b8, (const uint8_t *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x1980aaf8}, + {0xcbe95b78, (const uint8_t *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0xf58662c8}, + {0x4ef8a54b, (const uint8_t *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0x1f65ac54}, + {0x76ad267a, (const uint8_t *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x7b792e8e}, + {0x569e613c, (const uint8_t *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x1d61679c}, + {0x36aa61da, (const uint8_t *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x12ec687c}, + {0xf67222df, (const uint8_t *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x740329a9}, + {0x74b34fd3, (const uint8_t *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x374c5652}, + {0x351fd770, (const uint8_t *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xeadfde7e}, + {0xc45aef77, (const uint8_t *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x3fcbf664}, + {0xd034ea71, (const uint8_t *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0x6b080911}, + {0xdeadc0de, (const uint8_t *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0x355fdf73}, + {0xba5eba11, (const uint8_t *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xb48bd8d8}, + {0x7712aa45, (const uint8_t *)long_string, 5552, 0x7dc51be2}, +}; + +class adler32_variant : public ::testing::TestWithParam { +public: + void hash(adler32_test param, adler32_func adler32) { + uint32_t adler = adler32((uint32_t)param.adler, param.buf, param.len); + EXPECT_EQ(adler, param.expect); + } }; -static const int test_size = sizeof(tests) / sizeof(tests[0]); +INSTANTIATE_TEST_SUITE_P(adler32, adler32_variant, testing::ValuesIn(tests)); -int main(void) { - int i; - for (i = 0; i < test_size; i++) { - test_adler32(tests[i].adler, tests[i].buf, tests[i].len, tests[i].expect, tests[i].line); +#define TEST_ADLER32(name, func, support_flag) \ + TEST_P(adler32_variant, name) { \ + if (!support_flag) { \ + GTEST_SKIP(); \ + return; \ + } \ + hash(GetParam(), func); \ } - return 0; -} +TEST_ADLER32(c, adler32_c, 1) + +#ifdef ARM_NEON_ADLER32 +TEST_ADLER32(neon, adler32_neon, arm_cpu_has_neon) +#elif defined(POWER8_VSX_ADLER32) +TEST_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07) +#elif defined(PPC_VMX_ADLER32) +TEST_ADLER32(vmx, adler32_vmx, power_cpu_has_altivec) +#endif + +#ifdef X86_SSSE3_ADLER32 +TEST_ADLER32(ssse3, adler32_ssse3, x86_cpu_has_ssse3) +#endif +#ifdef X86_SSE41_ADLER32 +TEST_ADLER32(sse41, adler32_sse41, x86_cpu_has_sse41) +#endif +#ifdef X86_AVX2_ADLER32 +TEST_ADLER32(avx2, adler32_avx2, x86_cpu_has_avx2) +#endif +#ifdef X86_AVX512_ADLER32 +TEST_ADLER32(avx512, adler32_avx512, x86_cpu_has_avx512) +#endif +#ifdef X86_AVX512VNNI_ADLER32 +TEST_ADLER32(avx512_vnni, adler32_avx512_vnni, x86_cpu_has_avx512vnni) +#endif diff --git a/test/test_compress.cc b/test/test_compress.cc new file mode 100644 index 0000000000..9885b33014 --- /dev/null +++ b/test/test_compress.cc @@ -0,0 +1,33 @@ +/* test_compress.cc - Test compress() and uncompress() using hello world string */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(compress, basic) { + uint8_t compr[128], uncompr[128]; + z_size_t compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); + int err; + + err = PREFIX(compress)(compr, &compr_len, (const unsigned char *)hello, hello_len); + EXPECT_EQ(err, Z_OK); + + strcpy((char*)uncompr, "garbage"); + + err = PREFIX(uncompress)(uncompr, &uncompr_len, compr, compr_len); + EXPECT_EQ(err, Z_OK); + + EXPECT_STREQ((char *)uncompr, (char *)hello); +} diff --git a/test/test_crc32.c b/test/test_crc32.c deleted file mode 100644 index 83718eb0bc..0000000000 --- a/test/test_crc32.c +++ /dev/null @@ -1,197 +0,0 @@ -/* test_crc32.c -- crc32 unit test - * Copyright (C) 2019-2021 IBM Corporation - * Authors: Rogerio Alves - * Matheus Castanho - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#include - -typedef struct { - uint32_t line; - unsigned long crc; - const unsigned char *buf; - size_t len; - unsigned long expect; -} crc32_test; - -void test_crc32(unsigned long crc, const unsigned char *buf, size_t len, uint32_t chk, uint32_t line) { - uint32_t res = PREFIX(crc32_z)((uint32_t)crc, buf, len); - if (res != chk) { - fprintf(stderr, "FAIL [%d]: crc32 returned 0x%08X expected 0x%08X\n", - line, res, chk); - exit(1); - } -} - -static const crc32_test tests[] = { - {__LINE__, 0x0, (const unsigned char *)0x0, 0, 0x0}, - {__LINE__, 0xffffffff, (const unsigned char *)0x0, 0, 0x0}, - {__LINE__, 0x0, (const unsigned char *)0x0, 255, 0x0}, /* BZ 174799. */ - {__LINE__, 0x0, (const unsigned char *)0x0, 256, 0x0}, - {__LINE__, 0x0, (const unsigned char *)0x0, 257, 0x0}, - {__LINE__, 0x0, (const unsigned char *)0x0, 32767, 0x0}, - {__LINE__, 0x0, (const unsigned char *)0x0, 32768, 0x0}, - {__LINE__, 0x0, (const unsigned char *)0x0, 32769, 0x0}, - {__LINE__, 0x0, (const unsigned char *)"", 0, 0x0}, - {__LINE__, 0xffffffff, (const unsigned char *)"", 0, 0xffffffff}, - {__LINE__, 0x0, (const unsigned char *)"abacus", 6, 0xc3d7115b}, - {__LINE__, 0x0, (const unsigned char *)"backlog", 7, 0x269205}, - {__LINE__, 0x0, (const unsigned char *)"campfire", 8, 0x22a515f8}, - {__LINE__, 0x0, (const unsigned char *)"delta", 5, 0x9643fed9}, - {__LINE__, 0x0, (const unsigned char *)"executable", 10, 0xd68eda01}, - {__LINE__, 0x0, (const unsigned char *)"file", 4, 0x8c9f3610}, - {__LINE__, 0x0, (const unsigned char *)"greatest", 8, 0xc1abd6cd}, - {__LINE__, 0x0, (const unsigned char *)"hello", 5, 0x3610a686}, - {__LINE__, 0x0, (const unsigned char *)"inverter", 8, 0xc9e962c9}, - {__LINE__, 0x0, (const unsigned char *)"jigsaw", 6, 0xce4e3f69}, - {__LINE__, 0x0, (const unsigned char *)"karate", 6, 0x890be0e2}, - {__LINE__, 0x0, (const unsigned char *)"landscape", 9, 0xc4e0330b}, - {__LINE__, 0x0, (const unsigned char *)"machine", 7, 0x1505df84}, - {__LINE__, 0x0, (const unsigned char *)"nanometer", 9, 0xd4e19f39}, - {__LINE__, 0x0, (const unsigned char *)"oblivion", 8, 0xdae9de77}, - {__LINE__, 0x0, (const unsigned char *)"panama", 6, 0x66b8979c}, - {__LINE__, 0x0, (const unsigned char *)"quest", 5, 0x4317f817}, - {__LINE__, 0x0, (const unsigned char *)"resource", 8, 0xbc91f416}, - {__LINE__, 0x0, (const unsigned char *)"secret", 6, 0x5ca2e8e5}, - {__LINE__, 0x0, (const unsigned char *)"test", 4, 0xd87f7e0c}, - {__LINE__, 0x0, (const unsigned char *)"ultimate", 8, 0x3fc79b0b}, - {__LINE__, 0x0, (const unsigned char *)"vector", 6, 0x1b6e485b}, - {__LINE__, 0x0, (const unsigned char *)"walrus", 6, 0xbe769b97}, - {__LINE__, 0x0, (const unsigned char *)"xeno", 4, 0xe7a06444}, - {__LINE__, 0x0, (const unsigned char *)"yelling", 7, 0xfe3944e5}, - {__LINE__, 0x0, (const unsigned char *)"zlib", 4, 0x73887d3a}, - {__LINE__, 0x0, (const unsigned char *)"4BJD7PocN1VqX0jXVpWB", 20, 0xd487a5a1}, - {__LINE__, 0x0, (const unsigned char *)"F1rPWI7XvDs6nAIRx41l", 20, 0x61a0132e}, - {__LINE__, 0x0, (const unsigned char *)"ldhKlsVkPFOveXgkGtC2", 20, 0xdf02f76}, - {__LINE__, 0x0, (const unsigned char *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x579b2b0a}, - {__LINE__, 0x0, (const unsigned char *)"0l1tw7GOcem06Ddu7yn4", 20, 0xf7d16e2d}, - {__LINE__, 0x0, (const unsigned char *)"MCr47CjPIn9R1IvE1Tm5", 20, 0x731788f5}, - {__LINE__, 0x0, (const unsigned char *)"UcixbzPKTIv0SvILHVdO", 20, 0x7112bb11}, - {__LINE__, 0x0, (const unsigned char *)"dGnAyAhRQDsWw0ESou24", 20, 0xf32a0dac}, - {__LINE__, 0x0, (const unsigned char *)"di0nvmY9UYMYDh0r45XT", 20, 0x625437bb}, - {__LINE__, 0x0, (const unsigned char *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x896930f9}, - {__LINE__, 0x0, (const unsigned char *)"ZhrANFIiIvRnqClIVyeD", 20, 0x8579a37}, - {__LINE__, 0x0, (const unsigned char *)"v7Q9ehzioTOVeDIZioT1", 20, 0x632aa8e0}, - {__LINE__, 0x0, (const unsigned char *)"Yod5hEeKcYqyhfXbhxj2", 20, 0xc829af29}, - {__LINE__, 0x0, (const unsigned char *)"GehSWY2ay4uUKhehXYb0", 20, 0x1b08b7e8}, - {__LINE__, 0x0, (const unsigned char *)"kwytJmq6UqpflV8Y8GoE", 20, 0x4e33b192}, - {__LINE__, 0x0, (const unsigned char *)"70684206568419061514", 20, 0x59a179f0}, - {__LINE__, 0x0, (const unsigned char *)"42015093765128581010", 20, 0xcd1013d7}, - {__LINE__, 0x0, (const unsigned char *)"88214814356148806939", 20, 0xab927546}, - {__LINE__, 0x0, (const unsigned char *)"43472694284527343838", 20, 0x11f3b20c}, - {__LINE__, 0x0, (const unsigned char *)"49769333513942933689", 20, 0xd562d4ca}, - {__LINE__, 0x0, (const unsigned char *)"54979784887993251199", 20, 0x233395f7}, - {__LINE__, 0x0, (const unsigned char *)"58360544869206793220", 20, 0x2d167fd5}, - {__LINE__, 0x0, (const unsigned char *)"27347953487840714234", 20, 0x8b5108ba}, - {__LINE__, 0x0, (const unsigned char *)"07650690295365319082", 20, 0xc46b3cd8}, - {__LINE__, 0x0, (const unsigned char *)"42655507906821911703", 20, 0xc10b2662}, - {__LINE__, 0x0, (const unsigned char *)"29977409200786225655", 20, 0xc9a0f9d2}, - {__LINE__, 0x0, (const unsigned char *)"85181542907229116674", 20, 0x9341357b}, - {__LINE__, 0x0, (const unsigned char *)"87963594337989416799", 20, 0xf0424937}, - {__LINE__, 0x0, (const unsigned char *)"21395988329504168551", 20, 0xd7c4c31f}, - {__LINE__, 0x0, (const unsigned char *)"51991013580943379423", 20, 0xf11edcc4}, - {__LINE__, 0x0, (const unsigned char *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x40795df4}, - {__LINE__, 0x0, (const unsigned char *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0xdd61a631}, - {__LINE__, 0x0, (const unsigned char *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0xca907a99}, - {__LINE__, 0x0, (const unsigned char *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0xf652deac}, - {__LINE__, 0x0, (const unsigned char *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0xaf39a5a9}, - {__LINE__, 0x0, (const unsigned char *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x6bebb4cf}, - {__LINE__, 0x0, (const unsigned char *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x76430bac}, - {__LINE__, 0x0, (const unsigned char *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x6c80c388}, - {__LINE__, 0x0, (const unsigned char *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xd54d977d}, - {__LINE__, 0x0, (const unsigned char *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0xe3966ad5}, - {__LINE__, 0x0, (const unsigned char *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0xe7c71db9}, - {__LINE__, 0x0, (const unsigned char *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xeaa52777}, - {__LINE__, 0x0, (const unsigned char *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xcd472048}, - {__LINE__, 0x7a30360d, (const unsigned char *)"abacus", 6, 0xf8655a84}, - {__LINE__, 0x6fd767ee, (const unsigned char *)"backlog", 7, 0x1ed834b1}, - {__LINE__, 0xefeb7589, (const unsigned char *)"campfire", 8, 0x686cfca}, - {__LINE__, 0x61cf7e6b, (const unsigned char *)"delta", 5, 0x1554e4b1}, - {__LINE__, 0xdc712e2, (const unsigned char *)"executable", 10, 0x761b4254}, - {__LINE__, 0xad23c7fd, (const unsigned char *)"file", 4, 0x7abdd09b}, - {__LINE__, 0x85cb2317, (const unsigned char *)"greatest", 8, 0x4ba91c6b}, - {__LINE__, 0x9eed31b0, (const unsigned char *)"inverter", 8, 0xd5e78ba5}, - {__LINE__, 0xb94f34ca, (const unsigned char *)"jigsaw", 6, 0x23649109}, - {__LINE__, 0xab058a2, (const unsigned char *)"karate", 6, 0xc5591f41}, - {__LINE__, 0x5bff2b7a, (const unsigned char *)"landscape", 9, 0xf10eb644}, - {__LINE__, 0x605c9a5f, (const unsigned char *)"machine", 7, 0xbaa0a636}, - {__LINE__, 0x51bdeea5, (const unsigned char *)"nanometer", 9, 0x6af89afb}, - {__LINE__, 0x85c21c79, (const unsigned char *)"oblivion", 8, 0xecae222b}, - {__LINE__, 0x97216f56, (const unsigned char *)"panama", 6, 0x47dffac4}, - {__LINE__, 0x18444af2, (const unsigned char *)"quest", 5, 0x70c2fe36}, - {__LINE__, 0xbe6ce359, (const unsigned char *)"resource", 8, 0x1471d925}, - {__LINE__, 0x843071f1, (const unsigned char *)"secret", 6, 0x50c9a0db}, - {__LINE__, 0xf2480c60, (const unsigned char *)"ultimate", 8, 0xf973daf8}, - {__LINE__, 0x2d2feb3d, (const unsigned char *)"vector", 6, 0x344ac03d}, - {__LINE__, 0x7490310a, (const unsigned char *)"walrus", 6, 0x6d1408ef}, - {__LINE__, 0x97d247d4, (const unsigned char *)"xeno", 4, 0xe62670b5}, - {__LINE__, 0x93cf7599, (const unsigned char *)"yelling", 7, 0x1b36da38}, - {__LINE__, 0x73c84278, (const unsigned char *)"zlib", 4, 0x6432d127}, - {__LINE__, 0x228a87d1, (const unsigned char *)"4BJD7PocN1VqX0jXVpWB", 20, 0x997107d0}, - {__LINE__, 0xa7a048d0, (const unsigned char *)"F1rPWI7XvDs6nAIRx41l", 20, 0xdc567274}, - {__LINE__, 0x1f0ded40, (const unsigned char *)"ldhKlsVkPFOveXgkGtC2", 20, 0xdcc63870}, - {__LINE__, 0xa804a62f, (const unsigned char *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x6926cffd}, - {__LINE__, 0x508fae6a, (const unsigned char *)"0l1tw7GOcem06Ddu7yn4", 20, 0xb52b38bc}, - {__LINE__, 0xe5adaf4f, (const unsigned char *)"MCr47CjPIn9R1IvE1Tm5", 20, 0xf83b8178}, - {__LINE__, 0x67136a40, (const unsigned char *)"UcixbzPKTIv0SvILHVdO", 20, 0xc5213070}, - {__LINE__, 0xb00c4a10, (const unsigned char *)"dGnAyAhRQDsWw0ESou24", 20, 0xbc7648b0}, - {__LINE__, 0x2e0c84b5, (const unsigned char *)"di0nvmY9UYMYDh0r45XT", 20, 0xd8123a72}, - {__LINE__, 0x81238d44, (const unsigned char *)"2XKDwHfAhFsV0RhbqtvH", 20, 0xd5ac5620}, - {__LINE__, 0xf853aa92, (const unsigned char *)"ZhrANFIiIvRnqClIVyeD", 20, 0xceae099d}, - {__LINE__, 0x5a692325, (const unsigned char *)"v7Q9ehzioTOVeDIZioT1", 20, 0xb07d2b24}, - {__LINE__, 0x3275b9f, (const unsigned char *)"Yod5hEeKcYqyhfXbhxj2", 20, 0x24ce91df}, - {__LINE__, 0x38371feb, (const unsigned char *)"GehSWY2ay4uUKhehXYb0", 20, 0x707b3b30}, - {__LINE__, 0xafc8bf62, (const unsigned char *)"kwytJmq6UqpflV8Y8GoE", 20, 0x16abc6a9}, - {__LINE__, 0x9b07db73, (const unsigned char *)"70684206568419061514", 20, 0xae1fb7b7}, - {__LINE__, 0xe75b214, (const unsigned char *)"42015093765128581010", 20, 0xd4eecd2d}, - {__LINE__, 0x72d0fe6f, (const unsigned char *)"88214814356148806939", 20, 0x4660ec7}, - {__LINE__, 0xf857a4b1, (const unsigned char *)"43472694284527343838", 20, 0xfd8afdf7}, - {__LINE__, 0x54b8e14, (const unsigned char *)"49769333513942933689", 20, 0xc6d1b5f2}, - {__LINE__, 0xd6aa5616, (const unsigned char *)"54979784887993251199", 20, 0x32476461}, - {__LINE__, 0x11e63098, (const unsigned char *)"58360544869206793220", 20, 0xd917cf1a}, - {__LINE__, 0xbe92385, (const unsigned char *)"27347953487840714234", 20, 0x4ad14a12}, - {__LINE__, 0x49511de0, (const unsigned char *)"07650690295365319082", 20, 0xe37b5c6c}, - {__LINE__, 0x3db13bc1, (const unsigned char *)"42655507906821911703", 20, 0x7cc497f1}, - {__LINE__, 0xbb899bea, (const unsigned char *)"29977409200786225655", 20, 0x99781bb2}, - {__LINE__, 0xf6cd9436, (const unsigned char *)"85181542907229116674", 20, 0x132256a1}, - {__LINE__, 0x9109e6c3, (const unsigned char *)"87963594337989416799", 20, 0xbfdb2c83}, - {__LINE__, 0x75770fc, (const unsigned char *)"21395988329504168551", 20, 0x8d9d1e81}, - {__LINE__, 0x69b1d19b, (const unsigned char *)"51991013580943379423", 20, 0x7b6d4404}, - {__LINE__, 0xc6132975, (const unsigned char *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x8619f010}, - {__LINE__, 0xd58cb00c, (const unsigned char *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0x15746ac3}, - {__LINE__, 0xb63b8caa, (const unsigned char *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0xaccf812f}, - {__LINE__, 0x8a45a2b8, (const unsigned char *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x78af45de}, - {__LINE__, 0xcbe95b78, (const unsigned char *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x25b06b59}, - {__LINE__, 0x4ef8a54b, (const unsigned char *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x4ba0d08f}, - {__LINE__, 0x76ad267a, (const unsigned char *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0xe26b6aac}, - {__LINE__, 0x569e613c, (const unsigned char *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x7e2b0a66}, - {__LINE__, 0x36aa61da, (const unsigned char *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xb3430dc7}, - {__LINE__, 0xf67222df, (const unsigned char *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x626c17a}, - {__LINE__, 0x74b34fd3, (const unsigned char *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0xccf98060}, - {__LINE__, 0x351fd770, (const unsigned char *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xd8b95312}, - {__LINE__, 0xc45aef77, (const unsigned char *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xbb1c9912}, - {__LINE__, 0xc45aef77, (const unsigned char *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" - "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" - "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" - "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" - "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" - "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 600, 0x888AFA5B} -}; - -static const int test_size = sizeof(tests) / sizeof(tests[0]); - -int main(void) { - int i; - for (i = 0; i < test_size; i++) { - test_crc32(tests[i].crc, tests[i].buf, tests[i].len, tests[i].expect, tests[i].line); - } - return 0; -} diff --git a/test/test_crc32.cc b/test/test_crc32.cc new file mode 100644 index 0000000000..af0dd3b784 --- /dev/null +++ b/test/test_crc32.cc @@ -0,0 +1,219 @@ +/* test_crc32.cc -- crc32 unit test + * Copyright (C) 2019-2021 IBM Corporation + * Authors: Rogerio Alves + * Matheus Castanho + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include + +extern "C" { +# include "zbuild.h" +# include "zutil_p.h" +# include "cpu_features.h" +} + +#include + +typedef struct { + unsigned long crc; + const uint8_t *buf; + size_t len; + unsigned long expect; +} crc32_test; + +static const crc32_test tests[] = { + {0x0, (const uint8_t *)0x0, 0, 0x0}, + {0xffffffff, (const uint8_t *)0x0, 0, 0x0}, + {0x0, (const uint8_t *)0x0, 255, 0x0}, /* BZ 174799. */ + {0x0, (const uint8_t *)0x0, 256, 0x0}, + {0x0, (const uint8_t *)0x0, 257, 0x0}, + {0x0, (const uint8_t *)0x0, 32767, 0x0}, + {0x0, (const uint8_t *)0x0, 32768, 0x0}, + {0x0, (const uint8_t *)0x0, 32769, 0x0}, + {0x0, (const uint8_t *)"", 0, 0x0}, + {0xffffffff, (const uint8_t *)"", 0, 0xffffffff}, + {0x0, (const uint8_t *)"abacus", 6, 0xc3d7115b}, + {0x0, (const uint8_t *)"backlog", 7, 0x269205}, + {0x0, (const uint8_t *)"campfire", 8, 0x22a515f8}, + {0x0, (const uint8_t *)"delta", 5, 0x9643fed9}, + {0x0, (const uint8_t *)"executable", 10, 0xd68eda01}, + {0x0, (const uint8_t *)"file", 4, 0x8c9f3610}, + {0x0, (const uint8_t *)"greatest", 8, 0xc1abd6cd}, + {0x0, (const uint8_t *)"hello", 5, 0x3610a686}, + {0x0, (const uint8_t *)"inverter", 8, 0xc9e962c9}, + {0x0, (const uint8_t *)"jigsaw", 6, 0xce4e3f69}, + {0x0, (const uint8_t *)"karate", 6, 0x890be0e2}, + {0x0, (const uint8_t *)"landscape", 9, 0xc4e0330b}, + {0x0, (const uint8_t *)"machine", 7, 0x1505df84}, + {0x0, (const uint8_t *)"nanometer", 9, 0xd4e19f39}, + {0x0, (const uint8_t *)"oblivion", 8, 0xdae9de77}, + {0x0, (const uint8_t *)"panama", 6, 0x66b8979c}, + {0x0, (const uint8_t *)"quest", 5, 0x4317f817}, + {0x0, (const uint8_t *)"resource", 8, 0xbc91f416}, + {0x0, (const uint8_t *)"secret", 6, 0x5ca2e8e5}, + {0x0, (const uint8_t *)"test", 4, 0xd87f7e0c}, + {0x0, (const uint8_t *)"ultimate", 8, 0x3fc79b0b}, + {0x0, (const uint8_t *)"vector", 6, 0x1b6e485b}, + {0x0, (const uint8_t *)"walrus", 6, 0xbe769b97}, + {0x0, (const uint8_t *)"xeno", 4, 0xe7a06444}, + {0x0, (const uint8_t *)"yelling", 7, 0xfe3944e5}, + {0x0, (const uint8_t *)"zlib", 4, 0x73887d3a}, + {0x0, (const uint8_t *)"4BJD7PocN1VqX0jXVpWB", 20, 0xd487a5a1}, + {0x0, (const uint8_t *)"F1rPWI7XvDs6nAIRx41l", 20, 0x61a0132e}, + {0x0, (const uint8_t *)"ldhKlsVkPFOveXgkGtC2", 20, 0xdf02f76}, + {0x0, (const uint8_t *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x579b2b0a}, + {0x0, (const uint8_t *)"0l1tw7GOcem06Ddu7yn4", 20, 0xf7d16e2d}, + {0x0, (const uint8_t *)"MCr47CjPIn9R1IvE1Tm5", 20, 0x731788f5}, + {0x0, (const uint8_t *)"UcixbzPKTIv0SvILHVdO", 20, 0x7112bb11}, + {0x0, (const uint8_t *)"dGnAyAhRQDsWw0ESou24", 20, 0xf32a0dac}, + {0x0, (const uint8_t *)"di0nvmY9UYMYDh0r45XT", 20, 0x625437bb}, + {0x0, (const uint8_t *)"2XKDwHfAhFsV0RhbqtvH", 20, 0x896930f9}, + {0x0, (const uint8_t *)"ZhrANFIiIvRnqClIVyeD", 20, 0x8579a37}, + {0x0, (const uint8_t *)"v7Q9ehzioTOVeDIZioT1", 20, 0x632aa8e0}, + {0x0, (const uint8_t *)"Yod5hEeKcYqyhfXbhxj2", 20, 0xc829af29}, + {0x0, (const uint8_t *)"GehSWY2ay4uUKhehXYb0", 20, 0x1b08b7e8}, + {0x0, (const uint8_t *)"kwytJmq6UqpflV8Y8GoE", 20, 0x4e33b192}, + {0x0, (const uint8_t *)"70684206568419061514", 20, 0x59a179f0}, + {0x0, (const uint8_t *)"42015093765128581010", 20, 0xcd1013d7}, + {0x0, (const uint8_t *)"88214814356148806939", 20, 0xab927546}, + {0x0, (const uint8_t *)"43472694284527343838", 20, 0x11f3b20c}, + {0x0, (const uint8_t *)"49769333513942933689", 20, 0xd562d4ca}, + {0x0, (const uint8_t *)"54979784887993251199", 20, 0x233395f7}, + {0x0, (const uint8_t *)"58360544869206793220", 20, 0x2d167fd5}, + {0x0, (const uint8_t *)"27347953487840714234", 20, 0x8b5108ba}, + {0x0, (const uint8_t *)"07650690295365319082", 20, 0xc46b3cd8}, + {0x0, (const uint8_t *)"42655507906821911703", 20, 0xc10b2662}, + {0x0, (const uint8_t *)"29977409200786225655", 20, 0xc9a0f9d2}, + {0x0, (const uint8_t *)"85181542907229116674", 20, 0x9341357b}, + {0x0, (const uint8_t *)"87963594337989416799", 20, 0xf0424937}, + {0x0, (const uint8_t *)"21395988329504168551", 20, 0xd7c4c31f}, + {0x0, (const uint8_t *)"51991013580943379423", 20, 0xf11edcc4}, + {0x0, (const uint8_t *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x40795df4}, + {0x0, (const uint8_t *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0xdd61a631}, + {0x0, (const uint8_t *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0xca907a99}, + {0x0, (const uint8_t *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0xf652deac}, + {0x0, (const uint8_t *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0xaf39a5a9}, + {0x0, (const uint8_t *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x6bebb4cf}, + {0x0, (const uint8_t *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0x76430bac}, + {0x0, (const uint8_t *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x6c80c388}, + {0x0, (const uint8_t *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xd54d977d}, + {0x0, (const uint8_t *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0xe3966ad5}, + {0x0, (const uint8_t *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0xe7c71db9}, + {0x0, (const uint8_t *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xeaa52777}, + {0x0, (const uint8_t *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xcd472048}, + {0x7a30360d, (const uint8_t *)"abacus", 6, 0xf8655a84}, + {0x6fd767ee, (const uint8_t *)"backlog", 7, 0x1ed834b1}, + {0xefeb7589, (const uint8_t *)"campfire", 8, 0x686cfca}, + {0x61cf7e6b, (const uint8_t *)"delta", 5, 0x1554e4b1}, + {0xdc712e2, (const uint8_t *)"executable", 10, 0x761b4254}, + {0xad23c7fd, (const uint8_t *)"file", 4, 0x7abdd09b}, + {0x85cb2317, (const uint8_t *)"greatest", 8, 0x4ba91c6b}, + {0x9eed31b0, (const uint8_t *)"inverter", 8, 0xd5e78ba5}, + {0xb94f34ca, (const uint8_t *)"jigsaw", 6, 0x23649109}, + {0xab058a2, (const uint8_t *)"karate", 6, 0xc5591f41}, + {0x5bff2b7a, (const uint8_t *)"landscape", 9, 0xf10eb644}, + {0x605c9a5f, (const uint8_t *)"machine", 7, 0xbaa0a636}, + {0x51bdeea5, (const uint8_t *)"nanometer", 9, 0x6af89afb}, + {0x85c21c79, (const uint8_t *)"oblivion", 8, 0xecae222b}, + {0x97216f56, (const uint8_t *)"panama", 6, 0x47dffac4}, + {0x18444af2, (const uint8_t *)"quest", 5, 0x70c2fe36}, + {0xbe6ce359, (const uint8_t *)"resource", 8, 0x1471d925}, + {0x843071f1, (const uint8_t *)"secret", 6, 0x50c9a0db}, + {0xf2480c60, (const uint8_t *)"ultimate", 8, 0xf973daf8}, + {0x2d2feb3d, (const uint8_t *)"vector", 6, 0x344ac03d}, + {0x7490310a, (const uint8_t *)"walrus", 6, 0x6d1408ef}, + {0x97d247d4, (const uint8_t *)"xeno", 4, 0xe62670b5}, + {0x93cf7599, (const uint8_t *)"yelling", 7, 0x1b36da38}, + {0x73c84278, (const uint8_t *)"zlib", 4, 0x6432d127}, + {0x228a87d1, (const uint8_t *)"4BJD7PocN1VqX0jXVpWB", 20, 0x997107d0}, + {0xa7a048d0, (const uint8_t *)"F1rPWI7XvDs6nAIRx41l", 20, 0xdc567274}, + {0x1f0ded40, (const uint8_t *)"ldhKlsVkPFOveXgkGtC2", 20, 0xdcc63870}, + {0xa804a62f, (const uint8_t *)"5KKnGOOrs8BvJ35iKTOS", 20, 0x6926cffd}, + {0x508fae6a, (const uint8_t *)"0l1tw7GOcem06Ddu7yn4", 20, 0xb52b38bc}, + {0xe5adaf4f, (const uint8_t *)"MCr47CjPIn9R1IvE1Tm5", 20, 0xf83b8178}, + {0x67136a40, (const uint8_t *)"UcixbzPKTIv0SvILHVdO", 20, 0xc5213070}, + {0xb00c4a10, (const uint8_t *)"dGnAyAhRQDsWw0ESou24", 20, 0xbc7648b0}, + {0x2e0c84b5, (const uint8_t *)"di0nvmY9UYMYDh0r45XT", 20, 0xd8123a72}, + {0x81238d44, (const uint8_t *)"2XKDwHfAhFsV0RhbqtvH", 20, 0xd5ac5620}, + {0xf853aa92, (const uint8_t *)"ZhrANFIiIvRnqClIVyeD", 20, 0xceae099d}, + {0x5a692325, (const uint8_t *)"v7Q9ehzioTOVeDIZioT1", 20, 0xb07d2b24}, + {0x3275b9f, (const uint8_t *)"Yod5hEeKcYqyhfXbhxj2", 20, 0x24ce91df}, + {0x38371feb, (const uint8_t *)"GehSWY2ay4uUKhehXYb0", 20, 0x707b3b30}, + {0xafc8bf62, (const uint8_t *)"kwytJmq6UqpflV8Y8GoE", 20, 0x16abc6a9}, + {0x9b07db73, (const uint8_t *)"70684206568419061514", 20, 0xae1fb7b7}, + {0xe75b214, (const uint8_t *)"42015093765128581010", 20, 0xd4eecd2d}, + {0x72d0fe6f, (const uint8_t *)"88214814356148806939", 20, 0x4660ec7}, + {0xf857a4b1, (const uint8_t *)"43472694284527343838", 20, 0xfd8afdf7}, + {0x54b8e14, (const uint8_t *)"49769333513942933689", 20, 0xc6d1b5f2}, + {0xd6aa5616, (const uint8_t *)"54979784887993251199", 20, 0x32476461}, + {0x11e63098, (const uint8_t *)"58360544869206793220", 20, 0xd917cf1a}, + {0xbe92385, (const uint8_t *)"27347953487840714234", 20, 0x4ad14a12}, + {0x49511de0, (const uint8_t *)"07650690295365319082", 20, 0xe37b5c6c}, + {0x3db13bc1, (const uint8_t *)"42655507906821911703", 20, 0x7cc497f1}, + {0xbb899bea, (const uint8_t *)"29977409200786225655", 20, 0x99781bb2}, + {0xf6cd9436, (const uint8_t *)"85181542907229116674", 20, 0x132256a1}, + {0x9109e6c3, (const uint8_t *)"87963594337989416799", 20, 0xbfdb2c83}, + {0x75770fc, (const uint8_t *)"21395988329504168551", 20, 0x8d9d1e81}, + {0x69b1d19b, (const uint8_t *)"51991013580943379423", 20, 0x7b6d4404}, + {0xc6132975, (const uint8_t *)"*]+@!);({_$;}[_},?{?;(_?,=-][@", 30, 0x8619f010}, + {0xd58cb00c, (const uint8_t *)"_@:_).&(#.[:[{[:)$++-($_;@[)}+", 30, 0x15746ac3}, + {0xb63b8caa, (const uint8_t *)"&[!,[$_==}+.]@!;*(+},[;:)$;)-@", 30, 0xaccf812f}, + {0x8a45a2b8, (const uint8_t *)"]{.[.+?+[[=;[?}_#&;[=)__$$:+=_", 30, 0x78af45de}, + {0xcbe95b78, (const uint8_t *)"-%.)=/[@].:.(:,()$;=%@-$?]{%+%", 30, 0x25b06b59}, + {0x4ef8a54b, (const uint8_t *)"+]#$(@&.=:,*];/.!]%/{:){:@(;)$", 30, 0x4ba0d08f}, + {0x76ad267a, (const uint8_t *)")-._.:?[&:.=+}(*$/=!.${;(=$@!}", 30, 0xe26b6aac}, + {0x569e613c, (const uint8_t *)":(_*&%/[[}+,?#$&*+#[([*-/#;%(]", 30, 0x7e2b0a66}, + {0x36aa61da, (const uint8_t *)"{[#-;:$/{)(+[}#]/{&!%(@)%:@-$:", 30, 0xb3430dc7}, + {0xf67222df, (const uint8_t *)"_{$*,}(&,@.)):=!/%(&(,,-?$}}}!", 30, 0x626c17a}, + {0x74b34fd3, (const uint8_t *)"e$98KNzqaV)Y:2X?]77].{gKRD4G5{mHZk,Z)SpU%L3FSgv!Wb8MLAFdi{+fp)c,@8m6v)yXg@]HBDFk?.4&}g5_udE*JHCiH=aL", 100, 0xccf98060}, + {0x351fd770, (const uint8_t *)"r*Fd}ef+5RJQ;+W=4jTR9)R*p!B;]Ed7tkrLi;88U7g@3v!5pk2X6D)vt,.@N8c]@yyEcKi[vwUu@.Ppm@C6%Mv*3Nw}Y,58_aH)", 100, 0xd8b95312}, + {0xc45aef77, (const uint8_t *)"h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 100, 0xbb1c9912}, + {0xc45aef77, (const uint8_t *) + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&" + "h{bcmdC+a;t+Cf{6Y_dFq-{X4Yu&7uNfVDh?q&_u.UWJU],-GiH7ADzb7-V.Q%4=+v!$L9W+T=bP]$_:]Vyg}A.ygD.r;h-D]m%&", 600, 0x888AFA5B} +}; + +class crc32_variant : public ::testing::TestWithParam { +public: + void hash(crc32_test param, crc32_func crc32) { + uint32_t crc = 0; + if (param.buf != NULL) { + if (param.len) { + crc = crc32(param.crc, param.buf, param.len); + } else { + crc = param.crc; + } + } + EXPECT_EQ(crc, param.expect); + } +}; + +INSTANTIATE_TEST_SUITE_P(crc32, crc32_variant, testing::ValuesIn(tests)); + +#define TEST_CRC32(name, func, support_flag) \ + TEST_P(crc32_variant, name) { \ + if (!support_flag) { \ + GTEST_SKIP(); \ + return; \ + } \ + hash(GetParam(), func); \ + } + +TEST_CRC32(byfour, crc32_byfour, 1) + +#ifdef ARM_ACLE_CRC_HASH +TEST_CRC32(acle, crc32_acle, arm_cpu_has_crc32) +#elif defined(POWER8_VSX_CRC32) +TEST_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07) +#elif defined(S390_CRC32_VX) +TEST_CRC32(vx, s390_crc32_vx, s390_cpu_has_vx) +#elif defined(X86_PCLMULQDQ_CRC) +TEST_CRC32(pclmulqdq, crc32_pclmulqdq, x86_cpu_has_pclmulqdq) +#endif diff --git a/test/test_deflate_bound.cc b/test/test_deflate_bound.cc new file mode 100644 index 0000000000..d6f576a824 --- /dev/null +++ b/test/test_deflate_bound.cc @@ -0,0 +1,53 @@ +/* test_deflate_bound.cc - Test deflateBound() with small buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(deflate, bound) { + PREFIX3(stream) c_stream; + int estimate_len = 0; + uint8_t *out_buf = NULL; + int err; + + memset(&c_stream, 0, sizeof(c_stream)); + + c_stream.avail_in = hello_len; + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.avail_out = 0; + c_stream.next_out = out_buf; + + err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + /* calculate actual output length and update structure */ + estimate_len = PREFIX(deflateBound)(&c_stream, hello_len); + out_buf = (uint8_t *)malloc(estimate_len); + + if (out_buf != NULL) { + /* update zlib configuration */ + c_stream.avail_out = estimate_len; + c_stream.next_out = out_buf; + + /* do the compression */ + err = PREFIX(deflate)(&c_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + } + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + free(out_buf); +} diff --git a/test/test_deflate_copy.cc b/test/test_deflate_copy.cc new file mode 100644 index 0000000000..4adc9be967 --- /dev/null +++ b/test/test_deflate_copy.cc @@ -0,0 +1,60 @@ +/* test_deflate_copy.cc - Test deflateCopy() with small buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "deflate.h" + +#include "test_shared.h" + +#include + +TEST(deflate, copy) { + PREFIX3(stream) c_stream, c_stream_copy; + uint8_t compr[128]; + z_size_t compr_len = sizeof(compr); + int err; + + memset(&c_stream, 0, sizeof(c_stream)); + memset(&c_stream_copy, 0, sizeof(c_stream_copy)); + + err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != hello_len && c_stream.total_out < compr_len) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + } + + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = PREFIX(deflate)(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(deflateCopy)(&c_stream_copy, &c_stream); + EXPECT_EQ(err, Z_OK); + + EXPECT_EQ(c_stream.state->status, c_stream_copy.state->status); + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(deflateEnd)(&c_stream_copy); + EXPECT_EQ(err, Z_OK); +} diff --git a/test/test_deflate_dict.cc b/test/test_deflate_dict.cc new file mode 100644 index 0000000000..7a060a8dea --- /dev/null +++ b/test/test_deflate_dict.cc @@ -0,0 +1,54 @@ +/* test_deflate_dict.cc - Test deflateGetDictionary() with small buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(deflate, dictionary) { + PREFIX3(stream) c_stream; + uint8_t compr[128]; + uint32_t compr_len = sizeof(compr); + uint8_t *dict_new = NULL; + uint32_t *dict_len; + int err; + + memset(&c_stream, 0, sizeof(c_stream)); + + err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + c_stream.next_out = compr; + c_stream.avail_out = compr_len; + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.avail_in = (uint32_t)hello_len; + + err = PREFIX(deflate)(&c_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + + dict_new = (uint8_t *)calloc(256, 1); + ASSERT_TRUE(dict_new != NULL); + dict_len = (uint32_t *)calloc(4, 1); + ASSERT_TRUE(dict_len != NULL); + + err = PREFIX(deflateGetDictionary)(&c_stream, dict_new, dict_len); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + free(dict_new); + free(dict_len); +} diff --git a/test/test_deflate_hash_head_0.cc b/test/test_deflate_hash_head_0.cc new file mode 100644 index 0000000000..4a4e4b64ab --- /dev/null +++ b/test/test_deflate_hash_head_0.cc @@ -0,0 +1,83 @@ +/* Generated by fuzzing - test hash_head == 0 handling. */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(deflate, hash_head_0) { + PREFIX3(stream) strm; + int err; + + memset(&strm, 0, sizeof(strm)); + err = PREFIX(deflateInit2)(&strm, 1, Z_DEFLATED, -15, 4, Z_HUFFMAN_ONLY); + EXPECT_EQ(err, Z_OK); + + unsigned char next_in[9698]; + memset(next_in, 0x30, sizeof(next_in)); + next_in[8193] = 0x00; + next_in[8194] = 0x00; + next_in[8195] = 0x00; + next_in[8199] = 0x8a; + strm.next_in = next_in; + unsigned char next_out[21572]; + strm.next_out = next_out; + + strm.avail_in = 0; + strm.avail_out = 1348; + err = PREFIX(deflateParams(&strm, 3, Z_FILTERED)); + EXPECT_EQ(err, Z_OK); + + strm.avail_in = 6728; + strm.avail_out = 2696; + err = PREFIX(deflate(&strm, Z_SYNC_FLUSH)); + EXPECT_EQ(err, Z_OK); + + strm.avail_in = 15; + strm.avail_out = 1348; + err = PREFIX(deflateParams(&strm, 9, Z_FILTERED)); + EXPECT_EQ(err, Z_OK); + + strm.avail_in = 1453; + strm.avail_out = 1348; + err = PREFIX(deflate(&strm, Z_FULL_FLUSH)); + EXPECT_EQ(err, Z_OK); + + strm.avail_in = (uint32_t)(next_in + sizeof(next_in) - strm.next_in); + strm.avail_out = (uint32_t)(next_out + sizeof(next_out) - strm.next_out); + err = PREFIX(deflate)(&strm, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + + uint32_t compressed_size = (uint32_t)(strm.next_out - next_out); + + err = PREFIX(deflateEnd)(&strm); + EXPECT_EQ(err, Z_OK); + + memset(&strm, 0, sizeof(strm)); + err = PREFIX(inflateInit2)(&strm, -15); + EXPECT_EQ(err, Z_OK); + + strm.next_in = next_out; + strm.avail_in = compressed_size; + unsigned char uncompressed[sizeof(next_in)]; + strm.next_out = uncompressed; + strm.avail_out = sizeof(uncompressed); + + err = PREFIX(inflate)(&strm, Z_NO_FLUSH); + EXPECT_EQ(err, Z_STREAM_END); + + err = PREFIX(inflateEnd)(&strm); + EXPECT_EQ(err, Z_OK); + + EXPECT_TRUE(memcmp(uncompressed, next_in, sizeof(uncompressed)) == 0); +} diff --git a/test/test_deflate_header.cc b/test/test_deflate_header.cc new file mode 100644 index 0000000000..92f4612089 --- /dev/null +++ b/test/test_deflate_header.cc @@ -0,0 +1,68 @@ +/* test_deflate_header.cc - Test deflateSetHeader() with small buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(deflate, header) { + PREFIX3(stream) c_stream; + PREFIX(gz_header) *head; + uint8_t compr[128]; + z_size_t compr_len = sizeof(compr); + int err; + + head = (PREFIX(gz_header) *)calloc(1, sizeof(PREFIX(gz_header))); + ASSERT_TRUE(head != NULL); + + memset(&c_stream, 0, sizeof(c_stream)); + + /* gzip */ + err = PREFIX(deflateInit2)(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY); + EXPECT_EQ(err, Z_OK); + + head->text = 1; + head->comment = (uint8_t *)"comment"; + head->name = (uint8_t *)"name"; + head->hcrc = 1; + head->extra = (uint8_t *)"extra"; + head->extra_len = (uint32_t)strlen((const char *)head->extra); + + err = PREFIX(deflateSetHeader)(&c_stream, head); + EXPECT_EQ(err, Z_OK); + + PREFIX(deflateBound)(&c_stream, (unsigned long)compr_len); + + c_stream.next_in = (unsigned char *)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != hello_len && c_stream.total_out < compr_len) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + } + + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = PREFIX(deflate)(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + free(head); +} diff --git a/test/test_deflate_params.cc b/test/test_deflate_params.cc new file mode 100644 index 0000000000..f5f5066ad1 --- /dev/null +++ b/test/test_deflate_params.cc @@ -0,0 +1,143 @@ +/* test_deflate_params.cc - Test deflate() with dynamic change of compression level */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "deflate.h" + +#include "test_shared.h" + +#include + +#define COMPR_BUFFER_SIZE (48 * 1024) +#define UNCOMPR_BUFFER_SIZE (64 * 1024) +#define UNCOMPR_RAND_SIZE (8 * 1024) + +TEST(deflate, params) { + PREFIX3(stream) c_stream, d_stream; + uint8_t *compr, *uncompr; + uint32_t compr_len, uncompr_len; + uint32_t diff; + int32_t i; + time_t now; + int err; +#ifndef ZLIB_COMPAT + int level = -1; + int strategy = -1; + zng_deflate_param_value params[2]; + + params[0].param = Z_DEFLATE_LEVEL; + params[0].buf = &level; + params[0].size = sizeof(level); + + params[1].param = Z_DEFLATE_STRATEGY; + params[1].buf = &strategy; + params[1].size = sizeof(strategy); +#endif + + memset(&c_stream, 0, sizeof(c_stream)); + memset(&d_stream, 0, sizeof(d_stream)); + + compr = (uint8_t *)calloc(1, COMPR_BUFFER_SIZE); + ASSERT_TRUE(compr != NULL); + uncompr = (uint8_t *)calloc(1, UNCOMPR_BUFFER_SIZE); + ASSERT_TRUE(uncompr != NULL); + + compr_len = COMPR_BUFFER_SIZE; + uncompr_len = UNCOMPR_BUFFER_SIZE; + + srand((unsigned)time(&now)); + for (i = 0; i < UNCOMPR_RAND_SIZE; i++) + uncompr[i] = (uint8_t)(rand() % 256); + + err = PREFIX(deflateInit)(&c_stream, Z_BEST_SPEED); + EXPECT_EQ(err, Z_OK); + + c_stream.next_out = compr; + c_stream.avail_out = compr_len; + c_stream.next_in = uncompr; + c_stream.avail_in = uncompr_len; + + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + EXPECT_EQ(c_stream.avail_in, 0); + + /* Feed in already compressed data and switch to no compression: */ +#ifndef ZLIB_COMPAT + zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); + EXPECT_EQ(level, Z_BEST_SPEED); + EXPECT_EQ(strategy, Z_DEFAULT_STRATEGY); + + level = Z_NO_COMPRESSION; + strategy = Z_DEFAULT_STRATEGY; + zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); +#else + PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); +#endif + + c_stream.next_in = compr; + diff = (unsigned int)(c_stream.next_out - compr); + c_stream.avail_in = diff; + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + + /* Switch back to compressing mode: */ +#ifndef ZLIB_COMPAT + level = -1; + strategy = -1; + zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); + EXPECT_EQ(level, Z_NO_COMPRESSION); + EXPECT_EQ(strategy, Z_DEFAULT_STRATEGY); + + level = Z_BEST_COMPRESSION; + strategy = Z_FILTERED; + zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0])); +#else + PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); +#endif + + c_stream.next_in = uncompr; + c_stream.avail_in = (unsigned int)uncompr_len; + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(deflate)(&c_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + d_stream.next_in = compr; + d_stream.avail_in = (unsigned int)compr_len; + + err = PREFIX(inflateInit)(&d_stream); + EXPECT_EQ(err, Z_OK); + + do { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = uncompr_len; + err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) + break; + EXPECT_EQ(err, Z_OK); + } while (err == Z_OK); + + err = PREFIX(inflateEnd)(&d_stream); + EXPECT_EQ(err, Z_OK); + + EXPECT_EQ(d_stream.total_out, (2 * uncompr_len) + diff); + + free(compr); + free(uncompr); +} diff --git a/test/test_deflate_pending.cc b/test/test_deflate_pending.cc new file mode 100644 index 0000000000..b107dd43c1 --- /dev/null +++ b/test/test_deflate_pending.cc @@ -0,0 +1,66 @@ +/* test_deflate_pending.cc - Test deflatePending() with small buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(deflate, pending) { + PREFIX3(stream) c_stream; + uint8_t compr[128]; + z_size_t compr_len = sizeof(compr); + int *bits; + unsigned *ped; + int err; + + + bits = (int *)calloc(256, 1); + ASSERT_TRUE(bits != NULL); + ped = (unsigned *)calloc(256, 1); + ASSERT_TRUE(ped != NULL); + + memset(&c_stream, 0, sizeof(c_stream)); + + err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != hello_len && c_stream.total_out < compr_len) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(deflatePending)(&c_stream, ped, bits); + EXPECT_EQ(err, Z_OK); + + EXPECT_GE(*bits, 0); + EXPECT_LE(*bits, 7); + + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = PREFIX(deflate)(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + free(bits); + free(ped); +} diff --git a/test/test_deflate_prime.cc b/test/test_deflate_prime.cc new file mode 100644 index 0000000000..135a2d435f --- /dev/null +++ b/test/test_deflate_prime.cc @@ -0,0 +1,91 @@ +/* test_deflate_prime.cc - Test deflatePrime() wrapping gzip around deflate stream */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(deflate, prime) { + PREFIX3(stream) c_stream, d_stream; + uint8_t compr[128], uncompr[128]; + z_size_t compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); + uint32_t crc = 0; + int err; + + memset(&c_stream, 0, sizeof(c_stream)); + memset(&d_stream, 0, sizeof(d_stream)); + + /* Raw deflate windowBits is -15 */ + err = PREFIX(deflateInit2)(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY); + EXPECT_EQ(err, Z_OK); + + /* Gzip magic number */ + err = PREFIX(deflatePrime)(&c_stream, 16, 0x8b1f); + EXPECT_EQ(err, Z_OK); + /* Gzip compression method (deflate) */ + err = PREFIX(deflatePrime)(&c_stream, 8, 0x08); + EXPECT_EQ(err, Z_OK); + /* Gzip flags (one byte, using two odd bit calls) */ + err = PREFIX(deflatePrime)(&c_stream, 3, 0x0); + EXPECT_EQ(err, Z_OK); + err = PREFIX(deflatePrime)(&c_stream, 5, 0x0); + EXPECT_EQ(err, Z_OK); + /* Gzip modified time */ + err = PREFIX(deflatePrime)(&c_stream, 32, 0x0); + EXPECT_EQ(err, Z_OK); + /* Gzip extra flags */ + err = PREFIX(deflatePrime)(&c_stream, 8, 0x0); + EXPECT_EQ(err, Z_OK); + /* Gzip operating system */ + err = PREFIX(deflatePrime)(&c_stream, 8, 255); + EXPECT_EQ(err, Z_OK); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.avail_in = (uint32_t)hello_len; + c_stream.next_out = compr; + c_stream.avail_out = (uint32_t)compr_len; + + err = PREFIX(deflate)(&c_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + + /* Gzip uncompressed data crc32 */ + crc = PREFIX(crc32)(0, (const uint8_t *)hello, (uint32_t)hello_len); + err = PREFIX(deflatePrime)(&c_stream, 32, crc); + EXPECT_EQ(err, Z_OK); + /* Gzip uncompressed data length */ + err = PREFIX(deflatePrime)(&c_stream, 32, (uint32_t)hello_len); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + d_stream.next_in = compr; + d_stream.avail_in = (uint32_t)c_stream.total_out; + d_stream.next_out = uncompr; + d_stream.avail_out = (uint32_t)uncompr_len; + d_stream.total_in = 0; + d_stream.total_out = 0; + + /* Inflate with gzip header */ + err = PREFIX(inflateInit2)(&d_stream, MAX_WBITS + 32); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(inflate)(&d_stream, Z_FINISH); + EXPECT_EQ(err, Z_BUF_ERROR); + + err = PREFIX(inflateEnd)(&d_stream); + EXPECT_EQ(err, Z_OK); + + EXPECT_STREQ((char *)uncompr, hello); +} diff --git a/test/test_deflate_quick_bi_valid.c b/test/test_deflate_quick_bi_valid.cc similarity index 84% rename from test/test_deflate_quick_bi_valid.c rename to test/test_deflate_quick_bi_valid.cc index 0a60081f4e..8ce4c229db 100644 --- a/test/test_deflate_quick_bi_valid.c +++ b/test/test_deflate_quick_bi_valid.cc @@ -11,15 +11,18 @@ #include #include -int main() { +#include "test_shared.h" + +#include + +TEST(deflate_quick, bi_valid) { PREFIX3(stream) strm; + int err; + memset(&strm, 0, sizeof(strm)); - int ret = PREFIX(deflateInit2)(&strm, 1, Z_DEFLATED, 31, 1, Z_FILTERED); - if (ret != Z_OK) { - fprintf(stderr, "deflateInit2() failed with code %d\n", ret); - return EXIT_FAILURE; - } + err = PREFIX(deflateInit2)(&strm, 1, Z_DEFLATED, 31, 1, Z_FILTERED); + EXPECT_EQ(err, Z_OK); z_const unsigned char next_in[554] = { 0x8d, 0xff, 0xff, 0xff, 0xa2, 0x00, 0x00, 0xff, 0x00, 0x15, 0x1b, 0x1b, 0xa2, 0xa2, 0xaf, 0xa2, @@ -63,24 +66,15 @@ int main() { strm.avail_in = 554; strm.avail_out = 31; - ret = PREFIX(deflate)(&strm, Z_FINISH); - if (ret != Z_OK) { - fprintf(stderr, "deflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } + + err = PREFIX(deflate)(&strm, Z_FINISH); + EXPECT_EQ(err, Z_OK); strm.avail_in = 0; strm.avail_out = 498; - ret = PREFIX(deflate)(&strm, Z_FINISH); - if (ret != Z_STREAM_END) { - fprintf(stderr, "deflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } + err = PREFIX(deflate)(&strm, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); - ret = PREFIX(deflateEnd)(&strm); - if (ret != Z_OK) { - fprintf(stderr, "deflateEnd() failed with code %d\n", ret); - return EXIT_FAILURE; - } - return 0; + err = PREFIX(deflateEnd)(&strm); + EXPECT_EQ(err, Z_OK); } diff --git a/test/test_deflate_quick_block_open.c b/test/test_deflate_quick_block_open.cc similarity index 71% rename from test/test_deflate_quick_block_open.c rename to test/test_deflate_quick_block_open.cc index 9df9212000..b8703ae977 100644 --- a/test/test_deflate_quick_block_open.c +++ b/test/test_deflate_quick_block_open.cc @@ -11,17 +11,19 @@ #include #include -int main() { +#include "test_shared.h" + +#include + +TEST(deflate_quick, block_open) { PREFIX3(stream) strm; + int err; memset(&strm, 0, sizeof(strm)); - int ret = PREFIX(deflateInit2)(&strm, 1, Z_DEFLATED, -15, 1, Z_FILTERED); - if (ret != Z_OK) { - fprintf(stderr, "deflateInit2() failed with code %d\n", ret); - return EXIT_FAILURE; - } + err = PREFIX(deflateInit2)(&strm, 1, Z_DEFLATED, -15, 1, Z_FILTERED); + EXPECT_EQ(err, Z_OK); - z_const unsigned char next_in[494] = + z_const unsigned char next_in[495] = "\x1d\x1d\x00\x00\x00\x4a\x4a\x4a\xaf\xaf\xaf\xaf\x4a\x4a\x4a\x4a" "\x3f\x3e\xaf\xff\xff\xff\x11\xff\xff\xff\xff\xdf\x00\x00\x00\x01" "\x3f\x7d\x00\x50\x00\x00\xc8\x01\x2b\x60\xc8\x00\x24\x06\xff\xff" @@ -62,28 +64,19 @@ int main() { strm.avail_out = (uint32_t)(next_out + sizeof(next_out) - strm.next_out); if (strm.avail_out > 38) strm.avail_out = 38; - ret = PREFIX(deflate)(&strm, Z_FINISH); - if (ret == Z_STREAM_END) + err = PREFIX(deflate)(&strm, Z_FINISH); + if (err == Z_STREAM_END) break; - if (ret != Z_OK) { - fprintf(stderr, "deflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } + EXPECT_EQ(err, Z_OK); } uint32_t compressed_size = (uint32_t)(strm.next_out - next_out); - ret = PREFIX(deflateEnd)(&strm); - if (ret != Z_OK) { - fprintf(stderr, "deflateEnd() failed with code %d\n", ret); - return EXIT_FAILURE; - } + err = PREFIX(deflateEnd)(&strm); + EXPECT_EQ(err, Z_OK); memset(&strm, 0, sizeof(strm)); - ret = PREFIX(inflateInit2)(&strm, -15); - if (ret != Z_OK) { - fprintf(stderr, "inflateInit2() failed with code %d\n", ret); - return EXIT_FAILURE; - } + err = PREFIX(inflateInit2)(&strm, -15); + EXPECT_EQ(err, Z_OK); strm.next_in = next_out; strm.avail_in = compressed_size; @@ -91,21 +84,11 @@ int main() { strm.next_out = uncompressed; strm.avail_out = sizeof(uncompressed); - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); - if (ret != Z_STREAM_END) { - fprintf(stderr, "inflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } + err = PREFIX(inflate)(&strm, Z_NO_FLUSH); + EXPECT_EQ(err, Z_STREAM_END); - ret = PREFIX(inflateEnd)(&strm); - if (ret != Z_OK) { - fprintf(stderr, "inflateEnd() failed with code %d\n", ret); - return EXIT_FAILURE; - } + err = PREFIX(inflateEnd)(&strm); + EXPECT_EQ(err, Z_OK); - if (memcmp(uncompressed, next_in, sizeof(uncompressed)) != 0) { - fprintf(stderr, "Uncompressed data differs from the original\n"); - return EXIT_FAILURE; - } - return 0; + EXPECT_TRUE(memcmp(uncompressed, next_in, sizeof(uncompressed)) == 0); } diff --git a/test/test_deflate_tune.cc b/test/test_deflate_tune.cc new file mode 100644 index 0000000000..9921ee6437 --- /dev/null +++ b/test/test_deflate_tune.cc @@ -0,0 +1,56 @@ +/* test_deflate_tune.cc - Test deflateTune() with small buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(deflate, tune) { + PREFIX3(stream) c_stream; + uint8_t compr[128]; + z_size_t compr_len = sizeof(compr); + int err; + int good_length = 3; + int max_lazy = 5; + int nice_length = 18; + int max_chain = 6; + + memset(&c_stream, 0, sizeof(c_stream)); + + err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(deflateTune)(&c_stream, good_length, max_lazy,nice_length, max_chain); + EXPECT_EQ(err, Z_OK); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != hello_len && c_stream.total_out < compr_len) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + } + + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = PREFIX(deflate)(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); +} diff --git a/test/test_dict.cc b/test/test_dict.cc new file mode 100644 index 0000000000..223f0a6cb2 --- /dev/null +++ b/test/test_dict.cc @@ -0,0 +1,95 @@ +/* test_dict.cc - Test deflate() and inflate() with preset dictionary */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +/* Maximum dictionary size, according to inflateGetDictionary() description. */ +#define MAX_DICTIONARY_SIZE 32768 + +static const char dictionary[] = "hello"; + +TEST(dictionary, basic) { + PREFIX3(stream) c_stream, d_stream; + uint8_t compr[128], uncompr[128]; + z_size_t compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); + uint32_t dict_adler = 0; + uint8_t check_dict[MAX_DICTIONARY_SIZE]; + uint32_t check_dict_len = 0; + int err; + + memset(&c_stream, 0, sizeof(c_stream)); + memset(&d_stream, 0, sizeof(d_stream)); + + err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(deflateSetDictionary)(&c_stream, + (const unsigned char *)dictionary, (int)sizeof(dictionary)); + EXPECT_EQ(err, Z_OK); + + dict_adler = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uint32_t)compr_len; + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.avail_in = (uint32_t)hello_len; + + err = PREFIX(deflate)(&c_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + strcpy((char*)uncompr, "garbage garbage garbage"); + + d_stream.next_in = compr; + d_stream.avail_in = (unsigned int)compr_len; + + err = PREFIX(inflateInit)(&d_stream); + EXPECT_EQ(err, Z_OK); + + d_stream.next_out = uncompr; + d_stream.avail_out = (unsigned int)uncompr_len; + + for (;;) { + err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) + break; + if (err == Z_NEED_DICT) { + EXPECT_EQ(d_stream.adler, dict_adler); + err = PREFIX(inflateSetDictionary)(&d_stream, (const unsigned char*)dictionary, + (uint32_t)sizeof(dictionary)); + } + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(inflateGetDictionary)(&d_stream, NULL, &check_dict_len); + EXPECT_EQ(err, Z_OK); +#ifndef S390_DFLTCC_INFLATE + EXPECT_GE(check_dict_len, sizeof(dictionary)); +#endif + + err = PREFIX(inflateGetDictionary)(&d_stream, check_dict, &check_dict_len); + EXPECT_EQ(err, Z_OK); +#ifndef S390_DFLTCC_INFLATE + EXPECT_TRUE(memcmp(dictionary, check_dict, sizeof(dictionary)) == 0); +#endif + + err = PREFIX(inflateEnd)(&d_stream); + EXPECT_EQ(err, Z_OK); + + EXPECT_TRUE(strncmp((char*)uncompr, hello, sizeof(hello)) == 0); +} diff --git a/test/test_gzio.cc b/test/test_gzio.cc new file mode 100644 index 0000000000..46baa028eb --- /dev/null +++ b/test/test_gzio.cc @@ -0,0 +1,105 @@ +/* test_gzio.cc - Test read/write of .gz files */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +#define TESTFILE "foo.gz" + +TEST(gzip, readwrite) { +#ifdef NO_GZCOMPRESS + fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); + GTEST_SKIP(); +#else + uint8_t compr[128], uncompr[128]; + uint32_t compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); + size_t read; + int64_t pos; + gzFile file; + int err; + + /* Write gz file with test data */ + file = PREFIX(gzopen)(TESTFILE, "wb"); + ASSERT_TRUE(file != NULL); + /* Write hello, hello! using gzputs and gzprintf */ + PREFIX(gzputc)(file, 'h'); + EXPECT_EQ(PREFIX(gzputs)(file, "ello"), 4); + EXPECT_EQ(PREFIX(gzprintf)(file, ", %s!", "hello"), 8); + /* Write string null-teriminator using gzseek */ + EXPECT_GE(PREFIX(gzseek)(file, 1L, SEEK_CUR), 0); + /* Write hello, hello! using gzfwrite using best compression level */ + EXPECT_EQ(PREFIX(gzsetparams)(file, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY), Z_OK); + EXPECT_NE(PREFIX(gzfwrite)(hello, hello_len, 1, file), 0); + /* Flush compressed bytes to file */ + EXPECT_EQ(PREFIX(gzflush)(file, Z_SYNC_FLUSH), Z_OK); + compr_len = (uint32_t)PREFIX(gzoffset)(file); + EXPECT_GE(compr_len, 0UL); + PREFIX(gzclose)(file); + + /* Open gz file we previously wrote */ + file = PREFIX(gzopen)(TESTFILE, "rb"); + ASSERT_TRUE(file != NULL); + + /* Read uncompressed data - hello, hello! string twice */ + strcpy((char*)uncompr, "garbages"); + EXPECT_EQ(PREFIX(gzread)(file, uncompr, (unsigned)uncompr_len), (int)(hello_len + hello_len)); + EXPECT_STREQ((char*)uncompr, hello); + + /* Check position at the end of the gz file */ + EXPECT_EQ(PREFIX(gzeof)(file), 1); + + /* Seek backwards mid-string and check char reading with gzgetc and gzungetc */ + pos = PREFIX(gzseek)(file, -22L, SEEK_CUR); + EXPECT_EQ(pos, 6); + EXPECT_EQ(PREFIX(gztell)(file), pos); + EXPECT_EQ(PREFIX(gzgetc)(file), ' '); + EXPECT_EQ(PREFIX(gzungetc)(' ', file), ' '); + /* Read first hello, hello! string with gzgets */ + strcpy((char*)uncompr, "garbages"); + PREFIX(gzgets)(file, (char*)uncompr, (int)uncompr_len); + EXPECT_EQ(strlen((char*)uncompr), 7); /* " hello!" */ + EXPECT_STREQ((char*)uncompr, hello + 6); + + /* Seek to second hello, hello! string */ + pos = PREFIX(gzseek)(file, 14L, SEEK_SET); + EXPECT_EQ(pos, 14); + EXPECT_EQ(PREFIX(gztell)(file), pos); + + /* Check position not at end of file */ + EXPECT_EQ(PREFIX(gzeof)(file), 0); + /* Read first hello, hello! string with gzfread */ + strcpy((char*)uncompr, "garbages"); + read = PREFIX(gzfread)(uncompr, uncompr_len, 1, file); + EXPECT_STREQ((const char *)uncompr, hello); + + pos = PREFIX(gzoffset)(file); + EXPECT_GE(pos, 0); + EXPECT_EQ(pos, (compr_len + 10)); + + /* Trigger an error and clear it with gzclearerr */ + PREFIX(gzfread)(uncompr, (size_t)-1, (size_t)-1, file); + PREFIX(gzerror)(file, &err); + EXPECT_NE(err, 0); + + PREFIX(gzclearerr)(file); + PREFIX(gzerror)(file, &err); + EXPECT_EQ(err, 0); + + PREFIX(gzclose)(file); + + EXPECT_EQ(PREFIX(gzclose)(NULL), Z_STREAM_ERROR); + Z_UNUSED(read); +#endif +} diff --git a/test/test_hash_head_0.c b/test/test_hash_head_0.c deleted file mode 100644 index 1f615c5d67..0000000000 --- a/test/test_hash_head_0.c +++ /dev/null @@ -1,110 +0,0 @@ -/* Generated by fuzzing - test hash_head == 0 handling. */ - -#include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif - -#include -#include -#include - -int main() { - PREFIX3(stream) strm; - memset(&strm, 0, sizeof(strm)); - - int ret = PREFIX(deflateInit2)(&strm, 1, Z_DEFLATED, -15, 4, Z_HUFFMAN_ONLY); - if (ret != Z_OK) { - fprintf(stderr, "deflateInit2() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - unsigned char next_in[9698]; - memset(next_in, 0x30, sizeof(next_in)); - next_in[8193] = 0x00; - next_in[8194] = 0x00; - next_in[8195] = 0x00; - next_in[8199] = 0x8a; - strm.next_in = next_in; - unsigned char next_out[21572]; - strm.next_out = next_out; - - strm.avail_in = 0; - strm.avail_out = 1348; - ret = PREFIX(deflateParams(&strm, 3, Z_FILTERED)); - if (ret != Z_OK) { - fprintf(stderr, "deflateParams() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - strm.avail_in = 6728; - strm.avail_out = 2696; - ret = PREFIX(deflate(&strm, Z_SYNC_FLUSH)); - if (ret != Z_OK) { - fprintf(stderr, "deflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - strm.avail_in = 15; - strm.avail_out = 1348; - ret = PREFIX(deflateParams(&strm, 9, Z_FILTERED)); - if (ret != Z_OK) { - fprintf(stderr, "deflateParams() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - strm.avail_in = 1453; - strm.avail_out = 1348; - ret = PREFIX(deflate(&strm, Z_FULL_FLUSH)); - if (ret != Z_OK) { - fprintf(stderr, "deflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - strm.avail_in = (uint32_t)(next_in + sizeof(next_in) - strm.next_in); - strm.avail_out = (uint32_t)(next_out + sizeof(next_out) - strm.next_out); - ret = PREFIX(deflate)(&strm, Z_FINISH); - if (ret != Z_STREAM_END) { - fprintf(stderr, "deflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } - uint32_t compressed_size = (uint32_t)(strm.next_out - next_out); - - ret = PREFIX(deflateEnd)(&strm); - if (ret != Z_OK) { - fprintf(stderr, "deflateEnd() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - memset(&strm, 0, sizeof(strm)); - ret = PREFIX(inflateInit2)(&strm, -15); - if (ret != Z_OK) { - fprintf(stderr, "inflateInit2() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - strm.next_in = next_out; - strm.avail_in = compressed_size; - unsigned char uncompressed[sizeof(next_in)]; - strm.next_out = uncompressed; - strm.avail_out = sizeof(uncompressed); - - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); - if (ret != Z_STREAM_END) { - fprintf(stderr, "inflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - ret = PREFIX(inflateEnd)(&strm); - if (ret != Z_OK) { - fprintf(stderr, "inflateEnd() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - if (memcmp(uncompressed, next_in, sizeof(uncompressed)) != 0) { - fprintf(stderr, "Uncompressed data differs from the original\n"); - return EXIT_FAILURE; - } -} diff --git a/test/test_inflate_adler32.c b/test/test_inflate_adler32.cc similarity index 52% rename from test/test_inflate_adler32.c rename to test/test_inflate_adler32.cc index 3def08e42d..e17cf6b795 100644 --- a/test/test_inflate_adler32.c +++ b/test/test_inflate_adler32.cc @@ -11,49 +11,38 @@ #include #include +#include "test_shared.h" + +#include + const char* original = "The quick brown fox jumped over the lazy dog"; z_const unsigned char compressed[] = { - 0x78, 0x9c, 0x0b, 0xc9, 0x48, 0x55, 0x28, 0x2c, 0xcd, 0x4c, 0xce, 0x56, 0x48, - 0x2a, 0xca, 0x2f, 0xcf, 0x53, 0x48, 0xcb, 0xaf, 0x50, 0xc8, 0x2a, 0xcd, 0x2d, - 0x48, 0x4d, 0x51, 0xc8, 0x2f, 0x4b, 0x2d, 0x52, 0x28, 0xc9, 0x48, 0x55, 0xc8, + 0x78, 0x9c, 0x0b, 0xc9, 0x48, 0x55, 0x28, 0x2c, 0xcd, 0x4c, 0xce, 0x56, 0x48, + 0x2a, 0xca, 0x2f, 0xcf, 0x53, 0x48, 0xcb, 0xaf, 0x50, 0xc8, 0x2a, 0xcd, 0x2d, + 0x48, 0x4d, 0x51, 0xc8, 0x2f, 0x4b, 0x2d, 0x52, 0x28, 0xc9, 0x48, 0x55, 0xc8, 0x49, 0xac, 0xaa, 0x54, 0x48, 0xc9, 0x4f, 0x07, 0x00, 0x6b, 0x93, 0x10, 0x30 }; -int main() -{ +TEST(inflate, adler32) { unsigned char uncompressed[1024]; PREFIX3(stream) strm; memset(&strm, 0, sizeof(strm)); - int ret = PREFIX(inflateInit2)(&strm, 32 + MAX_WBITS); - if (ret != Z_OK) { - fprintf(stderr, "inflateInit2() failed with code %d\n", ret); - return EXIT_FAILURE; - } + int err = PREFIX(inflateInit2)(&strm, 32 + MAX_WBITS); + EXPECT_EQ(err, Z_OK); strm.next_in = compressed; strm.avail_in = sizeof(compressed); strm.next_out = uncompressed; strm.avail_out = sizeof(uncompressed); - ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); - if (ret != Z_STREAM_END) { - fprintf(stderr, "inflate() failed with code %d\n", ret); - return EXIT_FAILURE; - } - - ret = PREFIX(inflateEnd)(&strm); - if (ret != Z_OK) { - fprintf(stderr, "inflateEnd() failed with code %d\n", ret); - return EXIT_FAILURE; - } + err = PREFIX(inflate)(&strm, Z_NO_FLUSH); + EXPECT_EQ(err, Z_STREAM_END); - if (memcmp(uncompressed, original, MIN(strm.total_out, strlen(original))) != 0) { - fprintf(stderr, "expected output does not match\n"); - return EXIT_FAILURE; - } + err = PREFIX(inflateEnd)(&strm); + EXPECT_EQ(err, Z_OK); - return 0; + EXPECT_TRUE(memcmp(uncompressed, original, MIN(strm.total_out, strlen(original))) == 0); } diff --git a/test/test_inflate_sync.cc b/test/test_inflate_sync.cc new file mode 100644 index 0000000000..a79d867e68 --- /dev/null +++ b/test/test_inflate_sync.cc @@ -0,0 +1,75 @@ +/* test_inflate_sync.cc - Test inflateSync using full flush deflate and corrupted data */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(inflate, sync) { + PREFIX3(stream) c_stream, d_stream; + uint8_t compr[128], uncompr[128]; + z_size_t compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); + int err; + + memset(&c_stream, 0, sizeof(c_stream)); + + /* build compressed stream with full flush */ + err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uint32_t)compr_len; + + err = PREFIX(deflate)(&c_stream, Z_FULL_FLUSH); + EXPECT_EQ(err, Z_OK); + + /* force an error in first compressed block */ + compr[3]++; + c_stream.avail_in = hello_len-3; + + err = PREFIX(deflate)(&c_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + compr_len = (z_size_t)c_stream.total_out; + + memset(&d_stream, 0, sizeof(d_stream)); + /* just read the zlib header */ + d_stream.next_in = compr; + d_stream.avail_in = 2; + + err = PREFIX(inflateInit)(&d_stream); + EXPECT_EQ(err, Z_OK); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uint32_t)uncompr_len; + + err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + + /* read all compressed data, but skip damaged part */ + d_stream.avail_in = (uint32_t)compr_len-2; + err = PREFIX(inflateSync)(&d_stream); + EXPECT_EQ(err, Z_OK); + + err = PREFIX(inflate)(&d_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + + err = PREFIX(inflateEnd)(&d_stream); + EXPECT_EQ(err, Z_OK); +} diff --git a/test/test_large_buffers.cc b/test/test_large_buffers.cc new file mode 100644 index 0000000000..9bf133998a --- /dev/null +++ b/test/test_large_buffers.cc @@ -0,0 +1,87 @@ +/* test_large_buffers.cc - Test deflate() and inflate() with large buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +#define COMPR_BUFFER_SIZE (48 * 1024) +#define UNCOMPR_BUFFER_SIZE (32 * 1024) +#define UNCOMPR_RAND_SIZE (8 * 1024) + +TEST(deflate, large_buffers) { + PREFIX3(stream) c_stream, d_stream; + uint8_t *compr, *uncompr; + uint32_t compr_len, uncompr_len; + int32_t i; + time_t now; + int err; + + memset(&c_stream, 0, sizeof(c_stream)); + memset(&d_stream, 0, sizeof(d_stream)); + + compr = (uint8_t *)calloc(1, COMPR_BUFFER_SIZE); + ASSERT_TRUE(compr != NULL); + uncompr = (uint8_t *)calloc(1, UNCOMPR_BUFFER_SIZE); + ASSERT_TRUE(uncompr != NULL); + + compr_len = COMPR_BUFFER_SIZE; + uncompr_len = UNCOMPR_BUFFER_SIZE; + + srand((unsigned)time(&now)); + for (i = 0; i < UNCOMPR_RAND_SIZE; i++) + uncompr[i] = (uint8_t)(rand() % 256); + + err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + c_stream.next_out = compr; + c_stream.avail_out = compr_len; + c_stream.next_in = uncompr; + c_stream.avail_in = uncompr_len; + + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + EXPECT_EQ(c_stream.avail_in, 0); + + err = PREFIX(deflate)(&c_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END); + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + d_stream.next_in = compr; + d_stream.avail_in = compr_len; + d_stream.next_out = uncompr; + + err = PREFIX(inflateInit)(&d_stream); + EXPECT_EQ(err, Z_OK); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = uncompr_len; + err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(inflateEnd)(&d_stream); + EXPECT_EQ(err, Z_OK); + + EXPECT_EQ(d_stream.total_out, uncompr_len); + + free(compr); + free(uncompr); +} diff --git a/test/test_main.cc b/test/test_main.cc new file mode 100644 index 0000000000..c129db259f --- /dev/null +++ b/test/test_main.cc @@ -0,0 +1,17 @@ +/* test_test.cc - Main entry point for test framework */ + +#include + +#include "gtest/gtest.h" + +extern "C" { +# include "zbuild.h" +# include "cpu_features.h" +} + +GTEST_API_ int main(int argc, char **argv) { + printf("Running main() from %s\n", __FILE__); + cpu_check_features(); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/test/test_shared.h b/test/test_shared.h new file mode 100644 index 0000000000..f942967e5b --- /dev/null +++ b/test/test_shared.h @@ -0,0 +1,2 @@ +static const char hello[] = "hello, hello!"; +static const int hello_len = sizeof(hello); diff --git a/test/test_small_buffers.cc b/test/test_small_buffers.cc new file mode 100644 index 0000000000..bb3449fd88 --- /dev/null +++ b/test/test_small_buffers.cc @@ -0,0 +1,69 @@ +/* test_small_buffers.cc - Test deflate() and inflate() with small buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(deflate, small_buffers) { + PREFIX3(stream) c_stream, d_stream; + uint8_t compr[128], uncompr[128]; + z_size_t compr_len = sizeof(compr), uncompr_len = sizeof(uncompr); + int err; + + memset(&c_stream, 0, sizeof(c_stream)); + memset(&d_stream, 0, sizeof(d_stream)); + + err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); + EXPECT_EQ(err, Z_OK); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != hello_len && c_stream.total_out < compr_len) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH); + EXPECT_EQ(err, Z_OK); + } + /* Finish the stream, still forcing small buffers */ + for (;;) { + c_stream.avail_out = 1; + err = PREFIX(deflate)(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + + strcpy((char*)uncompr, "garbage"); + + d_stream.next_in = compr; + d_stream.next_out = uncompr; + + err = PREFIX(inflateInit)(&d_stream); + EXPECT_EQ(err, Z_OK); + + while (d_stream.total_out < uncompr_len && d_stream.total_in < compr_len) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + EXPECT_EQ(err, Z_OK); + } + + err = PREFIX(inflateEnd)(&d_stream); + EXPECT_EQ(err, Z_OK); + + EXPECT_STREQ((char*)uncompr, hello); +} diff --git a/test/test_version.cc b/test/test_version.cc new file mode 100644 index 0000000000..fda87904e0 --- /dev/null +++ b/test/test_version.cc @@ -0,0 +1,27 @@ +/* test_version.cc - Test zVersion() and zlibCompileFlags() */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +TEST(version, basic) { + static const char *my_version = PREFIX2(VERSION); + + EXPECT_EQ(zVersion()[0], my_version[0]); + EXPECT_STREQ(zVersion(), PREFIX2(VERSION)); + + printf("zlib-ng version %s = 0x%08lx, compile flags = 0x%lx\n", + ZLIBNG_VERSION, ZLIBNG_VERNUM, PREFIX(zlibCompileFlags)()); +} From e664973c031534b8d544dd0761bfe72738594eea Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 6 Feb 2022 09:51:06 -0800 Subject: [PATCH 290/798] Move CVE-2003-0107 test to Google Tests. --- .gitignore | 1 - CMakeLists.txt | 5 ----- configure | 2 -- test/Makefile.in | 21 ++---------------- test/README.md | 4 ++-- ...{CVE-2003-0107.c => test_cve-2003-0107.cc} | 22 ++++++++++++------- 6 files changed, 18 insertions(+), 37 deletions(-) rename test/{CVE-2003-0107.c => test_cve-2003-0107.cc} (55%) diff --git a/.gitignore b/.gitignore index 239171c2d6..e5aac03292 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,6 @@ /switchlevels /zlib.pc /zlib-ng.pc -/CVE-2003-0107 .DS_Store *_fuzzer diff --git a/CMakeLists.txt b/CMakeLists.txt index d88ca32e8d..440a716968 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1194,11 +1194,6 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME ${target} COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) endmacro() - - if(NOT WIN32 AND ZLIB_COMPAT) - add_simple_test_executable(CVE-2003-0107) - endif() - add_simple_test_executable(example) set(MINIGZIP_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) diff --git a/configure b/configure index 0ff33c34ce..149ae732a3 100755 --- a/configure +++ b/configure @@ -2205,7 +2205,6 @@ done # Generate Makefile in test dir mkdir -p test -if test $compat -eq 1; then COMPATTESTS="compattests"; fi if test $QEMU_ARCH; then QEMU_RUN="qemu-$QEMU_ARCH -L /usr/${CHOST}/"; fi sed < $SRCDIR/test/Makefile.in " /^CC *=/s#=.*#=$CC# @@ -2215,7 +2214,6 @@ sed < $SRCDIR/test/Makefile.in " /^oldtests: */s#:.*#: $TEST# /^SRCDIR *=/s#=.*#=$SRCDIR/test# /^SRCTOP *=/s#=.*#=$SRCDIR# -/^COMPATTESTS *=/s#=.*#=$COMPATTESTS# /^QEMU_RUN *=/s#=.*#=$QEMU_RUN# /^WITH_FUZZERS *=/s#=.*#=$with_fuzzers# /^LIBNAME *=/s#=.*#=$LIBNAME# diff --git a/test/Makefile.in b/test/Makefile.in index de72edc0f4..00050798b4 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -11,11 +11,10 @@ LIBNAME= TEST_LDFLAGS=-L.. ../$(LIBNAME).a WITH_FUZZERS= -COMPATTESTS = QEMU_RUN= QEMU_VER:=$(shell command -v $(QEMU_RUN) --version 2> /dev/null) -all: oldtests cvetests $(COMPATTESTS) fuzzer ghtests +all: oldtests cvetests fuzzer ghtests oldtests: #set by ../configure check_cross_dep: @@ -71,25 +70,9 @@ testshared: check_cross_dep cvetests: testCVEinputs -# Tests requiring zlib-ng to be built with --zlib-compat -compattests: testCVE-2003-0107 - testCVEinputs: check_cross_dep @EXE=$(EXE) QEMU_RUN="${QEMU_RUN}" $(SRCDIR)/testCVEinputs.sh -testCVE-2003-0107: CVE-2003-0107$(EXE) check_cross_dep - @if ${QEMU_RUN} ./CVE-2003-0107$(EXE); then \ - echo ' *** zlib not vulnerable to CVE-2003-0107 ***'; \ - else \ - echo ' *** zlib VULNERABLE to CVE-2003-0107 ***'; exit 1; \ - fi - -CVE-2003-0107.o: $(SRCDIR)/CVE-2003-0107.c - $(CC) $(CFLAGS) -I.. -I$(SRCTOP) -c -o $@ $(SRCDIR)/CVE-2003-0107.c - -CVE-2003-0107$(EXE): CVE-2003-0107.o - $(CC) $(CFLAGS) -o $@ CVE-2003-0107.o $(TEST_LDFLAGS) - .PHONY: ghtests ghtests: testGH-361 testGH-364 testGH-751 @@ -110,7 +93,7 @@ testGH-751: clean: rm -f *.o *.gcda *.gcno *.gcov - rm -f CVE-2003-0107$(EXE) switchlevels$(EXE) + rm -f switchlevels$(EXE) distclean: rm -f Makefile diff --git a/test/README.md b/test/README.md index b15b01df67..af655f15cb 100644 --- a/test/README.md +++ b/test/README.md @@ -3,7 +3,7 @@ Contents |Name|Description| |-|-| -|[CVE-2003-0107.c](https://nvd.nist.gov/vuln/detail/CVE-2003-0107)|Buffer overflow in the gzprintf function, requires ZLIB_COMPAT| +|[CVE-2003-0107](https://nvd.nist.gov/vuln/detail/CVE-2003-0107)|Buffer overflow in the gzprintf function, requires ZLIB_COMPAT| |[CVE-2002-0059](https://nvd.nist.gov/vuln/detail/CVE-2002-0059)|inflateEnd to release memory more than once| |[CVE-2004-0797](https://nvd.nist.gov/vuln/detail/CVE-2004-0797)|Error handling in inflate and inflateBack causes crash| |[CVE-2005-1849](https://nvd.nist.gov/vuln/detail/CVE-2005-1849)|inftrees.h bug causes crash| @@ -28,7 +28,7 @@ Some of the files in _test_ are licensed differently: which is licensed under the CC-BY license. See https://www.ploscompbiol.org/static/license for more information. - - test/data/lcet10.txt is from Project Gutenberg. It does not have expired + - test/data/lcet10.txt is from Project Gutenberg. It does not have expired copyright, but is still in the public domain according to the license information. (https://www.gutenberg.org/ebooks/53). diff --git a/test/CVE-2003-0107.c b/test/test_cve-2003-0107.cc similarity index 55% rename from test/CVE-2003-0107.c rename to test/test_cve-2003-0107.cc index 427767d072..9d9e5b00df 100644 --- a/test/CVE-2003-0107.c +++ b/test/test_cve-2003-0107.cc @@ -1,22 +1,28 @@ // https://www.securityfocus.com/archive/1/312869 --- originally by Richard Kettlewell #include -#include #include #include -int main(void) { +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include + +#if !defined(_WIN32) && defined(ZLIB_COMPAT) +TEST(gzip, cve_2003_0107) { gzFile f; int ret; - if(!(f = gzopen("/dev/null", "w"))) { - perror("/dev/null"); - exit(1); - } + f = gzopen("/dev/null", "w"); + EXPECT_TRUE(f != NULL); ret = gzprintf(f, "%10240s", ""); printf("gzprintf -> %d\n", ret); ret = gzclose(f); printf("gzclose -> %d [%d]\n", ret, errno); - - exit(0); } +#endif From 818d4beadb73e97456d3b79361e918c71e892e43 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 26 Jan 2022 18:27:20 -0800 Subject: [PATCH 291/798] Specify c++ compiler, packages, and flags for Google Test in cmake workflow. --- .github/workflows/cmake.yml | 68 +++++++++++++++++++++++--------- .github/workflows/pkgcheck.yml | 28 ++++++++++--- cmake/toolchain-mingw-i686.cmake | 11 ++++-- 3 files changed, 79 insertions(+), 28 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 1a50b0ea3b..9087990ed6 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -11,34 +11,40 @@ jobs: - name: Ubuntu 18.04 GCC os: ubuntu-18.04 compiler: gcc + cxx-compiler: g++ - name: Ubuntu GCC ASAN os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_SANITIZER=Address codecov: ubuntu_gcc - name: Ubuntu GCC Benchmark os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_BENCHMARKS=ON codecov: ubuntu_gcc_benchmark - name: Ubuntu GCC Symbol Prefix os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DZLIB_SYMBOL_PREFIX=zTest_ codecov: ubuntu_gcc_sprefix - name: Ubuntu GCC Compat Symbol Prefix os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DZLIB_COMPAT=ON -DZLIB_SYMBOL_PREFIX=zTest_ codecov: ubuntu_gcc_compat_sprefix - name: Ubuntu GCC OSB -O1 No Unaligned64 UBSAN os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_UNALIGNED=ON -DUNALIGNED64_OK=OFF -DWITH_SANITIZER=Undefined build-dir: ../build build-src-dir: ../zlib-ng @@ -48,6 +54,7 @@ jobs: - name: Ubuntu GCC -O3 No Unaligned os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_UNALIGNED=OFF codecov: ubuntu_gcc_o3 cflags: -O3 @@ -55,47 +62,55 @@ jobs: - name: Ubuntu GCC No CTZLL os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_OPTIM=OFF -DHAVE_BUILTIN_CTZLL=OFF codecov: ubuntu_gcc_no_ctzll - name: Ubuntu GCC No CTZ os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_OPTIM=OFF -DHAVE_BUILTIN_CTZLL=OFF -DHAVE_BUILTIN_CTZ=OFF codecov: ubuntu_gcc_no_ctz - name: Ubuntu GCC Link Zlib os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DZLIB_DUAL_LINK=ON - name: Ubuntu GCC No AVX2 UBSAN os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_AVX2=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_avx2 - name: Ubuntu GCC No SSE2 UBSAN os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_SSE2=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_sse2 - name: Ubuntu GCC No SSE4 UBSAN os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_SSE4=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_sse4 - name: Ubuntu GCC No PCLMULQDQ UBSAN os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_PCLMULQDQ=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_no_pclmulqdq - name: Ubuntu GCC Compat No Opt ASAN os: ubuntu-latest compiler: gcc + cxx-compiler: g++ cmake-args: -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Address codecov: ubuntu_gcc_compat_no_opt cflags: -DNOT_TWEAK_COMPILER @@ -104,77 +119,77 @@ jobs: os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross + packages: qemu qemu-user gcc-arm-linux-gnueabi g++-arm-linux-gnueabi libc-dev-armel-cross codecov: ubuntu_gcc_armsf - name: Ubuntu GCC ARM SF Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-arm-linux-gnueabi libc-dev-armel-cross + packages: qemu qemu-user gcc-arm-linux-gnueabi g++-arm-linux-gnueabi libc-dev-armel-cross codecov: ubuntu_gcc_armsf_compat_no_opt - name: Ubuntu GCC ARM HF ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross + packages: qemu qemu-user gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf - name: Ubuntu GCC ARM HF No ACLE ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross + packages: qemu qemu-user gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf_no_acle - name: Ubuntu GCC ARM HF No NEON ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross + packages: qemu qemu-user gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf_no_neon - name: Ubuntu GCC ARM HF Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-arm-linux-gnueabihf libc-dev-armel-cross + packages: qemu qemu-user gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf_compat_no_opt - name: Ubuntu GCC AARCH64 ASAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross + packages: qemu qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64 - name: Ubuntu GCC AARCH64 No ACLE UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross + packages: qemu qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_no_acle - name: Ubuntu GCC AARCH64 No NEON UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross + packages: qemu qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_no_neon - name: Ubuntu GCC AARCH64 Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-aarch64-linux-gnu libc-dev-arm64-cross + packages: qemu qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_compat_no_opt - name: Ubuntu GCC PPC os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross + packages: qemu qemu-user gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc-dev-powerpc-cross ldflags: -static codecov: ubuntu_gcc_ppc @@ -182,14 +197,14 @@ jobs: os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake -DWITH_POWER8=OFF asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-powerpc-linux-gnu libc-dev-powerpc-cross + packages: qemu qemu-user gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc-dev-powerpc-cross codecov: ubuntu_gcc_ppc_no_power8 - name: Ubuntu GCC PPC64 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64.cmake asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-powerpc64-linux-gnu libc-dev-ppc64-cross + packages: qemu qemu-user gcc-powerpc64-linux-gnu g++-powerpc64-linux-gnu libc-dev-ppc64-cross ldflags: -static codecov: ubuntu_gcc_ppc64 @@ -197,14 +212,14 @@ jobs: os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-powerpc64le-linux-gnu libc-dev-ppc64el-cross + packages: qemu qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc-dev-ppc64el-cross codecov: ubuntu_gcc_ppc64le - name: Ubuntu GCC SPARC64 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-sparc64-linux-gnu libc-dev-sparc64-cross + packages: qemu qemu-user gcc-sparc64-linux-gnu g++-sparc64-linux-gnu libc-dev-sparc64-cross ldflags: -static codecov: ubuntu_gcc_sparc64 @@ -212,7 +227,7 @@ jobs: os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross + packages: qemu qemu-user gcc-s390x-linux-gnu g++-s390x-linux-gnu libc-dev-s390x-cross ldflags: -static codecov: ubuntu_gcc_s390x @@ -220,13 +235,14 @@ jobs: os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-s390x.cmake -DWITH_CRC32_VX=OFF -DWITH_SANITIZER=Address asan-options: detect_leaks=0 - packages: qemu qemu-user gcc-s390x-linux-gnu libc-dev-s390x-cross + packages: qemu qemu-user gcc-s390x-linux-gnu g++-s390x-linux-gnu libc-dev-s390x-cross ldflags: -static codecov: ubuntu_gcc_s390x_no_crc32 - name: Ubuntu GCC S390X DFLTCC ASAN os: z15 compiler: gcc + cxx-compiler: g++ cmake-args: -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Address asan-options: detect_leaks=0 codecov: ubuntu_gcc_s390x_dfltcc @@ -234,6 +250,7 @@ jobs: - name: Ubuntu GCC S390X DFLTCC Compat UBSAN os: z15 compiler: gcc + cxx-compiler: g++ cmake-args: -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 codecov: ubuntu_gcc_s390x_dfltcc_compat @@ -241,7 +258,7 @@ jobs: - name: Ubuntu MinGW i686 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake - packages: wine32 gcc-mingw-w64 + packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 codecov: ubuntu_gcc_mingw_i686 # Limit parallel test jobs to prevent wine errors parallels-jobs: 1 @@ -249,7 +266,7 @@ jobs: - name: Ubuntu MinGW x86_64 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-x86_64.cmake - packages: wine-stable gcc-mingw-w64 + packages: wine-stable gcc-mingw-w64 g++-mingw-w64 codecov: ubuntu_gcc_mingw_x86_64 # Limit parallel test jobs to prevent wine errors parallels-jobs: 1 @@ -257,11 +274,13 @@ jobs: - name: Ubuntu 18.04 Clang os: ubuntu-18.04 compiler: clang-6.0 + cxx-compiler: clang++-6.0 packages: clang-6.0 - name: Ubuntu Clang os: ubuntu-latest compiler: clang-11 + cxx-compiler: clang++-11 packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang @@ -269,6 +288,7 @@ jobs: - name: Ubuntu Clang Inflate Strict os: ubuntu-latest compiler: clang-11 + cxx-compiler: clang++-11 cmake-args: -DWITH_INFLATE_STRICT=ON packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov @@ -277,6 +297,7 @@ jobs: - name: Ubuntu Clang Inflate Allow Invalid Dist os: ubuntu-latest compiler: clang-11 + cxx-compiler: clang++-11 cmake-args: -DWITH_INFLATE_ALLOW_INVALID_DIST=ON packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov @@ -285,6 +306,7 @@ jobs: - name: Ubuntu Clang Reduced Memory os: ubuntu-latest compiler: clang-11 + cxx-compiler: clang++-11 cmake-args: -DWITH_REDUCED_MEM=ON packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov @@ -293,6 +315,7 @@ jobs: - name: Ubuntu Clang Memory Map os: ubuntu-latest compiler: clang-11 + cxx-compiler: clang++-11 cflags: -DUSE_MMAP packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov @@ -301,6 +324,7 @@ jobs: - name: Ubuntu Clang Debug os: ubuntu-latest compiler: clang-11 + cxx-compiler: clang++-11 packages: llvm-11-tools gcov-exec: llvm-cov-11 gcov codecov: ubuntu_clang_debug @@ -309,6 +333,7 @@ jobs: - name: Ubuntu Clang MSAN os: ubuntu-latest compiler: clang-11 + cxx-compiler: clang++-11 cmake-args: -GNinja -DWITH_SANITIZER=Memory packages: ninja-build llvm-11-tools gcov-exec: llvm-cov-11 gcov @@ -345,24 +370,28 @@ jobs: - name: Windows GCC os: windows-latest compiler: gcc + cxx-compiler: g++ cmake-args: -G Ninja codecov: win64_gcc - name: Windows GCC Compat No Opt os: windows-latest compiler: gcc + cxx-compiler: g++ cmake-args: -G Ninja -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF codecov: win64_gcc_compat_no_opt - name: macOS Clang ASAN os: macos-latest compiler: clang + cxx-compiler: clang++ cmake-args: -DWITH_SANITIZER=Address codecov: macos_clang - name: macOS GCC UBSAN os: macos-latest compiler: gcc-10 + cxx-compiler: g++-10 cmake-args: -DWITH_SANITIZER=Undefined packages: gcc@10 gcov-exec: gcov-10 @@ -419,6 +448,7 @@ jobs: cmake ${{ matrix.build-src-dir || '.' }} ${{ matrix.cmake-args }} -DCMAKE_BUILD_TYPE=${{ matrix.build-config || 'Release' }} -DBUILD_SHARED_LIBS=OFF -DWITH_FUZZERS=ON ${{ matrix.codecov && '-DWITH_CODE_COVERAGE=ON' }} -DWITH_MAINTAINER_WARNINGS=ON env: CC: ${{ matrix.compiler }} + CXX: ${{ matrix.cxx-compiler }} CFLAGS: ${{ matrix.cflags }} LDFLAGS: ${{ matrix.ldflags }} CI: true diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 8f3338abff..41daf5f309 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -11,56 +11,66 @@ jobs: - name: Ubuntu GCC os: ubuntu-latest compiler: gcc + cxx-compiler: g++ - name: Ubuntu GCC -m32 os: ubuntu-latest compiler: gcc - packages: gcc-multilib - cmake-args: -DCMAKE_C_FLAGS=-m32 + cxx-compiler: g++ + packages: gcc-multilib g++-multilib + cmake-args: -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 cflags: -m32 + cxxflags: -m32 ldflags: -m32 - name: Ubuntu GCC ARM HF os: ubuntu-latest chost: arm-linux-gnueabihf compiler: arm-linux-gnueabihf-gcc + cxx-compiler: g++-arm-linux-gnueabihf cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake - packages: qemu gcc-arm-linux-gnueabihf libc6-dev-armhf-cross + packages: qemu gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc6-dev-armhf-cross - name: Ubuntu GCC AARCH64 os: ubuntu-latest chost: aarch64-linux-gnu compiler: aarch64-linux-gnu-gcc + cxx-compiler: g++-aarch64-linux-gnu cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake - packages: qemu gcc-aarch64-linux-gnu libc6-dev-arm64-cross + packages: qemu gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6-dev-arm64-cross - name: Ubuntu GCC PPC os: ubuntu-latest chost: powerpc-linux-gnu compiler: powerpc-linux-gnu-gcc + cxx-compiler: g++-powerpc-linux-gnu cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake - packages: qemu gcc-powerpc-linux-gnu libc6-dev-powerpc-cross + packages: qemu gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc6-dev-powerpc-cross - name: Ubuntu GCC PPC64LE os: ubuntu-latest chost: powerpc64le-linux-gnu compiler: powerpc64le-linux-gnu-gcc + cxx-compiler: g++-powerpc64le-linux-gnu cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake - packages: qemu gcc-powerpc64le-linux-gnu libc6-dev-ppc64el-cross + packages: qemu gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc6-dev-ppc64el-cross - name: macOS Clang os: macOS-latest compiler: clang + cxx-compiler: clang++ - name: macOS Clang Native os: macOS-latest compiler: clang + cxx-compiler: clang++ cmake-args: -DWITH_NATIVE_INSTRUCTIONS=ON configure-args: --native - name: macOS Clang Symbol Prefix os: macOS-latest compiler: clang + cxx-compiler: clang++ cmake-args: -DZLIB_SYMBOL_PREFIX=zTest_ configure-args: --sprefix=zTest_ @@ -95,7 +105,9 @@ jobs: sh test/pkgcheck.sh env: CC: ${{ matrix.compiler }} + CXX: ${{ matrix.cxx-compiler }} CFLAGS: ${{ matrix.cflags }} + CXXFLAGS: ${{ matrix.cxxflags }} CHOST: ${{ matrix.chost }} CMAKE_ARGS: ${{ matrix.cmake-args }} CONFIGURE_ARGS: ${{ matrix.configure-args }} @@ -119,7 +131,9 @@ jobs: sh test/abicheck.sh --refresh_if env: CC: ${{ matrix.compiler }} + CXX: ${{ matrix.cxx-compiler }} CFLAGS: ${{ matrix.cflags }} + CXXFLAGS: ${{ matrix.cxxflags }} CHOST: ${{ matrix.chost }} CMAKE_ARGS: ${{ matrix.cmake-args }} CONFIGURE_ARGS: ${{ matrix.configure-args }} @@ -132,7 +146,9 @@ jobs: sh test/abicheck.sh --zlib-compat --refresh_if env: CC: ${{ matrix.compiler }} + CXX: ${{ matrix.cxx-compiler }} CFLAGS: ${{ matrix.cflags }} + CXXFLAGS: ${{ matrix.cxxflags }} CHOST: ${{ matrix.chost }} CMAKE_ARGS: ${{ matrix.cmake-args }} CONFIGURE_ARGS: ${{ matrix.configure-args }} diff --git a/cmake/toolchain-mingw-i686.cmake b/cmake/toolchain-mingw-i686.cmake index 07ae63ce74..9a51cd22b2 100644 --- a/cmake/toolchain-mingw-i686.cmake +++ b/cmake/toolchain-mingw-i686.cmake @@ -12,18 +12,23 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc) +find_program(C_COMPILER_FULL_PATH NAMES + ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc + gcc-mingw32-w64-${CMAKE_C_COMPILER_TARGET}) if(NOT C_COMPILER_FULL_PATH) message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH NAMES ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES + g++-mingw-w64-${CMAKE_CXX_COMPILER_TARGET} + ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() -find_program(RC_COMPILER_FULL_PATH NAMES ${CMAKE_RC_COMPILER_TARGET}-w64-mingw32-windres) +find_program(RC_COMPILER_FULL_PATH NAMES + ${CMAKE_RC_COMPILER_TARGET}-w64-mingw32-windres) if(RC_COMPILER_FULL_PATH) set(CMAKE_RC_COMPILER ${RC_COMPILER_FULL_PATH}) endif() From 8f9f9ff5cf5af8a528a2ef707d1f7f11e7495c8c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 31 Jan 2022 15:50:27 -0800 Subject: [PATCH 292/798] Added static versions of c++ libraries on S390X, MinGW, and ppc. --- .github/workflows/cmake.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9087990ed6..100165fb9a 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -190,7 +190,6 @@ jobs: cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc-dev-powerpc-cross - ldflags: -static codecov: ubuntu_gcc_ppc - name: Ubuntu GCC PPC No Power8 @@ -245,6 +244,7 @@ jobs: cxx-compiler: g++ cmake-args: -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Address asan-options: detect_leaks=0 + ldflags: -static codecov: ubuntu_gcc_s390x_dfltcc - name: Ubuntu GCC S390X DFLTCC Compat UBSAN @@ -253,12 +253,14 @@ jobs: cxx-compiler: g++ cmake-args: -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined asan-options: detect_leaks=0 + ldflags: -static codecov: ubuntu_gcc_s390x_dfltcc_compat - name: Ubuntu MinGW i686 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 + ldflags: -static codecov: ubuntu_gcc_mingw_i686 # Limit parallel test jobs to prevent wine errors parallels-jobs: 1 @@ -267,6 +269,7 @@ jobs: os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-x86_64.cmake packages: wine-stable gcc-mingw-w64 g++-mingw-w64 + ldflags: -static codecov: ubuntu_gcc_mingw_x86_64 # Limit parallel test jobs to prevent wine errors parallels-jobs: 1 From 21251622daf4a25e13886c4908c858677ce16a70 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 31 Jan 2022 15:59:42 -0800 Subject: [PATCH 293/798] Prefer posix versions of MinGW for compiling against googletest. --- cmake/toolchain-mingw-i686.cmake | 3 +++ cmake/toolchain-mingw-x86_64.cmake | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cmake/toolchain-mingw-i686.cmake b/cmake/toolchain-mingw-i686.cmake index 9a51cd22b2..4b1264cb5b 100644 --- a/cmake/toolchain-mingw-i686.cmake +++ b/cmake/toolchain-mingw-i686.cmake @@ -12,7 +12,9 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +# Prefer posix gcc variant for gtest pthread support find_program(C_COMPILER_FULL_PATH NAMES + ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc-posix ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc gcc-mingw32-w64-${CMAKE_C_COMPILER_TARGET}) if(NOT C_COMPILER_FULL_PATH) @@ -22,6 +24,7 @@ set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) find_program(CXX_COMPILER_FULL_PATH NAMES g++-mingw-w64-${CMAKE_CXX_COMPILER_TARGET} + ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++-posix ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) diff --git a/cmake/toolchain-mingw-x86_64.cmake b/cmake/toolchain-mingw-x86_64.cmake index aa597da333..7ae8140422 100644 --- a/cmake/toolchain-mingw-x86_64.cmake +++ b/cmake/toolchain-mingw-x86_64.cmake @@ -12,13 +12,18 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -find_program(C_COMPILER_FULL_PATH NAMES ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc) +# Prefer posix gcc variant for gtest pthread support +find_program(C_COMPILER_FULL_PATH NAMES + ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc-posix + ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-gcc) if(NOT C_COMPILER_FULL_PATH) message(FATAL_ERROR "Cross-compiler for ${CMAKE_C_COMPILER_TARGET} not found") endif() set(CMAKE_C_COMPILER ${C_COMPILER_FULL_PATH}) -find_program(CXX_COMPILER_FULL_PATH NAMES ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) +find_program(CXX_COMPILER_FULL_PATH NAMES + ${CMAKE_C_COMPILER_TARGET}-w64-mingw32-g++-posix + ${CMAKE_CXX_COMPILER_TARGET}-w64-mingw32-g++) if(CXX_COMPILER_FULL_PATH) set(CMAKE_CXX_COMPILER ${CXX_COMPILER_FULL_PATH}) endif() From f7e746bcf6585527659179e906b984cd8dd2ae28 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 3 Feb 2022 14:37:12 -0800 Subject: [PATCH 294/798] Compile MSAN instrumented C++ libraries for MSAN build with googletest. --- .github/workflows/cmake.yml | 14 ++++++++++++++ test/CMakeLists.txt | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 100165fb9a..3b6ac22206 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -443,6 +443,20 @@ jobs: run: | wineboot --init + - name: Compile LLVM C++ libraries (MSAN) + if: contains(matrix.name, 'MSAN') + run: | + git clone --depth=1 https://github.com/llvm/llvm-project --single-branch --branch llvmorg-11.0.0 + cd llvm-project + mkdir build + cd build + cmake -G Ninja ../llvm -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" -DLLVM_USE_SANITIZER=MemoryWithOrigins -DLLVM_LIBC_ENABLE_LINTING=OFF + cmake --build . -- cxx cxxabi + echo "LLVM_BUILD_DIR=`pwd`" >> $GITHUB_ENV + env: + CC: ${{ matrix.compiler }} + CXX: ${{ matrix.cxx-compiler }} + - name: Generate project files # Shared libraries turned off for qemu ppc* and sparc & reduce code coverage sources run: | diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 973e9f9399..9def5f120a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,6 +7,17 @@ enable_language(CXX) # Google test requires at least C++11 set(CMAKE_CXX_STANDARD 11) +# Google test requires MSAN instrumented LLVM C++ libraries +if(WITH_SANITIZER STREQUAL "Memory") + if(NOT DEFINED ENV{LLVM_BUILD_DIR}) + message(FATAL_ERROR "MSAN instrumented C++ libraries required!") + endif() + + # Must set include and compile options before fetching googletest + include_directories($ENV{LLVM_BUILD_DIR}/include $ENV{LLVM_BUILD_DIR}/include/c++/v1) + add_compile_options(-stdlib=libc++ -g) +endif() + # Prevent overriding the parent project's compiler/linker settings for Windows set(gtest_force_shared_crt ON CACHE BOOL "Use shared (DLL) run-time lib even when Google Test is built as static lib." FORCE) @@ -36,6 +47,15 @@ target_include_directories(gtest_zlib PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) +if(WITH_SANITIZER STREQUAL "Memory") + target_link_directories(gtest_zlib PRIVATE $ENV{LLVM_BUILD_DIR}/lib) + target_link_options(gtest_zlib PRIVATE + -stdlib=libc++ + -lc++abi + -fsanitize=memory + -fsanitize-memory-track-origins) +endif() + target_link_libraries(gtest_zlib zlibstatic gtest) if(ZLIB_ENABLE_TESTS) From 42b15e36f713c105df1b776dc3cc50e83cf11e61 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 24 Feb 2022 17:56:09 -0800 Subject: [PATCH 295/798] Ignore code coverage for files in _dep directory. --- .codecov.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.codecov.yaml b/.codecov.yaml index 50ad857b57..fc17c66a90 100644 --- a/.codecov.yaml +++ b/.codecov.yaml @@ -23,4 +23,5 @@ ignore: - /build/usr/lib/.* - usr/lib64/.* - /usr/lib64/.* -- /build/usr/lib64/.* \ No newline at end of file +- /build/usr/lib64/.* +- _deps/**/* From a5a98448c318387ece5dde8edca1cae2169b773a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 7 Mar 2022 08:25:42 -0800 Subject: [PATCH 296/798] Use older version of Google test to support older versions of GCC. Allow specifying alternative Google test repository and tag. --- test/CMakeLists.txt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9def5f120a..35655a3d0d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,10 +25,23 @@ set(gtest_force_shared_crt ON CACHE BOOL set(gtest_disable_pthreads ON CACHE BOOL "Disable uses of pthreads in gtest." FORCE) +# Allow specifying alternative Google test repository +if(NOT DEFINED GTEST_REPOSITORY) + set(GTEST_REPOSITORY https://github.com/google/googletest.git) +endif() +if(NOT DEFINED GTEST_TAG) + # Use older version of Google test to support older versions of GCC + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3) + set(GTEST_TAG release-1.10.0) + else() + set(GTEST_TAG main) + endif() +endif() + # Fetch Google test source code from official repository FetchContent_Declare(googletest - GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG main) + GIT_REPOSITORY ${GTEST_REPOSITORY} + GIT_TAG ${GTEST_TAG}) FetchContent_GetProperties(googletest) if(NOT googletest_POPULATED) From 360054119427d1b613f878ce5f1221a390c0acfe Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 15 Mar 2022 08:09:04 -0400 Subject: [PATCH 297/798] IBM Z: Delete stale self-hosted builder containers Due to things like power outage ExecStop may not run, resulting in a stale actions-runner container. This would prevent ExecStart from succeeding, so try deleting such stale containers in ExecStartPre. --- arch/s390/self-hosted-builder/actions-runner.service | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/self-hosted-builder/actions-runner.service b/arch/s390/self-hosted-builder/actions-runner.service index 1d3129ff50..71053a79d6 100644 --- a/arch/s390/self-hosted-builder/actions-runner.service +++ b/arch/s390/self-hosted-builder/actions-runner.service @@ -7,6 +7,7 @@ StartLimitIntervalSec=0 [Service] Type=simple Restart=always +ExecStartPre=-/usr/bin/docker rm --force actions-runner ExecStart=/usr/bin/docker run \ --env-file=/etc/actions-runner \ --init \ From a39e323a4db80a57feecf2ae212c08070234050c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 4 Jan 2022 10:30:54 -0800 Subject: [PATCH 298/798] Added memory alignment compensation functions for users who may be using custom allocators that don't align on the same boundary zlib-ng expects. --- zutil.c | 39 +++++++++++++++++++++++++++++++++++++++ zutil.h | 11 +++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/zutil.c b/zutil.c index 18db2fe00f..20f5ac120c 100644 --- a/zutil.c +++ b/zutil.c @@ -109,3 +109,42 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr) { Z_UNUSED(opaque); zng_free(ptr); } + +/* Since we support custom memory allocators, some which might not align memory as we expect, + * we have to ask for extra memory and return an aligned pointer. */ +void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align) { + uintptr_t return_ptr, original_ptr; + int32_t alloc_size, align_diff; + void *ptr; + + /* Allocate enough memory for proper alignment and to store the original memory pointer */ + alloc_size = sizeof(void *) + (items * size) + align; + ptr = zalloc(opaque, 1, alloc_size); + if (!ptr) + return NULL; + + /* Calculate return pointer address with space enough to store original pointer */ + align_diff = align - ((uintptr_t)ptr % align); + return_ptr = (uintptr_t)ptr + align_diff; + if (align_diff < sizeof(void *)) + return_ptr += align; + + /* Store the original pointer for free() */ + original_ptr = return_ptr - sizeof(void *); + memcpy((void *)original_ptr, &ptr, sizeof(void *)); + + /* Return properly aligned pointer in allocation */ + return (void *)return_ptr; +} + +void Z_INTERNAL zng_cfree_aligned(zng_cfree_func zfree, void *opaque, void *ptr) { + if (!ptr) + return; + + /* Calculate offset to original memory allocation pointer */ + void *original_ptr = (void *)((uintptr_t)ptr - sizeof(void *)); + void *free_ptr = *(void **)original_ptr; + + /* Free original memory allocation */ + zfree(opaque, free_ptr); +} diff --git a/zutil.h b/zutil.h index 2a30c6d577..5022b36f54 100644 --- a/zutil.h +++ b/zutil.h @@ -125,8 +125,15 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size); void Z_INTERNAL zng_cfree(void *opaque, void *ptr); -#define ZALLOC(strm, items, size) (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (void *)(addr)) +typedef void *zng_calloc_func(void *opaque, unsigned items, unsigned size); +typedef void zng_cfree_func(void *opaque, void *ptr); + +void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align); +void Z_INTERNAL zng_cfree_aligned(zng_cfree_func zfree, void *opaque, void *ptr); + +#define ZALLOC(strm, items, size) zng_calloc_aligned((strm)->zalloc, (strm)->opaque, (items), (size), 64) +#define ZFREE(strm, addr) zng_cfree_aligned((strm)->zfree, (strm)->opaque, (void *)(addr)) + #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} #endif /* ZUTIL_H_ */ From 80d9b164550ce9542c1987fb3903cc227b4bd3a6 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 24 Jan 2022 20:58:54 -0800 Subject: [PATCH 299/798] Bypass memory alignment compensation if not using custom allocator. --- zutil.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/zutil.c b/zutil.c index 20f5ac120c..c3ef19f5bc 100644 --- a/zutil.c +++ b/zutil.c @@ -117,6 +117,10 @@ void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsign int32_t alloc_size, align_diff; void *ptr; + /* If no custom calloc function used then call zlib-ng's aligned calloc */ + if (zalloc == zng_calloc) + return zng_calloc(opaque, items, size); + /* Allocate enough memory for proper alignment and to store the original memory pointer */ alloc_size = sizeof(void *) + (items * size) + align; ptr = zalloc(opaque, 1, alloc_size); @@ -138,6 +142,11 @@ void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsign } void Z_INTERNAL zng_cfree_aligned(zng_cfree_func zfree, void *opaque, void *ptr) { + /* If no custom cfree function used then call zlib-ng's aligned cfree */ + if (zfree == zng_cfree) { + zng_cfree(opaque, ptr); + return; + } if (!ptr) return; From 87b4a35b7a71fd34542dd2ca75c54bd0b7000385 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Mar 2022 11:46:02 -0700 Subject: [PATCH 300/798] Added unit test for zng_calloc_aligned to ensure that it always returns 64-byte aligned memory allocation when requested. --- test/test_aligned_alloc.cc | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 test/test_aligned_alloc.cc diff --git a/test/test_aligned_alloc.cc b/test/test_aligned_alloc.cc new file mode 100644 index 0000000000..43324d3db5 --- /dev/null +++ b/test/test_aligned_alloc.cc @@ -0,0 +1,44 @@ +/* test_aligned_alloc.cc - Test zng_calloc_aligned and zng_cfree_aligned */ + +#include +#include +#include + +extern "C" { +# include "zbuild.h" +# include "zutil.h" +} + +#include + +void *zng_calloc_unaligned(void *opaque, unsigned items, unsigned size) { + uint8_t *pointer = (uint8_t *)calloc(1, (items * size) + 2); + if (pointer == NULL) + return pointer; + /* Store whether or not our allocation is aligned */ + *pointer = ((uint64_t)(intptr_t)pointer + 1) % 2 == 0; + pointer++; + if (*pointer) { + /* Return pointer that is off by one */ + pointer++; + } + return (void *)pointer; +} + +void zng_cfree_unaligned(void *opaque, void *ptr) { + uint8_t *pointer = (uint8_t *)ptr; + pointer--; + /* Get whether or not our original memory pointer was aligned */ + if (*pointer) { + /* Return original aligned pointer to free() */ + pointer--; + } + free(pointer); +} + +TEST(zalloc, aligned_64) { + void *return_ptr = zng_calloc_aligned(zng_calloc_unaligned, 0, 1, 100, 64); + ASSERT_TRUE(return_ptr != NULL); + EXPECT_EQ((intptr_t)return_ptr % 64, 0); + zng_cfree_aligned(zng_cfree_unaligned, 0, return_ptr); +} From ff554565c09ee52e7503d817e26ce090ac0cf5c3 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 23 Jan 2022 23:32:46 -0500 Subject: [PATCH 301/798] Improve SSE2 slide hash performance At least on pre-nehalem CPUs, we get a > 50% improvement. This is mostly due to the fact that we're opportunistically doing aligned loads instead of unaligned loads. This is something that is very likely to be possible, given that the deflate stream initialization uses the zalloc function, which most libraries don't override. Our allocator aligns to 64 byte boundaries, meaning we can do aligned loads on even AVX512 for the zstream->prev and zstream->head pointers. However, only pre-nehalem CPUs _actually_ benefit from explicitly aligned load instructions. The other thing being done here is we're unrolling the loop by a factor of 2 so that we can get a tiny bit more ILP. This improved performance by another 5%-7% gain. --- arch/x86/slide_hash_sse2.c | 46 +++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/arch/x86/slide_hash_sse2.c b/arch/x86/slide_hash_sse2.c index 7507c68b12..1bd2bebf56 100644 --- a/arch/x86/slide_hash_sse2.c +++ b/arch/x86/slide_hash_sse2.c @@ -12,27 +12,51 @@ #include "../../deflate.h" #include +#include + +static inline void slide_hash_chain(Pos *table0, Pos *table1, uint32_t entries0, + uint32_t entries1, const __m128i wsize) { + uint32_t entries; + Pos *table; + __m128i value0, value1, result0, result1; + + int on_chain = 0; + +next_chain: + table = (on_chain) ? table1 : table0; + entries = (on_chain) ? entries1 : entries0; -static inline void slide_hash_chain(Pos *table, uint32_t entries, const __m128i wsize) { table += entries; - table -= 8; + table -= 16; + /* ZALLOC allocates this pointer unless the user chose a custom allocator. + * Our alloc function is aligned to 64 byte boundaries */ do { - __m128i value, result; + value0 = _mm_load_si128((__m128i *)table); + value1 = _mm_load_si128((__m128i *)(table + 8)); + result0 = _mm_subs_epu16(value0, wsize); + result1 = _mm_subs_epu16(value1, wsize); + _mm_store_si128((__m128i *)table, result0); + _mm_store_si128((__m128i *)(table + 8), result1); - value = _mm_loadu_si128((__m128i *)table); - result= _mm_subs_epu16(value, wsize); - _mm_storeu_si128((__m128i *)table, result); - - table -= 8; - entries -= 8; + table -= 16; + entries -= 16; } while (entries > 0); + + ++on_chain; + if (on_chain > 1) { + return; + } else { + goto next_chain; + } } Z_INTERNAL void slide_hash_sse2(deflate_state *s) { uint16_t wsize = (uint16_t)s->w_size; const __m128i xmm_wsize = _mm_set1_epi16((short)wsize); - slide_hash_chain(s->head, HASH_SIZE, xmm_wsize); - slide_hash_chain(s->prev, wsize, xmm_wsize); + assert(((uintptr_t)s->head) & 15 == 0); + assert(((uintptr_t)s->prev) & 15 == 0); + + slide_hash_chain(s->head, s->prev, HASH_SIZE, wsize, xmm_wsize); } From 49a6bb5d413fef477a76111e1a5946452ff9d4a8 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Mon, 21 Feb 2022 16:52:17 -0500 Subject: [PATCH 302/798] Speed up chunkcopy and memset This was found to have a significant impact on a highly compressible PNG for both the encode and decode. Some deltas show performance improving as much as 60%+. For the scenarios where the "dist" is not an even modulus of our chunk size, we simply repeat the bytes as many times as possible into our vector registers. We then copy the entire vector and then advance the quotient of our chunksize divided by our dist value. If dist happens to be 1, there's no reason to not just call memset from libc (this is likely to be just as fast if not faster). --- chunkset_tpl.h | 141 +++++++++++++++++++------------------------------ functable.c | 27 ---------- functable.h | 1 - inffast.c | 11 ++-- inflate.c | 2 +- inflate_p.h | 75 ++++++++++++++++++++++++++ 6 files changed, 136 insertions(+), 121 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 8e6f566443..189b5ec457 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -3,6 +3,7 @@ */ #include "zbuild.h" +#include /* Returns the chunk size */ Z_INTERNAL uint32_t CHUNKSIZE(void) { @@ -38,52 +39,6 @@ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { return out; } -/* Behave like chunkcopy, but avoid writing beyond of legal output. */ -Z_INTERNAL uint8_t* CHUNKCOPY_SAFE(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe) { - unsigned safelen = (unsigned)((safe - out) + 1); - len = MIN(len, safelen); -#if CHUNK_SIZE >= 32 - while (len >= 32) { - memcpy(out, from, 32); - out += 32; - from += 32; - len -= 32; - } -#endif -#if CHUNK_SIZE >= 16 - while (len >= 16) { - memcpy(out, from, 16); - out += 16; - from += 16; - len -= 16; - } -#endif -#if CHUNK_SIZE >= 8 - while (len >= 8) { - zmemcpy_8(out, from); - out += 8; - from += 8; - len -= 8; - } -#endif - if (len >= 4) { - zmemcpy_4(out, from); - out += 4; - from += 4; - len -= 4; - } - if (len >= 2) { - zmemcpy_2(out, from); - out += 2; - from += 2; - len -= 2; - } - if (len == 1) { - *out++ = *from++; - } - return out; -} - /* Perform short copies until distance can be rewritten as being at least sizeof chunk_t. @@ -112,66 +67,80 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { Assert(len >= sizeof(uint64_t), "chunkmemset should be called on larger chunks"); */ Assert(dist > 0, "chunkmemset cannot have a distance 0"); - unsigned char *from = out - dist; - chunk_t chunk; - unsigned sz = sizeof(chunk); - if (len < sz) { - while (len != 0) { - *out++ = *from++; - --len; - } - return out; - } + uint8_t *from = out - dist; -#ifdef HAVE_CHUNKMEMSET_1 if (dist == 1) { - chunkmemset_1(from, &chunk); - } else -#endif + memset(out, *from, len); + return out + len; + } else if (dist > sizeof(chunk_t)) { + return CHUNKCOPY(out, out - dist, len); + } + + chunk_t chunk_load; + uint32_t chunk_mod = 0; + + /* TODO: possibly build up a permutation table for this if not an even modulus */ #ifdef HAVE_CHUNKMEMSET_2 if (dist == 2) { - chunkmemset_2(from, &chunk); + chunkmemset_2(from, &chunk_load); } else #endif #ifdef HAVE_CHUNKMEMSET_4 if (dist == 4) { - chunkmemset_4(from, &chunk); + chunkmemset_4(from, &chunk_load); } else #endif #ifdef HAVE_CHUNKMEMSET_8 if (dist == 8) { - chunkmemset_8(from, &chunk); + chunkmemset_8(from, &chunk_load); + } else if (dist == sizeof(chunk_t)) { + loadchunk(from, &chunk_load); } else #endif - if (dist == sz) { - loadchunk(from, &chunk); - } else if (dist < sz) { - unsigned char *end = out + len - 1; - while (len > dist) { - out = CHUNKCOPY_SAFE(out, from, dist, end); - len -= dist; + { + /* This code takes string of length dist from "from" and repeats + * it for as many times as can fit in a chunk_t (vector register) */ + int32_t cpy_dist; + int32_t bytes_remaining = sizeof(chunk_t); + uint8_t *cur_chunk = (uint8_t*)&chunk_load; + while (bytes_remaining) { + cpy_dist = MIN(dist, bytes_remaining); + memcpy(cur_chunk, from, cpy_dist); + bytes_remaining -= cpy_dist; + cur_chunk += cpy_dist; + /* This allows us to bypass an expensive integer division since we're effectively + * counting in this loop, anyway. However, we may have to derive a similarly + * sensible solution for if we use a permutation table that allows us to construct + * this vector in one load and one permute instruction */ + chunk_mod = cpy_dist; } - if (len > 0) { - out = CHUNKCOPY_SAFE(out, from, len, end); + } + + /* If we're lucky enough and dist happens to be an even modulus of our vector length, + * we can do two stores per loop iteration, which for most ISAs, especially x86, is beneficial */ + if (chunk_mod == 0) { + while (len >= (2 * sizeof(chunk_t))) { + storechunk(out, &chunk_load); + storechunk(out + sizeof(chunk_t), &chunk_load); + out += 2 * sizeof(chunk_t); + len -= 2 * sizeof(chunk_t); } - return out; - } else { - out = CHUNKUNROLL(out, &dist, &len); - return CHUNKCOPY(out, out - dist, len); } - unsigned rem = len % sz; - len -= rem; - while (len) { - storechunk(out, &chunk); - out += sz; - len -= sz; + /* If we don't have a "dist" length that divides evenly into a vector + * register, we can write the whole vector register but we need only + * advance by the amount of the whole string that fits in our chunk_t. + * If we do divide evenly into the vector length, adv_amount = chunk_t size*/ + uint32_t adv_amount = sizeof(chunk_t) - chunk_mod; + while (len >= sizeof(chunk_t)) { + storechunk(out, &chunk_load); + len -= adv_amount; + out += adv_amount; } - /* Last, deal with the case when LEN is not a multiple of SZ. */ - if (rem) { - memcpy(out, from, rem); - out += rem; + if (len) { + memcpy(out, &chunk_load, len); + out += len; } return out; diff --git a/functable.c b/functable.c index 5147d3f8d9..f39db29554 100644 --- a/functable.c +++ b/functable.c @@ -273,32 +273,6 @@ Z_INTERNAL uint8_t* chunkcopy_stub(uint8_t *out, uint8_t const *from, unsigned l return functable.chunkcopy(out, from, len); } -Z_INTERNAL uint8_t* chunkcopy_safe_stub(uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe) { - // Initialize default - functable.chunkcopy_safe = &chunkcopy_safe_c; - -#ifdef X86_SSE2_CHUNKSET -# if !defined(__x86_64__) && !defined(_M_X64) && !defined(X86_NOCHECK_SSE2) - if (x86_cpu_has_sse2) -# endif - functable.chunkcopy_safe = &chunkcopy_safe_sse2; -#endif -#ifdef X86_AVX_CHUNKSET - if (x86_cpu_has_avx2) - functable.chunkcopy_safe = &chunkcopy_safe_avx; -#endif -#ifdef ARM_NEON_CHUNKSET - if (arm_cpu_has_neon) - functable.chunkcopy_safe = &chunkcopy_safe_neon; -#endif -#ifdef POWER8_VSX_CHUNKSET - if (power_cpu_has_arch_2_07) - functable.chunkcopy_safe = &chunkcopy_safe_power8; -#endif - - return functable.chunkcopy_safe(out, from, len, safe); -} - Z_INTERNAL uint8_t* chunkunroll_stub(uint8_t *out, unsigned *dist, unsigned *len) { // Initialize default functable.chunkunroll = &chunkunroll_c; @@ -436,7 +410,6 @@ Z_INTERNAL Z_TLS struct functable_s functable = { compare256_stub, chunksize_stub, chunkcopy_stub, - chunkcopy_safe_stub, chunkunroll_stub, chunkmemset_stub, chunkmemset_safe_stub, diff --git a/functable.h b/functable.h index 949c5b1be8..a106c93aab 100644 --- a/functable.h +++ b/functable.h @@ -18,7 +18,6 @@ struct functable_s { uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* chunksize) (void); uint8_t* (* chunkcopy) (uint8_t *out, uint8_t const *from, unsigned len); - uint8_t* (* chunkcopy_safe) (uint8_t *out, uint8_t const *from, unsigned len, uint8_t *safe); uint8_t* (* chunkunroll) (uint8_t *out, unsigned *dist, unsigned *len); uint8_t* (* chunkmemset) (uint8_t *out, unsigned dist, unsigned len); uint8_t* (* chunkmemset_safe) (uint8_t *out, unsigned dist, unsigned len, unsigned left); diff --git a/inffast.c b/inffast.c index 58cbad7ef9..e0fb99c593 100644 --- a/inffast.c +++ b/inffast.c @@ -11,7 +11,6 @@ #include "inflate_p.h" #include "functable.h" - /* Load 64 bits from IN and place the bytes at offset BITS in the result. */ static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { uint64_t chunk; @@ -430,7 +429,7 @@ void Z_INTERNAL zng_inflate_fast_back(PREFIX3(stream) *strm, unsigned long start from += wsize - op; if (op < len) { /* some from end of window */ len -= op; - out = functable.chunkcopy_safe(out, from, op, safe); + out = chunkcopy_safe(out, from, op, safe); from = window; /* more from start of window */ op = wnext; /* This (rare) case can create a situation where @@ -440,16 +439,16 @@ void Z_INTERNAL zng_inflate_fast_back(PREFIX3(stream) *strm, unsigned long start } if (op < len) { /* still need some from output */ len -= op; - out = functable.chunkcopy_safe(out, from, op, safe); + out = chunkcopy_safe(out, from, op, safe); out = functable.chunkunroll(out, &dist, &len); - out = functable.chunkcopy_safe(out, out - dist, len, safe); + out = chunkcopy_safe(out, out - dist, len, safe); } else { - out = functable.chunkcopy_safe(out, from, len, safe); + out = chunkcopy_safe(out, from, len, safe); } } else if (extra_safe) { /* Whole reference is in range of current output. */ if (dist >= len || dist >= state->chunksize) - out = functable.chunkcopy_safe(out, out - dist, len, safe); + out = chunkcopy_safe(out, out - dist, len, safe); else out = functable.chunkmemset_safe(out, dist, len, (unsigned)((safe - out) + 1)); } else { diff --git a/inflate.c b/inflate.c index 06b37bf40c..5e2af29c6c 100644 --- a/inflate.c +++ b/inflate.c @@ -887,7 +887,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { } unsigned char *next_out = state->window + state->wsize + state->wnext; if (copy <= state->offset) { - functable.chunkcopy_safe(next_out, next_out - state->offset, copy, put + buf_left); + chunkcopy_safe(next_out, next_out - state->offset, copy, put + buf_left); } else { /* copy from output */ functable.chunkmemset_safe(next_out, state->offset, copy, (uint32_t)buf_left); } diff --git a/inflate_p.h b/inflate_p.h index c5ba13a0c6..86e3702b86 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -211,3 +211,78 @@ static inline void window_output_flush(PREFIX3(stream) *strm) { state->whave += out_bytes; state->whave = MIN(state->whave, state->wsize); } + +/* Behave like chunkcopy, but avoid writing beyond of legal output. */ +static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, unsigned len, uint8_t *safe) { + uint32_t safelen = (uint32_t)((safe - out) + 1); + len = MIN(len, safelen); + int olap_src = from >= out && from < out + len; + int olap_dst = out >= from && out < from + len; + int tocopy; + + /* For all cases without overlap, memcpy is ideal */ + if (!(olap_src || olap_dst)) { + memcpy(out, from, len); + return out + len; + } + + /* We are emulating a self-modifying copy loop here. To do this in a way that doesn't produce undefined behavior, + * we have to get a bit clever. First if the overlap is such that src falls between dst and dst+len, we can do the + * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest + * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look + * behind or lookahead distance */ + int non_olap_size = (from > out) ? from - out : out - from; + + memcpy(out, from, non_olap_size); + out += non_olap_size; + from += non_olap_size; + len -= non_olap_size; + + /* So this doesn't give use a worst case scenario of function calls in a loop, + * we want to instead break this down into copy blocks of fixed lengths */ + while (len) { + tocopy = MIN(non_olap_size, len); + len -= tocopy; + + while (tocopy >= 32) { + memcpy(out, from, 32); + out += 32; + from += 32; + tocopy -= 32; + } + + if (tocopy >= 16) { + memcpy(out, from, 16); + out += 16; + from += 16; + tocopy -= 16; + } + + if (tocopy >= 8) { + zmemcpy_8(out, from); + out += 8; + from += 8; + tocopy -= 8; + } + + if (tocopy >= 4) { + zmemcpy_4(out, from); + out += 4; + from += 4; + tocopy -= 4; + } + + if (tocopy >= 2) { + zmemcpy_2(out, from); + out += 2; + from += 2; + tocopy -= 2; + } + + if (tocopy) { + *out++ = *from++; + } + } + + return out; +} From 1f2743ce0d9c83dfef9096438df251860a810709 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 23 Feb 2022 12:07:01 -0800 Subject: [PATCH 303/798] Fixed wrong error name when calling inflate in minideflate. --- test/minideflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/minideflate.c b/test/minideflate.c index 2ea280f21a..3f687877a4 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -167,7 +167,7 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ do { err = PREFIX(inflate)(&d_stream, flush); if (err == Z_STREAM_END) break; - CHECK_ERR(err, "deflate"); + CHECK_ERR(err, "inflate"); if (d_stream.next_out == write_buf + write_buf_size) { fwrite(write_buf, 1, write_buf_size, fout); From 74c744812695a899cad75b8991d1c55b0820bef7 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 27 Feb 2022 10:06:13 -0800 Subject: [PATCH 304/798] Updated help usage with correct values for window_bits. --- test/minideflate.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/minideflate.c b/test/minideflate.c index 3f687877a4..68e9907dc0 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -214,7 +214,10 @@ void show_help(void) { " -R : compress with Z_RLE\n" \ " -F : compress with Z_FIXED\n" \ " -m : memory level (1 to 8)\n" \ - " -w : window bits (8 to 15 for gzip, -8 to -15 for zlib)\n" \ + " -w : window bits..\n" \ + " : -1 to -15 for raw deflate\n" + " : 0 to 15 for deflate (adler32)\n" + " : 16 to 31 for gzip (crc32)\n" " -s : flush type (0 to 5)\n" \ " -r : read buffer size\n" \ " -t : write buffer size\n" \ From 81d7f95413330827edd3b6983b64a160752f8ea8 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 28 Feb 2022 09:00:26 -0800 Subject: [PATCH 305/798] Auto-detect wrapper when inflating and no window_bits specified. --- test/minideflate.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/minideflate.c b/test/minideflate.c index 68e9907dc0..7ee07e6d40 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -227,7 +227,7 @@ void show_help(void) { int main(int argc, char **argv) { int32_t i; int32_t mem_level = DEF_MEM_LEVEL; - int32_t window_bits = MAX_WBITS; + int32_t window_bits = INT32_MAX; int32_t strategy = Z_DEFAULT_STRATEGY; int32_t level = Z_DEFAULT_COMPRESSION; int32_t read_buf_size = 4096; @@ -274,6 +274,14 @@ int main(int argc, char **argv) { SET_BINARY_MODE(stdin); SET_BINARY_MODE(stdout); + + if (window_bits == INT32_MAX) { + window_bits = MAX_WBITS; + /* Auto-detect wrapper for inflateInit */ + if (uncompr) + window_bits += 32; + } + if (i != argc) { fin = fopen(argv[i], "rb+"); if (fin == NULL) { From 4bb56176ffe97c47dac797c9aeb62011ab153687 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 10 Mar 2022 08:53:44 -0800 Subject: [PATCH 306/798] Include zutil.h for definition of DEF_MEM_LEVEL. --- test/minideflate.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index 7ee07e6d40..47c58a55bd 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -7,11 +7,7 @@ #include #include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif +#include "zutil.h" #if defined(_WIN32) || defined(__CYGWIN__) # include @@ -21,12 +17,6 @@ # define SET_BINARY_MODE(file) #endif -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif - #define CHECK_ERR(err, msg) { \ if (err != Z_OK) { \ fprintf(stderr, "%s error: %d\n", msg, err); \ From d09a640816b5152b8dfc769834a183223c3c7841 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 10 Mar 2022 08:57:13 -0800 Subject: [PATCH 307/798] Use large default buffer size for minideflate to match minigzip use of GZBUFSIZE. --- test/minideflate.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index 47c58a55bd..b2144f18cd 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -24,6 +24,9 @@ } \ } +/* Default read/write i/o buffer size based on GZBUFSIZE */ +#define BUFSIZE 131072 + /* =========================================================================== * deflate() using specialized parameters */ @@ -220,8 +223,8 @@ int main(int argc, char **argv) { int32_t window_bits = INT32_MAX; int32_t strategy = Z_DEFAULT_STRATEGY; int32_t level = Z_DEFAULT_COMPRESSION; - int32_t read_buf_size = 4096; - int32_t write_buf_size = 4096; + int32_t read_buf_size = BUFSIZE; + int32_t write_buf_size = BUFSIZE; int32_t flush = Z_NO_FLUSH; uint8_t copyout = 0; uint8_t uncompr = 0; From 5dc1b61ec395ea0a4b2266c69096a38743d1c94b Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 11 Mar 2022 14:53:47 -0800 Subject: [PATCH 308/798] Added support for -k keep argument to minideflate. By default minideflate will now delete the input file. --- test/minideflate.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/minideflate.c b/test/minideflate.c index b2144f18cd..0352622e9c 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -199,9 +199,10 @@ void inflate_params(FILE *fin, FILE *fout, int32_t read_buf_size, int32_t write_ } void show_help(void) { - printf("Usage: minideflate [-c] [-f|-h|-R|-F] [-m level] [-r/-t size] [-s flush] [-w bits] [-0 to -9] [input file]\n\n" \ + printf("Usage: minideflate [-c][-d][-k] [-f|-h|-R|-F] [-m level] [-r/-t size] [-s flush] [-w bits] [-0 to -9] [input file]\n\n" \ " -c : write to standard output\n" \ " -d : decompress\n" \ + " -k : keep input file\n" \ " -f : compress with Z_FILTERED\n" \ " -h : compress with Z_HUFFMAN_ONLY\n" \ " -R : compress with Z_RLE\n" \ @@ -228,6 +229,7 @@ int main(int argc, char **argv) { int32_t flush = Z_NO_FLUSH; uint8_t copyout = 0; uint8_t uncompr = 0; + uint8_t keep = 0; char out_file[320]; FILE *fin = stdin; FILE *fout = stdout; @@ -247,6 +249,8 @@ int main(int argc, char **argv) { copyout = 1; else if (strcmp(argv[i], "-d") == 0) uncompr = 1; + else if (strcmp(argv[i], "-k") == 0) + keep = 1; else if (strcmp(argv[i], "-f") == 0) strategy = Z_FILTERED; else if (strcmp(argv[i], "-h") == 0) @@ -299,6 +303,9 @@ int main(int argc, char **argv) { if (fin != stdin) { fclose(fin); + if (!keep) { + unlink(argv[i]); + } } if (fout != stdout) { fclose(fout); From b991b3e1f70031478d5c2af8a4fc97c79848b79a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 11 Mar 2022 15:31:57 -0800 Subject: [PATCH 309/798] Append extension to output file path based on window_bits when compressing and remove extension from output file path when decompressing. --- test/minideflate.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index 0352622e9c..07ab2bd407 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -230,7 +230,6 @@ int main(int argc, char **argv) { uint8_t copyout = 0; uint8_t uncompr = 0; uint8_t keep = 0; - char out_file[320]; FILE *fin = stdin; FILE *fout = stdout; @@ -286,12 +285,31 @@ int main(int argc, char **argv) { exit(1); } if (!copyout) { - snprintf(out_file, sizeof(out_file), "%s%s", argv[i], (window_bits < 0) ? ".zz" : ".gz"); + char *out_file = (char *)calloc(1, strlen(argv[i]) + 6); + if (out_file == NULL) { + fprintf(stderr, "Not enough memory\n"); + exit(1); + } + strcat(out_file, argv[i]); + if (!uncompr) { + if (window_bits < 0) { + strcat(out_file, ".zraw"); + } else if (window_bits > MAX_WBITS) { + strcat(out_file, ".gz"); + } else { + strcat(out_file, ".z"); + } + } else { + char *out_ext = strrchr(out_file, '.'); + if (out_ext != NULL) + *out_ext = 0; + } fout = fopen(out_file, "wb"); if (fout == NULL) { fprintf(stderr, "Failed to open file: %s\n", out_file); exit(1); } + free(out_file); } } From 693f1eb819c536a083a2622f5741b5e93abe7d6a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 11 Mar 2022 15:42:14 -0800 Subject: [PATCH 310/798] Print help when no arguments supplied to minideflate. --- test/minideflate.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/minideflate.c b/test/minideflate.c index 07ab2bd407..e1295afc89 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -233,6 +233,12 @@ int main(int argc, char **argv) { FILE *fin = stdin; FILE *fout = stdout; + + if (argc == 1) { + show_help(); + return 64; /* EX_USAGE */ + } + for (i = 1; i < argc; i++) { if ((strcmp(argv[i], "-m") == 0) && (i + 1 < argc)) mem_level = atoi(argv[++i]); @@ -313,6 +319,13 @@ int main(int argc, char **argv) { } } + if (window_bits == INT32_MAX) { + window_bits = MAX_WBITS; + /* Auto-detect wrapper for inflateInit */ + if (uncompr) + window_bits += 32; + } + if (uncompr) { inflate_params(fin, fout, read_buf_size, write_buf_size, window_bits, flush); } else { From 063484eb629716b27a226a1b5bc5ba2eb6adf14f Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 11 Mar 2022 15:45:06 -0800 Subject: [PATCH 311/798] Throw an error when input is raw deflate stream but window_bits is not supplied. --- test/minideflate.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/test/minideflate.c b/test/minideflate.c index e1295afc89..d4d8423a9f 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -12,8 +12,13 @@ #if defined(_WIN32) || defined(__CYGWIN__) # include # include +# include # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +# ifdef _MSC_VER +# define strcasecmp _stricmp +# endif #else +# include # define SET_BINARY_MODE(file) #endif @@ -277,13 +282,6 @@ int main(int argc, char **argv) { SET_BINARY_MODE(stdin); SET_BINARY_MODE(stdout); - if (window_bits == INT32_MAX) { - window_bits = MAX_WBITS; - /* Auto-detect wrapper for inflateInit */ - if (uncompr) - window_bits += 32; - } - if (i != argc) { fin = fopen(argv[i], "rb+"); if (fin == NULL) { @@ -307,8 +305,13 @@ int main(int argc, char **argv) { } } else { char *out_ext = strrchr(out_file, '.'); - if (out_ext != NULL) + if (out_ext != NULL) { + if (strcasecmp(out_ext, ".zraw") == 0 && window_bits == INT32_MAX) { + fprintf(stderr, "Must specify window bits for raw deflate stream\n"); + exit(1); + } *out_ext = 0; + } } fout = fopen(out_file, "wb"); if (fout == NULL) { @@ -318,6 +321,13 @@ int main(int argc, char **argv) { free(out_file); } } + + if (window_bits == INT32_MAX) { + window_bits = MAX_WBITS; + /* Auto-detect wrapper for inflateInit */ + if (uncompr) + window_bits += 32; + } if (window_bits == INT32_MAX) { window_bits = MAX_WBITS; From db3feb4cf2de73a84039e90c89f0c0b393e620bc Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Sun, 13 Mar 2022 17:12:42 +0200 Subject: [PATCH 312/798] Allow bypassing runtime feature check of TZCNT instructions. * This avoids conditional branch when it's known at build time that TZCNT instructions are always supported --- CMakeLists.txt | 5 +++++ README.md | 1 + configure | 8 ++++++++ fallback_builtins.h | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 440a716968..60ccbe25bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,7 @@ elseif(BASEARCH_S360_FOUND) option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF) option(WITH_CRC32_VX "Build with vectorized CRC32 on IBM Z" ON) elseif(BASEARCH_X86_FOUND) + option(FORCE_TZCNT "Always assume CPU is TZCNT capable" OFF) option(WITH_AVX2 "Build with AVX2" ON) option(WITH_AVX512 "Build with AVX512" ON) option(WITH_AVX512VNNI "Build with AVX512 VNNI extensions" ON) @@ -792,6 +793,10 @@ if(WITH_OPTIM) set(WITH_SSE4 OFF) endif() endif() + if(FORCE_TZCNT) + add_definitions(-DX86_NOCHECK_TZCNT) + endif() + add_feature_info(FORCE_TZCNT FORCE_TZCNT "Assume CPU is TZCNT capable") if(WITH_SSE2) check_sse2_intrinsics() if(HAVE_SSE2_INTRIN) diff --git a/README.md b/README.md index 3c4fd00b64..668c29cbb0 100644 --- a/README.md +++ b/README.md @@ -196,6 +196,7 @@ Advanced Build Options | ZLIB_DUAL_LINK | | Dual link tests with system zlib | OFF | | UNALIGNED_OK | | Allow unaligned reads | ON (x86, arm) | | | --force-sse2 | Skip runtime check for SSE2 instructions (Always on for x86_64) | OFF (x86) | +| FORCE_TZCNT | --force-tzcnt | Skip runtime check for TZCNT instructions | OFF | | WITH_AVX2 | | Build with AVX2 intrinsics | ON | | WITH_AVX512 | | Build with AVX512 intrinsics | ON | | WITH_AVX512VNNI | | Build with AVX512VNNI intrinsics | ON | diff --git a/configure b/configure index 149ae732a3..bd237236d6 100755 --- a/configure +++ b/configure @@ -103,6 +103,7 @@ with_fuzzers=0 floatabi= native=0 forcesse2=0 +forcetzcnt=0 # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal # instruction scheduling unless you specify a reasonable -mtune= target avx512flag="-mavx512f -mavx512dq -mavx512bw -mavx512vl -mtune=cascadelake" @@ -173,6 +174,7 @@ case "$1" in echo ' [--without-crc32-vx] Build without vectorized CRC32 on IBM Z' | tee -a configure.log echo ' [--with-reduced-mem] Reduced memory usage for special cases (reduces performance)' | tee -a configure.log echo ' [--force-sse2] Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log + echo ' [--force-tzcnt] Assume TZCNT instructions are always available (disabled by default)' | tee -a configure.log echo ' [--with-sanitizer] Build with sanitizer (memory, address, undefined)' | tee -a configure.log echo ' [--with-fuzzers] Build test/fuzz (disabled by default)' | tee -a configure.log echo ' [--native] Compiles with full instruction set supported on this host' | tee -a configure.log @@ -206,6 +208,7 @@ case "$1" in --without-crc32-vx) buildcrc32vx=0; shift ;; --with-reduced-mem) reducedmem=1; shift ;; --force-sse2) forcesse2=1; shift ;; + --force-tzcnt) forcetzcnt=1; shift ;; -n | --native) native=1; shift ;; -a*=* | --archs=*) ARCHS=$(echo $1 | sed 's/.*=//'); shift ;; --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; @@ -1589,6 +1592,11 @@ case "${ARCH}" in fi fi fi + + if test $forcetzcnt -eq 1; then + CFLAGS="${CFLAGS} -DX86_NOCHECK_TZCNT" + SFLAGS="${SFLAGS} -DX86_NOCHECK_TZCNT" + fi fi ;; diff --git a/fallback_builtins.h b/fallback_builtins.h index 8abec2fad7..c9fcceac3b 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -14,7 +14,9 @@ */ static __forceinline unsigned long __builtin_ctz(uint32_t value) { #ifdef X86_FEATURES +# ifndef X86_NOCHECK_TZCNT if (x86_cpu_has_tzcnt) +# endif return _tzcnt_u32(value); #endif unsigned long trailing_zero; @@ -29,7 +31,9 @@ static __forceinline unsigned long __builtin_ctz(uint32_t value) { */ static __forceinline unsigned long long __builtin_ctzll(uint64_t value) { #ifdef X86_FEATURES +# ifndef X86_NOCHECK_TZCNT if (x86_cpu_has_tzcnt) +# endif return _tzcnt_u64(value); #endif unsigned long trailing_zero; From 15e5df63a597ffa9731f8a2f4a1a3e6be6a5a50e Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Mon, 14 Mar 2022 20:02:01 +0200 Subject: [PATCH 313/798] [README] Add missing FORCE_SSE2 for CMake. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 668c29cbb0..0a801a7ec5 100644 --- a/README.md +++ b/README.md @@ -195,7 +195,7 @@ Advanced Build Options |:--------------------------------|:----------------------|:--------------------------------------------------------------------|------------------------| | ZLIB_DUAL_LINK | | Dual link tests with system zlib | OFF | | UNALIGNED_OK | | Allow unaligned reads | ON (x86, arm) | -| | --force-sse2 | Skip runtime check for SSE2 instructions (Always on for x86_64) | OFF (x86) | +| FORCE_SSE2 | --force-sse2 | Skip runtime check for SSE2 instructions (Always on for x86_64) | OFF (x86) | | FORCE_TZCNT | --force-tzcnt | Skip runtime check for TZCNT instructions | OFF | | WITH_AVX2 | | Build with AVX2 intrinsics | ON | | WITH_AVX512 | | Build with AVX512 intrinsics | ON | From 5db8d3cf13c9294a41cb68b0a6becb899f54e562 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 15 Mar 2022 17:19:58 +0200 Subject: [PATCH 314/798] Don't use -mtune with ClangCl. --- cmake/detect-intrinsics.cmake | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index c4231c26ac..9a4e54c3dc 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -34,7 +34,10 @@ macro(check_avx512_intrinsics) if(NOT NATIVEFLAG) # For CPUs that can benefit from AVX512, it seems GCC generates suboptimal # instruction scheduling unless you specify a reasonable -mtune= target - set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mtune=cascadelake") + set(AVX512FLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl") + if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "ClangCl") + set(AVX512FLAG "${AVX512FLAG} -mtune=cascadelake") + endif() endif() elseif(MSVC) set(AVX512FLAG "/ARCH:AVX512") @@ -79,7 +82,10 @@ macro(check_avx512vnni_intrinsics) endif() elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) - set(AVX512VNNIFLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx512vnni -mtune=cascadelake") + set(AVX512VNNIFLAG "-mavx512f -mavx512dq -mavx512bw -mavx512vl -mavx512vnni") + if(NOT CMAKE_GENERATOR_TOOLSET MATCHES "ClangCl") + set(AVX512VNNIFLAG "${AVX512VNNIFLAG} -mtune=cascadelake") + endif() endif() elseif(MSVC) set(AVX512VNNIFLAG "/ARCH:AVX512") From 276a3ec3b3d9096b408726ff0da04d70cfe1f6f3 Mon Sep 17 00:00:00 2001 From: "Mika T. Lindqvist" Date: Tue, 15 Mar 2022 18:33:17 +0200 Subject: [PATCH 315/798] Explicitly install dependencies for wine32. * Allow downgrading packages to resolve conflicts --- .github/workflows/cmake.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 3b6ac22206..b37c84d351 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -259,7 +259,7 @@ jobs: - name: Ubuntu MinGW i686 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake - packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 + packages: wine32 gcc-mingw-w64-i686 g++-mingw-w64-i686 libpcre2-8-0=10.34-7 libpcre2-8-0:i386=10.34-7 libodbc1=2.3.6-0.1build1 libodbc1:i386=2.3.6-0.1build1 ldflags: -static codecov: ubuntu_gcc_mingw_i686 # Limit parallel test jobs to prevent wine errors @@ -417,13 +417,12 @@ jobs: if: contains(matrix.packages, 'wine') run: | sudo dpkg --add-architecture i386 - sudo apt-add-repository ppa:ondrej/php -y - name: Install packages (Ubuntu) if: runner.os == 'Linux' && matrix.packages run: | sudo apt-get update - sudo apt-get install -y ${{ matrix.packages }} + sudo apt-get install -y --allow-downgrades ${{ matrix.packages }} - name: Install packages (Windows) if: runner.os == 'Windows' From e38c493337d751f36cdb5fd33a2bc54326a60963 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 17 Jan 2022 18:47:23 -0800 Subject: [PATCH 316/798] Move UNALIGNED_OK detection to compile time instead of configure time. --- .github/workflows/cmake.yml | 7 +++--- CMakeLists.txt | 44 ------------------------------------- README.md | 2 -- arch/x86/compare256_avx2.c | 2 +- compare256.c | 4 ++-- configure | 20 ----------------- win32/Makefile.a64 | 2 -- win32/Makefile.arm | 1 - win32/Makefile.msc | 2 -- zbuild.h | 22 +++++++++++++++++++ 10 files changed, 28 insertions(+), 78 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index b37c84d351..5fdc38a185 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -41,21 +41,20 @@ jobs: cmake-args: -DZLIB_COMPAT=ON -DZLIB_SYMBOL_PREFIX=zTest_ codecov: ubuntu_gcc_compat_sprefix - - name: Ubuntu GCC OSB -O1 No Unaligned64 UBSAN + - name: Ubuntu GCC OSB -O1 UBSAN os: ubuntu-latest compiler: gcc cxx-compiler: g++ - cmake-args: -DWITH_UNALIGNED=ON -DUNALIGNED64_OK=OFF -DWITH_SANITIZER=Undefined + cmake-args: -DWITH_SANITIZER=Undefined build-dir: ../build build-src-dir: ../zlib-ng codecov: ubuntu_gcc_osb cflags: -O1 -g3 - - name: Ubuntu GCC -O3 No Unaligned + - name: Ubuntu GCC -O3 os: ubuntu-latest compiler: gcc cxx-compiler: g++ - cmake-args: -DWITH_UNALIGNED=OFF codecov: ubuntu_gcc_o3 cflags: -O3 diff --git a/CMakeLists.txt b/CMakeLists.txt index 60ccbe25bd..c41428c74f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,7 +87,6 @@ option(WITH_MAINTAINER_WARNINGS "Build with project maintainer warnings" OFF) option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF) option(WITH_INFLATE_STRICT "Build with strict inflate distance checking" OFF) option(WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances" OFF) -option(WITH_UNALIGNED "Support unaligned reads on platforms that support it" ON) set(ZLIB_SYMBOL_PREFIX "" CACHE STRING "Give this prefix to all publicly exported symbols. Useful when embedding into a larger library. @@ -138,7 +137,6 @@ mark_as_advanced(FORCE WITH_POWER8 WITH_INFLATE_STRICT WITH_INFLATE_ALLOW_INVALID_DIST - WITH_UNALIGNED INSTALL_UTILS ) @@ -249,46 +247,6 @@ else() endif() endif() -# Set architecture alignment requirements -if(WITH_UNALIGNED) - if((BASEARCH_ARM_FOUND AND NOT "${ARCH}" MATCHES "armv[2-7]") OR (BASEARCH_PPC_FOUND AND "${ARCH}" MATCHES "powerpc64le") OR BASEARCH_X86_FOUND) - if(NOT DEFINED UNALIGNED_OK) - set(UNALIGNED_OK TRUE) - endif() - endif() - if(UNALIGNED_OK) - add_definitions(-DUNALIGNED_OK) - message(STATUS "Architecture supports unaligned reads") - endif() - if(BASEARCH_ARM_FOUND) - if(NOT DEFINED UNALIGNED64_OK) - if("${ARCH}" MATCHES "armv[2-7]") - set(UNALIGNED64_OK FALSE) - elseif("${ARCH}" MATCHES "(arm(v[8-9])?|aarch64)") - set(UNALIGNED64_OK TRUE) - endif() - endif() - endif() - if(BASEARCH_PPC_FOUND) - if(NOT DEFINED UNALIGNED64_OK) - if("${ARCH}" MATCHES "powerpc64le") - set(UNALIGNED64_OK TRUE) - endif() - endif() - endif() - if(BASEARCH_X86_FOUND) - if(NOT DEFINED UNALIGNED64_OK) - set(UNALIGNED64_OK TRUE) - endif() - endif() - if(UNALIGNED64_OK) - add_definitions(-DUNALIGNED64_OK) - message(STATUS "Architecture supports unaligned reads of > 4 bytes") - endif() -else() - message(STATUS "Unaligned reads manually disabled") -endif() - # Apply warning compiler flags if(WITH_MAINTAINER_WARNINGS) add_compile_options(${WARNFLAGS} ${WARNFLAGS_MAINTAINER} ${WARNFLAGS_DISABLE}) @@ -1459,8 +1417,6 @@ add_feature_info(WITH_MAINTAINER_WARNINGS WITH_MAINTAINER_WARNINGS "Build with p add_feature_info(WITH_CODE_COVERAGE WITH_CODE_COVERAGE "Enable code coverage reporting") add_feature_info(WITH_INFLATE_STRICT WITH_INFLATE_STRICT "Build with strict inflate distance checking") add_feature_info(WITH_INFLATE_ALLOW_INVALID_DIST WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances") -add_feature_info(WITH_UNALIGNED UNALIGNED_OK "Support unaligned reads on platforms that support it") -add_feature_info(WITH_UNALIGNED64 UNALIGNED64_OK "Support unaligned 64-bit reads on platforms that support it") if(BASEARCH_ARM_FOUND) add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE") diff --git a/README.md b/README.md index 0a801a7ec5..59899ad5c2 100644 --- a/README.md +++ b/README.md @@ -194,7 +194,6 @@ Advanced Build Options | CMake | configure | Description | Default | |:--------------------------------|:----------------------|:--------------------------------------------------------------------|------------------------| | ZLIB_DUAL_LINK | | Dual link tests with system zlib | OFF | -| UNALIGNED_OK | | Allow unaligned reads | ON (x86, arm) | | FORCE_SSE2 | --force-sse2 | Skip runtime check for SSE2 instructions (Always on for x86_64) | OFF (x86) | | FORCE_TZCNT | --force-tzcnt | Skip runtime check for TZCNT instructions | OFF | | WITH_AVX2 | | Build with AVX2 intrinsics | ON | @@ -212,7 +211,6 @@ Advanced Build Options | WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON | | WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF | | WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF | -| WITH_UNALIGNED | | Allow optimizations that use unaligned reads if safe on current arch| ON | | WITH_INFLATE_STRICT | | Build with strict inflate distance checking | OFF | | WITH_INFLATE_ALLOW_INVALID_DIST | | Build with zero fill for inflate invalid distances | OFF | | INSTALL_UTILS | | Copy minigzip and minideflate during install | OFF | diff --git a/arch/x86/compare256_avx2.c b/arch/x86/compare256_avx2.c index 07f57f2839..e25fa93eb9 100644 --- a/arch/x86/compare256_avx2.c +++ b/arch/x86/compare256_avx2.c @@ -14,7 +14,7 @@ # include #endif -/* UNALIGNED_OK, AVX2 intrinsic comparison */ +/* AVX2 unaligned intrinsic comparison */ static inline uint32_t compare256_unaligned_avx2_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; diff --git a/compare256.c b/compare256.c index 1b693f274f..609e6181ae 100644 --- a/compare256.c +++ b/compare256.c @@ -56,7 +56,7 @@ Z_INTERNAL uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1) { #include "match_tpl.h" #ifdef UNALIGNED_OK -/* UNALIGNED_OK, 16-bit integer comparison */ +/* 16-bit unaligned integer comparison */ static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; @@ -94,7 +94,7 @@ Z_INTERNAL uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t * #include "match_tpl.h" #ifdef HAVE_BUILTIN_CTZ -/* UNALIGNED_OK, 32-bit integer comparison */ +/* 32-bit unaligned integer comparison */ static inline uint32_t compare256_unaligned_32_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; diff --git a/configure b/configure index bd237236d6..17bd9fd8b3 100755 --- a/configure +++ b/configure @@ -1481,9 +1481,6 @@ case "${ARCH}" in i386 | i486 | i586 | i686 |x86_64) ARCHDIR=arch/x86 - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - # Enable arch-specific optimizations if test $without_optimizations -eq 0; then CFLAGS="${CFLAGS} -DX86_FEATURES" @@ -1704,9 +1701,6 @@ EOF fi ;; armv6l | armv6hl) - CFLAGS="${CFLAGS} -DUNALIGNED_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK" - if test $without_optimizations -eq 0; then if test $buildacle -eq 1; then echo ACLE support not available @@ -1718,9 +1712,6 @@ EOF fi ;; arm | armv7*) - CFLAGS="${CFLAGS} -DUNALIGNED_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK" - if test $without_optimizations -eq 0; then if test $buildacle -eq 1; then echo ACLE support not available @@ -1745,9 +1736,6 @@ EOF fi ;; armv8-a | armv8-a+simd) - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - if test $without_optimizations -eq 0; then if test $buildacle -eq 1; then echo ACLE support not available @@ -1772,9 +1760,6 @@ EOF fi ;; armv8-a+crc | armv8-a+crc+simd | armv8.[1234]-a | armv8.[1234]-a+simd) - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - acleflag="-march=${ARCH}" if test $without_optimizations -eq 0; then @@ -1869,9 +1854,6 @@ EOF neonflag="-march=${ARCH}" acleflag="-march=${ARCH}" - - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" ;; powerpc*) case "${ARCH}" in @@ -1883,8 +1865,6 @@ EOF ;; powerpc64le) [ ! -z $CROSS_PREFIX ] && QEMU_ARCH=ppc64le - CFLAGS="${CFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" - SFLAGS="${SFLAGS} -DUNALIGNED_OK -DUNALIGNED64_OK" ;; esac diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 4df6f3d080..29e66ceed1 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -30,8 +30,6 @@ WFLAGS = \ -D_CRT_NONSTDC_NO_DEPRECATE \ -DARM_NEON_HASLD4 \ -DARM_FEATURES \ - -DUNALIGNED_OK \ - -DUNALIGNED64_OK \ # LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest ARFLAGS = -nologo diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 4cc902888d..a43dc59b1c 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -30,7 +30,6 @@ WFLAGS = \ -D_CRT_NONSTDC_NO_DEPRECATE \ -DARM_FEATURES \ -DARM_NEON_HASLD4 \ - -DUNALIGNED_OK \ # LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest ARFLAGS = -nologo diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 3d8f1b2e3e..9caa8211c8 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -35,8 +35,6 @@ WFLAGS = \ -DX86_AVX2 \ -DX86_AVX_CHUNKSET \ -DX86_SSE2_CHUNKSET \ - -DUNALIGNED_OK \ - -DUNALIGNED64_OK \ # LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest ARFLAGS = -nologo diff --git a/zbuild.h b/zbuild.h index 08bc7ef612..20e3e20e34 100644 --- a/zbuild.h +++ b/zbuild.h @@ -194,6 +194,28 @@ # define Tracecv(c, x) #endif +#if defined(__x86_64__) || defined(_M_X64) || defined(__amd64__) || defined(_M_AMD64) +# define UNALIGNED_OK +# define UNALIGNED64_OK +#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(_X86_) || defined(_M_IX86) +# define UNALIGNED_OK +#elif defined(__aarch64__) || defined(_M_ARM64) +# if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) +# define UNALIGNED_OK +# define UNALIGNED64_OK +# endif +#elif defined(__arm__) || (_M_ARM >= 7) +# if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) +# define UNALIGNED_OK +# endif +#elif defined(__powerpc64__) || defined(__ppc64__) +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define UNALIGNED_OK +# define UNALIGNED64_OK +# endif +#endif + /* Force compiler to emit unaligned memory accesses if unaligned access is supported on the architecture, otherwise don't assume unaligned access is supported. Older compilers don't optimize memcpy and memcmp calls to unaligned access instructions From c78c835a4981ff2305ff79d6c05fe0e2c22c8dc2 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 14 Mar 2022 18:30:51 -0700 Subject: [PATCH 317/798] Make unaligned access being disabled configurable via build scripts. --- .github/workflows/cmake.yml | 3 ++- CMakeLists.txt | 8 ++++++++ README.md | 1 + configure | 12 +++++++++++- zbuild.h | 34 ++++++++++++++++++---------------- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 5fdc38a185..a4d05f35e5 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -51,10 +51,11 @@ jobs: codecov: ubuntu_gcc_osb cflags: -O1 -g3 - - name: Ubuntu GCC -O3 + - name: Ubuntu GCC -O3 No Unaligned os: ubuntu-latest compiler: gcc cxx-compiler: g++ + cmake-args: -DWITH_UNALIGNED=OFF codecov: ubuntu_gcc_o3 cflags: -O3 diff --git a/CMakeLists.txt b/CMakeLists.txt index c41428c74f..e18a39451f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,7 @@ option(WITH_MAINTAINER_WARNINGS "Build with project maintainer warnings" OFF) option(WITH_CODE_COVERAGE "Enable code coverage reporting" OFF) option(WITH_INFLATE_STRICT "Build with strict inflate distance checking" OFF) option(WITH_INFLATE_ALLOW_INVALID_DIST "Build with zero fill for inflate invalid distances" OFF) +option(WITH_UNALIGNED "Support unaligned reads on platforms that support it" ON) set(ZLIB_SYMBOL_PREFIX "" CACHE STRING "Give this prefix to all publicly exported symbols. Useful when embedding into a larger library. @@ -137,6 +138,7 @@ mark_as_advanced(FORCE WITH_POWER8 WITH_INFLATE_STRICT WITH_INFLATE_ALLOW_INVALID_DIST + WITH_UNALIGNED INSTALL_UTILS ) @@ -247,6 +249,12 @@ else() endif() endif() +# Set architecture alignment requirements +if(NOT WITH_UNALIGNED) + add_definitions(-DNO_UNALIGNED) + message(STATUS "Unaligned reads manually disabled") +endif() + # Apply warning compiler flags if(WITH_MAINTAINER_WARNINGS) add_compile_options(${WARNFLAGS} ${WARNFLAGS_MAINTAINER} ${WARNFLAGS_DISABLE}) diff --git a/README.md b/README.md index 59899ad5c2..b0842bc442 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,7 @@ Advanced Build Options | WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON | | WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF | | WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF | +| WITH_UNALIGNED | --without-unaligned | Allow optimizations that use unaligned reads if safe on current arch| ON | | WITH_INFLATE_STRICT | | Build with strict inflate distance checking | OFF | | WITH_INFLATE_ALLOW_INVALID_DIST | | Build with zero fill for inflate invalid distances | OFF | | INSTALL_UTILS | | Copy minigzip and minideflate during install | OFF | diff --git a/configure b/configure index 17bd9fd8b3..35404ce5b1 100755 --- a/configure +++ b/configure @@ -86,6 +86,7 @@ mandir=${mandir-'${prefix}/share/man'} shared_ext='.so' shared=1 gzfileops=1 +unalignedok=1 compat=0 cover=0 build32=0 @@ -162,7 +163,8 @@ case "$1" in echo ' [--warn] Enables extra compiler warnings' | tee -a configure.log echo ' [--debug] Enables extra debug prints during operation' | tee -a configure.log echo ' [--zlib-compat] Compiles for zlib-compatible API instead of zlib-ng API' | tee -a configure.log - echo ' [--without-gzfileops] Compiles with the gzfile parts of the API enabled' | tee -a configure.log + echo ' [--without-unaligned] Compiles without fast unaligned access' | tee -a configure.log + echo ' [--without-gzfileops] Compiles without the gzfile parts of the API enabled' | tee -a configure.log echo ' [--without-optimizations] Compiles without support for optional instruction sets' | tee -a configure.log echo ' [--without-new-strategies] Compiles without using new additional deflate strategies' | tee -a configure.log echo ' [--without-acle] Compiles without ARM C Language Extensions' | tee -a configure.log @@ -194,6 +196,7 @@ case "$1" in -s* | --shared | --enable-shared) shared=1; shift ;; -t | --static) shared=0; shift ;; --zlib-compat) compat=1; shift ;; + --without-unaligned) unalignedok=0; shift ;; --without-gzfileops) gzfileops=0; shift ;; --cover) cover=1; shift ;; -3* | --32) build32=1; shift ;; @@ -910,6 +913,13 @@ else PIC_TESTOBJG="\$(OBJG)" fi +# set architecture alignment requirements +if test $unalignedok -eq 0; then + CFLAGS="${CFLAGS} -DNO_UANLIGNED" + SFLAGS="${SFLAGS} -DNO_UNALIGNED" + echo "Unaligned reads manually disabled." | tee -a configure.log +fi + # enable reduced memory configuration if test $reducedmem -eq 1; then echo "Configuring for reduced memory environment." | tee -a configure.log diff --git a/zbuild.h b/zbuild.h index 20e3e20e34..0513bf0b16 100644 --- a/zbuild.h +++ b/zbuild.h @@ -194,25 +194,27 @@ # define Tracecv(c, x) #endif -#if defined(__x86_64__) || defined(_M_X64) || defined(__amd64__) || defined(_M_AMD64) -# define UNALIGNED_OK -# define UNALIGNED64_OK -#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || \ - defined(__i686__) || defined(_X86_) || defined(_M_IX86) -# define UNALIGNED_OK -#elif defined(__aarch64__) || defined(_M_ARM64) -# if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) +#ifndef NO_UNALIGNED +# if defined(__x86_64__) || defined(_M_X64) || defined(__amd64__) || defined(_M_AMD64) # define UNALIGNED_OK # define UNALIGNED64_OK -# endif -#elif defined(__arm__) || (_M_ARM >= 7) -# if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) -# define UNALIGNED_OK -# endif -#elif defined(__powerpc64__) || defined(__ppc64__) -# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# elif defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(_X86_) || defined(_M_IX86) # define UNALIGNED_OK -# define UNALIGNED64_OK +# elif defined(__aarch64__) || defined(_M_ARM64) +# if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) +# define UNALIGNED_OK +# define UNALIGNED64_OK +# endif +# elif defined(__arm__) || (_M_ARM >= 7) +# if (defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED)) || !defined(__GNUC__) +# define UNALIGNED_OK +# endif +# elif defined(__powerpc64__) || defined(__ppc64__) +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define UNALIGNED_OK +# define UNALIGNED64_OK +# endif # endif #endif From 5c22804d0be01116464fe1a1c9b321e5dd46f616 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 15 Mar 2022 10:24:47 -0700 Subject: [PATCH 318/798] Added 32-bit GCC build to CMake GitHub Actions. --- .github/workflows/cmake.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index a4d05f35e5..13c1933f10 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -59,6 +59,14 @@ jobs: codecov: ubuntu_gcc_o3 cflags: -O3 + - name: Ubuntu GCC 32-bit + os: ubuntu-latest + compiler: gcc + cxx-compiler: g++ + cmake-args: -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32 -DCMAKE_SHARED_LINKER_FLAGS=-m32 -DCMAKE_EXE_LINKER_FLAGS=-m32 + packages: gcc-multilib g++-multilib + codecov: ubuntu_gcc_m32 + - name: Ubuntu GCC No CTZLL os: ubuntu-latest compiler: gcc From 7a6d5ace97a84ea7a9ec31b02cc64cad2e200e8d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 15 Mar 2022 16:54:44 -0700 Subject: [PATCH 319/798] Added check for UNALIGNED64_OK when defining zmemcpy_8 and zmemcmp_8. --- zbuild.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zbuild.h b/zbuild.h index 0513bf0b16..f692385344 100644 --- a/zbuild.h +++ b/zbuild.h @@ -228,7 +228,7 @@ # define zmemcmp_2(str1, str2) (*((uint16_t *)(str1)) != *((uint16_t *)(str2))) # define zmemcpy_4(dest, src) (*((uint32_t *)(dest)) = *((uint32_t *)(src))) # define zmemcmp_4(str1, str2) (*((uint32_t *)(str1)) != *((uint32_t *)(str2))) -# if UINTPTR_MAX == UINT64_MAX +# if defined(UNALIGNED64_OK) && (UINTPTR_MAX == UINT64_MAX) # define zmemcpy_8(dest, src) (*((uint64_t *)(dest)) = *((uint64_t *)(src))) # define zmemcmp_8(str1, str2) (*((uint64_t *)(str1)) != *((uint64_t *)(str2))) # else From 1f87fac9d3812a4932ccf3d73a613c172866889c Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Wed, 16 Mar 2022 22:52:44 -0400 Subject: [PATCH 320/798] Fix UBSAN's cry afoul Technically, we weren't actually doing this the way C wants us to, legally. The zmemcpy's turn into NOPs for pretty much all > 0 optimization levels and this gets us defined behavior with the sanitizer, putting the optimized load by arbitrary alignment into the compiler's hands instead of ours. --- arch/x86/chunkset_avx.c | 12 +++++++++--- arch/x86/chunkset_sse2.c | 12 +++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index 358869bc6a..ff5d3c61e3 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -20,15 +20,21 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { } static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { - *chunk = _mm256_set1_epi16(*(int16_t *)from); + int16_t tmp; + zmemcpy_2(&tmp, from); + *chunk = _mm256_set1_epi16(tmp); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { - *chunk = _mm256_set1_epi32(*(int32_t *)from); + int32_t tmp; + zmemcpy_4(&tmp, from); + *chunk = _mm256_set1_epi32(tmp); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { - *chunk = _mm256_set1_epi64x(*(int64_t *)from); + int64_t tmp; + zmemcpy_8(&tmp, from); + *chunk = _mm256_set1_epi64x(tmp); } static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { diff --git a/arch/x86/chunkset_sse2.c b/arch/x86/chunkset_sse2.c index 59b86f15ca..778e4ca14a 100644 --- a/arch/x86/chunkset_sse2.c +++ b/arch/x86/chunkset_sse2.c @@ -21,15 +21,21 @@ static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { } static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { - *chunk = _mm_set1_epi16(*(int16_t *)from); + int16_t tmp; + zmemcpy_2(&tmp, from); + *chunk = _mm_set1_epi16(tmp); } static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { - *chunk = _mm_set1_epi32(*(int32_t *)from); + int32_t tmp; + zmemcpy_4(&tmp, from); + *chunk = _mm_set1_epi32(tmp); } static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { - *chunk = _mm_set1_epi64x(*(int64_t *)from); + int64_t tmp; + zmemcpy_8(&tmp, from); + *chunk = _mm_set1_epi64x(tmp); } static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { From e81c083fda107ca37b93304a1fd0aa9e68acfdee Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Thu, 17 Mar 2022 20:22:56 -0400 Subject: [PATCH 321/798] Fix a latent issue with chunkmemset It would seem that on some platforms, namely those which are !UNALIGNED64_OK, there was a likelihood of chunkmemset_safe_c copying all the bytes before passing control flow to chunkcopy, a function which is explicitly unsafe to be called with a zero length copy. This fixes that bug for those platforms. --- chunkset_tpl.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 189b5ec457..9ea37225ec 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -171,5 +171,8 @@ Z_INTERNAL uint8_t* CHUNKMEMSET_SAFE(uint8_t *out, unsigned dist, unsigned len, } return out; } - return CHUNKMEMSET(out, dist, len); + if (len) + return CHUNKMEMSET(out, dist, len); + + return out; } From d30a24d9aa9cfab016d8635bae14d3bf3db5ea14 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 16 Mar 2022 14:38:37 -0700 Subject: [PATCH 322/798] Remove unused zutil header. --- test/benchmarks/benchmark_adler32.cc | 1 - test/benchmarks/benchmark_compare256.cc | 1 - test/benchmarks/benchmark_crc32.cc | 1 - test/benchmarks/benchmark_slidehash.cc | 1 - 4 files changed, 4 deletions(-) diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index 780c0a2161..7aa46c2634 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -10,7 +10,6 @@ extern "C" { # include "zbuild.h" -# include "zutil.h" # include "zutil_p.h" # include "cpu_features.h" } diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 5a8a98b2dd..09a4bbc2a6 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -9,7 +9,6 @@ extern "C" { # include "zbuild.h" -# include "zutil.h" # include "zutil_p.h" # include "cpu_features.h" } diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index 07c238862e..5908116f1c 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -10,7 +10,6 @@ extern "C" { # include "zbuild.h" -# include "zutil.h" # include "zutil_p.h" # include "cpu_features.h" } diff --git a/test/benchmarks/benchmark_slidehash.cc b/test/benchmarks/benchmark_slidehash.cc index 516da80b76..655820e0cd 100644 --- a/test/benchmarks/benchmark_slidehash.cc +++ b/test/benchmarks/benchmark_slidehash.cc @@ -9,7 +9,6 @@ extern "C" { # include "zbuild.h" -# include "zutil.h" # include "zutil_p.h" # include "deflate.h" # include "cpu_features.h" From 92aa5d1cafd965b044d04c3767981837d3b0d709 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 17 Mar 2022 17:16:11 -0700 Subject: [PATCH 323/798] Use zutil.h which already includes zlib headers. --- arch/s390/dfltcc_common.h | 5 ----- compress.c | 5 ----- uncompr.c | 6 +----- 3 files changed, 1 insertion(+), 15 deletions(-) diff --git a/arch/s390/dfltcc_common.h b/arch/s390/dfltcc_common.h index 6de8bb18f6..df4b8b5784 100644 --- a/arch/s390/dfltcc_common.h +++ b/arch/s390/dfltcc_common.h @@ -1,11 +1,6 @@ #ifndef DFLTCC_COMMON_H #define DFLTCC_COMMON_H -#ifdef ZLIB_COMPAT -#include "zlib.h" -#else -#include "zlib-ng.h" -#endif #include "zutil.h" void Z_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size); diff --git a/compress.c b/compress.c index fded2a4cdf..db13f6ca22 100644 --- a/compress.c +++ b/compress.c @@ -5,11 +5,6 @@ #include "zbuild.h" #include "zutil.h" -#if defined(ZLIB_COMPAT) -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif /* =========================================================================== * Architecture-specific hooks. diff --git a/uncompr.c b/uncompr.c index 0053ef9827..54ed57fdbd 100644 --- a/uncompr.c +++ b/uncompr.c @@ -4,11 +4,7 @@ */ #include "zbuild.h" -#ifdef ZLIB_COMPAT -# include "zlib.h" -#else -# include "zlib-ng.h" -#endif +#include "zutil.h" /* =========================================================================== Decompresses the source buffer into the destination buffer. *sourceLen is From 7db850aa08791532af535ac896bb0ee13b415b62 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 17 Mar 2022 12:22:22 -0700 Subject: [PATCH 324/798] Added sanitizer tests in configure GitHub Actions workflow. Added missing OPTIONS environment variable for UBSAN in CMake GitHub workflow. --- .github/workflows/cmake.yml | 8 ++++---- .github/workflows/configure.yml | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 13c1933f10..2bf834a70f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -41,21 +41,20 @@ jobs: cmake-args: -DZLIB_COMPAT=ON -DZLIB_SYMBOL_PREFIX=zTest_ codecov: ubuntu_gcc_compat_sprefix - - name: Ubuntu GCC OSB -O1 UBSAN + - name: Ubuntu GCC -O1 OSB os: ubuntu-latest compiler: gcc cxx-compiler: g++ - cmake-args: -DWITH_SANITIZER=Undefined build-dir: ../build build-src-dir: ../zlib-ng codecov: ubuntu_gcc_osb cflags: -O1 -g3 - - name: Ubuntu GCC -O3 No Unaligned + - name: Ubuntu GCC -O3 No Unaligned UBSAN os: ubuntu-latest compiler: gcc cxx-compiler: g++ - cmake-args: -DWITH_UNALIGNED=OFF + cmake-args: -DWITH_UNALIGNED=OFF -DWITH_SANITIZER=Undefined codecov: ubuntu_gcc_o3 cflags: -O3 @@ -493,6 +492,7 @@ jobs: MSAN_OPTIONS: ${{ matrix.msan-options || 'verbosity=0' }}:abort_on_error=1 TSAN_OPTIONS: ${{ matrix.tsan-options || 'verbosity=0' }}:abort_on_error=1 LSAN_OPTIONS: ${{ matrix.lsan-options || 'verbosity=0' }}:abort_on_error=1 + UBSAN_OPTIONS: ${{ matrix.ubsan-options || 'verbosity=0' }}:print_stacktrace=1:abort_on_error=1 - name: Generate coverage report if: matrix.codecov diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 2c72afb8aa..2ab9d0e524 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -30,6 +30,21 @@ jobs: compiler: gcc configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies + - name: Ubuntu GCC ASAN + os: ubuntu-latest + compiler: gcc + configure-args: --warn --with-sanitizer=address + + - name: Ubuntu GCC MSAN + os: ubuntu-latest + compiler: gcc + configure-args: --warn --with-sanitizer=memory + + - name: Ubuntu GCC No Unaligned UBSAN + os: ubuntu-latest + compiler: gcc + configure-args: --warn --without-unaligned --with-sanitizer=undefined + - name: Ubuntu GCC ARM SF os: ubuntu-latest compiler: arm-linux-gnueabi-gcc @@ -224,6 +239,9 @@ jobs: make test env: QEMU_RUN: ${{ matrix.qemu-run }} + ASAN_OPTIONS: abort_on_error=1 + MSAN_OPTIONS: abort_on_error=1 + UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1 - name: Upload build errors uses: actions/upload-artifact@v2 From 7b5cfb67ee6ac6f25363274b5c82110810058172 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 17 Mar 2022 12:57:41 -0700 Subject: [PATCH 325/798] Wrong variable used when detecting unaligned support for sanitize --- cmake/detect-sanitizer.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/detect-sanitizer.cmake b/cmake/detect-sanitizer.cmake index fc4519ef28..965ddca8d0 100644 --- a/cmake/detect-sanitizer.cmake +++ b/cmake/detect-sanitizer.cmake @@ -112,7 +112,7 @@ macro(add_undefined_sanitizer) ) # Only check for alignment sanitizer flag if unaligned access is not supported - if(NOT UNALIGNED_OK) + if(NOT WITH_UNALIGNED) list(APPEND known_checks alignment) endif() # Object size sanitizer has no effect at -O0 and produces compiler warning if enabled @@ -129,7 +129,7 @@ macro(add_undefined_sanitizer) # Group sanitizer flag -fsanitize=undefined will automatically add alignment, even if # it is not in our sanitize flag list, so we need to explicitly disable alignment sanitizing. - if(UNALIGNED_OK) + if(WITH_UNALIGNED) add_compile_options(-fno-sanitize=alignment) endif() else() From 53be1944aaf8af5aa64330438e6467d0e3b15a4e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 17 Mar 2022 13:01:38 -0700 Subject: [PATCH 326/798] Fixed misspelling in NO_UNALIGNED flag. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 35404ce5b1..4bc0ee9cb1 100755 --- a/configure +++ b/configure @@ -915,7 +915,7 @@ fi # set architecture alignment requirements if test $unalignedok -eq 0; then - CFLAGS="${CFLAGS} -DNO_UANLIGNED" + CFLAGS="${CFLAGS} -DNO_UNALIGNED" SFLAGS="${SFLAGS} -DNO_UNALIGNED" echo "Unaligned reads manually disabled." | tee -a configure.log fi From c663e6fcee01a4d6c1577b64e843da8ed9420637 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 17 Mar 2022 14:39:12 -0700 Subject: [PATCH 327/798] Make symbolic prefix instance names consistent in NMake GHA workflow. --- .github/workflows/nmake.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nmake.yml b/.github/workflows/nmake.yml index d02065ff76..dcc1e736db 100644 --- a/.github/workflows/nmake.yml +++ b/.github/workflows/nmake.yml @@ -19,13 +19,13 @@ jobs: vc-vars: x86_amd64 additional-args: ZLIB_COMPAT=yes - - name: Windows NMake x64 sprefix + - name: Windows NMake x64 Symbol Prefix os: windows-2022 makefile: win32/Makefile.msc vc-vars: x86_amd64 additional-args: SYMBOL_PREFIX=zTest_ - - name: Windows NMake x64 sprefix compat + - name: Windows NMake x64 Symbol Prefix Compat os: windows-2022 makefile: win32/Makefile.msc vc-vars: x86_amd64 From 18c181987f532e13439489d21b454774b536fb2e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 18 Mar 2022 11:05:58 -0700 Subject: [PATCH 328/798] Use halt_on_error in sanitizer options. https://lists.llvm.org/pipermail/cfe-dev/2015-October/045710.html --- .github/workflows/cmake.yml | 10 +++++----- .github/workflows/configure.yml | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 2bf834a70f..e7a099a437 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -488,11 +488,11 @@ jobs: cd ${{ matrix.build-dir || '.' }} ctest --verbose -C Release --output-on-failure --max-width 120 -j ${{ matrix.parallels-jobs || '6' }} env: - ASAN_OPTIONS: ${{ matrix.asan-options || 'verbosity=0' }}:abort_on_error=1 - MSAN_OPTIONS: ${{ matrix.msan-options || 'verbosity=0' }}:abort_on_error=1 - TSAN_OPTIONS: ${{ matrix.tsan-options || 'verbosity=0' }}:abort_on_error=1 - LSAN_OPTIONS: ${{ matrix.lsan-options || 'verbosity=0' }}:abort_on_error=1 - UBSAN_OPTIONS: ${{ matrix.ubsan-options || 'verbosity=0' }}:print_stacktrace=1:abort_on_error=1 + ASAN_OPTIONS: ${{ matrix.asan-options || 'verbosity=0' }}:abort_on_error=1:halt_on_error=1 + MSAN_OPTIONS: ${{ matrix.msan-options || 'verbosity=0' }}:abort_on_error=1:halt_on_error=1 + TSAN_OPTIONS: ${{ matrix.tsan-options || 'verbosity=0' }}:abort_on_error=1:halt_on_error=1 + LSAN_OPTIONS: ${{ matrix.lsan-options || 'verbosity=0' }}:abort_on_error=1:halt_on_error=1 + UBSAN_OPTIONS: ${{ matrix.ubsan-options || 'verbosity=0' }}:print_stacktrace=1:abort_on_error=1:halt_on_error=1 - name: Generate coverage report if: matrix.codecov diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index 2ab9d0e524..ce367493ee 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -239,9 +239,9 @@ jobs: make test env: QEMU_RUN: ${{ matrix.qemu-run }} - ASAN_OPTIONS: abort_on_error=1 - MSAN_OPTIONS: abort_on_error=1 - UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1 + ASAN_OPTIONS: abort_on_error=1:halt_on_error=1 + MSAN_OPTIONS: abort_on_error=1:halt_on_error=1 + UBSAN_OPTIONS: print_stacktrace=1:abort_on_error=1:halt_on_error=1 - name: Upload build errors uses: actions/upload-artifact@v2 From 85f9709137a88c546e5dd188f7cb196b80f84253 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 18 Mar 2022 16:05:18 -0700 Subject: [PATCH 329/798] Added common sanitizer flags for getting optimal stack traces. --- .github/workflows/cmake.yml | 11 +++++------ cmake/detect-sanitizer.cmake | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index e7a099a437..f9e97d314c 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -41,22 +41,22 @@ jobs: cmake-args: -DZLIB_COMPAT=ON -DZLIB_SYMBOL_PREFIX=zTest_ codecov: ubuntu_gcc_compat_sprefix - - name: Ubuntu GCC -O1 OSB + - name: Ubuntu GCC -O3 OSB os: ubuntu-latest compiler: gcc cxx-compiler: g++ build-dir: ../build build-src-dir: ../zlib-ng codecov: ubuntu_gcc_osb - cflags: -O1 -g3 + cflags: -O3 - - name: Ubuntu GCC -O3 No Unaligned UBSAN + - name: Ubuntu GCC -O1 No Unaligned UBSAN os: ubuntu-latest compiler: gcc cxx-compiler: g++ cmake-args: -DWITH_UNALIGNED=OFF -DWITH_SANITIZER=Undefined - codecov: ubuntu_gcc_o3 - cflags: -O3 + codecov: ubuntu_gcc_o1 + cflags: -O1 - name: Ubuntu GCC 32-bit os: ubuntu-latest @@ -347,7 +347,6 @@ jobs: cmake-args: -GNinja -DWITH_SANITIZER=Memory packages: ninja-build llvm-11-tools gcov-exec: llvm-cov-11 gcov - cflags: -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-memory-track-origins - name: Windows MSVC Win32 os: windows-latest diff --git a/cmake/detect-sanitizer.cmake b/cmake/detect-sanitizer.cmake index 965ddca8d0..ae3d37317c 100644 --- a/cmake/detect-sanitizer.cmake +++ b/cmake/detect-sanitizer.cmake @@ -1,6 +1,22 @@ # detect-sanitizer.cmake -- Detect supported compiler sanitizer flags # Licensed under the Zlib license, see LICENSE.md for details +macro(add_common_sanitizer_flags) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + add_compile_options(-g3) + endif() + check_c_compiler_flag(-fno-omit-frame-pointer HAVE_NO_OMIT_FRAME_POINTER) + if(HAVE_NO_OMIT_FRAME_POINTER) + add_compile_options(-fno-omit-frame-pointer) + add_link_options(-fno-omit-frame-pointer) + endif() + check_c_compiler_flag(-fno-optimize-sibling-calls HAVE_NO_OPTIMIZE_SIBLING_CALLS) + if(HAVE_NO_OPTIMIZE_SIBLING_CALLS) + add_compile_options(-fno-optimize-sibling-calls) + add_link_options(-fno-optimize-sibling-calls) + endif() +endmacro() + macro(check_sanitizer_support known_checks supported_checks) set(available_checks "") @@ -41,6 +57,7 @@ macro(add_address_sanitizer) message(STATUS "Address sanitizer is enabled: ${supported_checks}") add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) + add_common_sanitizer_flags() else() message(STATUS "Address sanitizer is not supported") endif() @@ -55,6 +72,7 @@ macro(add_address_sanitizer) message(STATUS "Leak sanitizer is enabled: ${supported_checks}") add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) + add_common_sanitizer_flags() else() message(STATUS "Leak sanitizer is not supported") endif() @@ -67,6 +85,13 @@ macro(add_memory_sanitizer) message(STATUS "Memory sanitizer is enabled: ${supported_checks}") add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) + add_common_sanitizer_flags() + + check_c_compiler_flag(-fsanitize-memory-track-origins HAVE_MEMORY_TRACK_ORIGINS) + if(HAVE_MEMORY_TRACK_ORIGINS) + add_compile_options(-fsanitize-memory-track-origins) + add_link_options(-fsanitize-memory-track-origins) + endif() else() message(STATUS "Memory sanitizer is not supported") endif() @@ -78,6 +103,7 @@ macro(add_thread_sanitizer) message(STATUS "Thread sanitizer is enabled: ${supported_checks}") add_compile_options(-fsanitize=${supported_checks}) add_link_options(-fsanitize=${supported_checks}) + add_common_sanitizer_flags() else() message(STATUS "Thread sanitizer is not supported") endif() @@ -132,6 +158,8 @@ macro(add_undefined_sanitizer) if(WITH_UNALIGNED) add_compile_options(-fno-sanitize=alignment) endif() + + add_common_sanitizer_flags() else() message(STATUS "Undefined behavior sanitizer is not supported") endif() From 097f789fa2ceff089b4a4f341d2aa2ac7d9fd44d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 6 Mar 2022 19:16:37 -0800 Subject: [PATCH 330/798] Revert "DFLTCC update for window optimization from Jim & Nathan" This reverts commit b4ca25afabba7b4bf74d36e26728006d28df891d. --- arch/s390/README.md | 20 +++++++--------- arch/s390/dfltcc_deflate.c | 48 ++++++++++++++++++++++++++++++++++++-- arch/s390/dfltcc_detail.h | 47 ------------------------------------- arch/s390/dfltcc_inflate.c | 30 ++++-------------------- arch/s390/dfltcc_inflate.h | 16 +------------ inflate.c | 28 +++++++++++----------- inflate_p.h | 9 ++----- 7 files changed, 74 insertions(+), 124 deletions(-) diff --git a/arch/s390/README.md b/arch/s390/README.md index b4b3fb8b51..90066f0f96 100644 --- a/arch/s390/README.md +++ b/arch/s390/README.md @@ -66,10 +66,11 @@ buffer and a window. `ZALLOC_STATE()`, `ZFREE_STATE()`, `ZCOPY_STATE()`, details for the parameter block (which is allocated alongside zlib-ng state) and the window (which must be page-aligned). -Software and hardware deflate window formats don't match, therefore, -`deflateSetDictionary()` and `deflateGetDictionary()` need special handling, -which is triggered using `DEFLATE_SET_DICTIONARY_HOOK()` and -`DEFLATE_GET_DICTIONARY_HOOK()` macros. +While inflate software and hardware window formats match, this is not +the case for deflate. Therefore, `deflateSetDictionary()` and +`deflateGetDictionary()` need special handling, which is triggered using +`DEFLATE_SET_DICTIONARY_HOOK()` and `DEFLATE_GET_DICTIONARY_HOOK()` +macros. `deflateResetKeep()` and `inflateResetKeep()` update the DFLTCC parameter block using `DEFLATE_RESET_KEEP_HOOK()` and @@ -91,14 +92,9 @@ and `DEFLATE_NEED_CONSERVATIVE_BOUND()` macros make `deflateBound()` return the correct results for the hardware implementation. Actual compression and decompression are handled by `DEFLATE_HOOK()` and -`INFLATE_TYPEDO_HOOK()` macros. - -Software and hardware inflate window formats don't match, therefore, -`inflateSetDictionary()` and `inflateGetDictionary()` need special handling, -which is triggered using `INFLATE_SET_DICTIONARY_HOOK()` and -`INFLATE_GET_DICTIONARY_HOOK()` macros. Furthermore, calling -`window_output_flush()` is suppressed using -`INFLATE_NEED_WINDOW_OUTPUT_FLUSH()` macro. +`INFLATE_TYPEDO_HOOK()` macros. Since inflation with DFLTCC manages the +window on its own, calling `updatewindow()` is suppressed using +`INFLATE_NEED_UPDATEWINDOW()` macro. In addition to compression, DFLTCC computes CRC-32 and Adler-32 checksums, therefore, whenever it's used, software checksumming is diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index c498e3ecaf..dcb3f7c5d7 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -342,13 +342,46 @@ int Z_INTERNAL dfltcc_can_set_reproducible(PREFIX3(streamp) strm, int reproducib return reproducible != state->reproducible && !dfltcc_was_deflate_used(strm); } +/* + Preloading history. +*/ +static void append_history(struct dfltcc_param_v0 *param, unsigned char *history, const unsigned char *buf, uInt count) { + size_t offset; + size_t n; + + /* Do not use more than 32K */ + if (count > HB_SIZE) { + buf += count - HB_SIZE; + count = HB_SIZE; + } + offset = (param->ho + param->hl) % HB_SIZE; + if (offset + count <= HB_SIZE) + /* Circular history buffer does not wrap - copy one chunk */ + memcpy(history + offset, buf, count); + else { + /* Circular history buffer wraps - copy two chunks */ + n = HB_SIZE - offset; + memcpy(history + offset, buf, n); + memcpy(history, buf + n, count - n); + } + n = param->hl + count; + if (n <= HB_SIZE) + /* All history fits into buffer - no need to discard anything */ + param->hl = n; + else { + /* History does not fit into buffer - discard extra bytes */ + param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE; + param->hl = HB_SIZE; + } +} + int Z_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length) { deflate_state *state = (deflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; - dfltcc_append_history(param, state->window, dictionary, dict_length); + append_history(param, state->window, dictionary, dict_length); state->strstart = 1; /* Add FDICT to zlib header */ state->block_start = state->strstart; /* Make deflate_stored happy */ return Z_OK; @@ -359,6 +392,17 @@ int Z_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned cha struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; - dfltcc_get_history(param, state->window, dictionary, dict_length); + if (dictionary) { + if (param->ho + param->hl <= HB_SIZE) + /* Circular history buffer does not wrap - copy one chunk */ + memcpy(dictionary, state->window + param->ho, param->hl); + else { + /* Circular history buffer wraps - copy two chunks */ + memcpy(dictionary, state->window + param->ho, HB_SIZE - param->ho); + memcpy(dictionary + HB_SIZE - param->ho, state->window, param->ho + param->hl - HB_SIZE); + } + } + if (dict_length) + *dict_length = param->hl; return Z_OK; } diff --git a/arch/s390/dfltcc_detail.h b/arch/s390/dfltcc_detail.h index 5fb8f47c52..4ec03f8097 100644 --- a/arch/s390/dfltcc_detail.h +++ b/arch/s390/dfltcc_detail.h @@ -197,50 +197,3 @@ struct dfltcc_state { #define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1)) #define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8))) - -static inline void dfltcc_get_history(struct dfltcc_param_v0 *param, const unsigned char *history, - unsigned char *buf, uInt *count) { - if (buf) { - if (param->ho + param->hl <= HB_SIZE) - /* Circular history buffer does not wrap - copy one chunk */ - memcpy(buf, history + param->ho, param->hl); - else { - /* Circular history buffer wraps - copy two chunks */ - memcpy(buf, history + param->ho, HB_SIZE - param->ho); - memcpy(buf + HB_SIZE - param->ho, history, param->ho + param->hl - HB_SIZE); - } - } - if (count) - *count = param->hl; -} - -static inline void dfltcc_append_history(struct dfltcc_param_v0 *param, unsigned char *history, - const unsigned char *buf, uInt count) { - size_t offset; - size_t n; - - /* Do not use more than 32K */ - if (count > HB_SIZE) { - buf += count - HB_SIZE; - count = HB_SIZE; - } - offset = (param->ho + param->hl) % HB_SIZE; - if (offset + count <= HB_SIZE) - /* Circular history buffer does not wrap - copy one chunk */ - memcpy(history + offset, buf, count); - else { - /* Circular history buffer wraps - copy two chunks */ - n = HB_SIZE - offset; - memcpy(history + offset, buf, n); - memcpy(history, buf + n, count - n); - } - n = param->hl + count; - if (n <= HB_SIZE) - /* All history fits into buffer - no need to discard anything */ - param->hl = n; - else { - /* History does not fit into buffer - discard extra bytes */ - param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE; - param->hl = HB_SIZE; - } -} diff --git a/arch/s390/dfltcc_inflate.c b/arch/s390/dfltcc_inflate.c index 9b1497d2b8..253506466d 100644 --- a/arch/s390/dfltcc_inflate.c +++ b/arch/s390/dfltcc_inflate.c @@ -83,6 +83,8 @@ dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush /* Translate stream to parameter block */ param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32; param->sbb = state->bits; + param->hl = state->whave; /* Software and hardware history formats match */ + param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1); if (param->hl) param->nt = 0; /* Honor history for the first block */ param->cv = state->flags ? ZSWAP32(state->check) : state->check; @@ -96,6 +98,8 @@ dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); state->last = cc == DFLTCC_CC_OK; state->bits = param->sbb; + state->whave = param->hl; + state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1); state->check = state->flags ? ZSWAP32(param->cv) : param->cv; if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) { /* Report an error if stream is corrupted */ @@ -118,8 +122,6 @@ int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm) { int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; - uInt count; if (!dfltcc_can_inflate(strm)) return 0; @@ -131,29 +133,5 @@ int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm) { return 1; /* DFLTCC was not used yet - decompress in software */ memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); - /* Convert window from hardware to software format. Use its second part as scratch space. */ - dfltcc_get_history(param, state->window, state->window + state->wsize, &count); - state->whave = count; - state->wnext = 0; - memcpy(state->window + state->wsize - state->whave, state->window + state->wsize, state->whave); return 0; } - -int Z_INTERNAL dfltcc_inflate_set_dictionary(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length) { - struct inflate_state *state = (struct inflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; - - dfltcc_append_history(param, state->window, dictionary, dict_length); - state->havedict = 1; - return Z_OK; -} - -int Z_INTERNAL dfltcc_inflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt *dict_length) { - struct inflate_state *state = (struct inflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; - - dfltcc_get_history(param, state->window, dictionary, dict_length); - return Z_OK; -} diff --git a/arch/s390/dfltcc_inflate.h b/arch/s390/dfltcc_inflate.h index 4b68b7048e..fc8a000f7b 100644 --- a/arch/s390/dfltcc_inflate.h +++ b/arch/s390/dfltcc_inflate.h @@ -12,8 +12,6 @@ typedef enum { dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret); int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm); int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm); -int Z_INTERNAL dfltcc_inflate_set_dictionary(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length); -int Z_INTERNAL dfltcc_inflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length); #define INFLATE_RESET_KEEP_HOOK(strm) \ dfltcc_reset((strm), sizeof(struct inflate_state)) @@ -36,7 +34,7 @@ int Z_INTERNAL dfltcc_inflate_get_dictionary(PREFIX3(streamp) strm, unsigned cha #define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm))) -#define INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) (!dfltcc_can_inflate((strm))) +#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm))) #define INFLATE_MARK_HOOK(strm) \ do { \ @@ -48,16 +46,4 @@ int Z_INTERNAL dfltcc_inflate_get_dictionary(PREFIX3(streamp) strm, unsigned cha if (dfltcc_was_inflate_used((strm))) return Z_STREAM_ERROR; \ } while (0) -#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \ - do { \ - if (dfltcc_can_inflate((strm))) \ - return dfltcc_inflate_set_dictionary((strm), (dict), (dict_len)); \ - } while (0) - -#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \ - do { \ - if (dfltcc_can_inflate((strm))) \ - return dfltcc_inflate_get_dictionary((strm), (dict), (dict_len)); \ - } while (0) - #endif diff --git a/inflate.c b/inflate.c index 5e2af29c6c..419939b147 100644 --- a/inflate.c +++ b/inflate.c @@ -911,13 +911,11 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { break; case CHECK: - if (INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm)) { - RESTORE(); - window_output_flush(strm); - LOAD(); - if (strm->avail_out == 0 && state->wnext) - goto inf_leave; - } + RESTORE(); + window_output_flush(strm); + LOAD(); + if (strm->avail_out == 0 && state->wnext) + goto inf_leave; if (state->wrap) { NEEDBITS(32); out -= left; @@ -984,7 +982,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { inf_leave: RESTORE(); - if (INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) && strm->avail_out && state->wnext) + if (strm->avail_out && state->wnext) window_output_flush(strm); in -= strm->avail_in; @@ -1019,12 +1017,13 @@ int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *di /* check state */ if (inflateStateCheck(strm)) return Z_STREAM_ERROR; - INFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ state = (struct inflate_state *)strm->state; /* copy dictionary */ - if (state->whave && dictionary != NULL) - memcpy(dictionary, state->window + state->wsize - state->whave, state->whave); + if (state->whave && dictionary != NULL) { + memcpy(dictionary, state->window + state->wnext, state->whave - state->wnext); + memcpy(dictionary + state->whave - state->wnext, state->window, state->wnext); + } if (dictLength != NULL) *dictLength = state->whave; return Z_OK; @@ -1033,7 +1032,7 @@ int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *di int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) { struct inflate_state *state; unsigned long dictid, dict_copy, hist_copy; - const unsigned char *dict_from; + const unsigned char *dict_from, *hist_from; unsigned char *dict_to, *hist_to; int ret; @@ -1056,8 +1055,6 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8 Tracec(state->wnext != 0, (stderr, "Setting dictionary with unflushed output")); - INFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength); /* hook for IBM Z DFLTCC */ - /* copy dictionary to window and amend if necessary */ dict_from = dictionary; dict_copy = dictLength; @@ -1067,13 +1064,14 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8 } dict_to = state->window + state->wsize - dict_copy; + hist_from = state->window + state->wsize - state->whave; hist_copy = state->wsize - dict_copy; if (hist_copy > state->whave) hist_copy = state->whave; hist_to = dict_to - hist_copy; if (hist_copy) - memcpy(hist_to, state->window + state->wsize - hist_copy, hist_copy); + memcpy(hist_to, hist_from, hist_copy); if (dict_copy) memcpy(dict_to, dict_from, dict_copy); diff --git a/inflate_p.h b/inflate_p.h index 86e3702b86..d2aab559f3 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -27,17 +27,12 @@ # define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0) /* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */ # define INFLATE_NEED_CHECKSUM(strm) 1 -/* Returns whether zlib-ng should flush the window to the output buffer. - Set to 0 if arch-specific inflation code already does that. */ -# define INFLATE_NEED_WINDOW_OUTPUT_FLUSH(strm) 1 +/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */ +# define INFLATE_NEED_UPDATEWINDOW(strm) 1 /* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */ # define INFLATE_MARK_HOOK(strm) do {} while (0) /* Invoked at the beginning of inflateSyncPoint(). Useful for performing arch-specific state checks. */ # define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) -/* Invoked at the beginning of inflateSetDictionary(). Useful for checking arch-specific window data. */ -# define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) -/* Invoked at the beginning of inflateGetDictionary(). Useful for adjusting arch-specific window data. */ -# define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0) #endif From b5af5013d9e6ae15d13581fada9c29720567b3ad Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 6 Mar 2022 19:16:49 -0800 Subject: [PATCH 331/798] Revert "Add back original version of inflate_fast for use with inflateBack." This reverts commit 2d2dde43b11c40cb58a339ff4a8425bca0091c31. --- infback.c | 11 --- inffast.c | 252 ---------------------------------------------------- inffast.h | 1 - inflate_p.h | 22 ----- 4 files changed, 286 deletions(-) diff --git a/infback.c b/infback.c index cf0549ae1e..8c43a7cef8 100644 --- a/infback.c +++ b/infback.c @@ -338,17 +338,6 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in state->mode = LEN; case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= INFLATE_FAST_MIN_HAVE && - left >= INFLATE_FAST_MIN_LEFT) { - RESTORE_BACK(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - zng_inflate_fast_back(strm, state->wsize); - LOAD_BACK(); - break; - } - /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; diff --git a/inffast.c b/inffast.c index e0fb99c593..1dc1f789ec 100644 --- a/inffast.c +++ b/inffast.c @@ -249,258 +249,6 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { state->bits = bits; return; } -void Z_INTERNAL zng_inflate_fast_back(PREFIX3(stream) *strm, unsigned long start) { - /* start: inflate()'s starting value for strm->avail_out */ - struct inflate_state *state; - z_const unsigned char *in; /* local strm->next_in */ - const unsigned char *last; /* have enough input while in < last */ - unsigned char *out; /* local strm->next_out */ - unsigned char *beg; /* inflate()'s initial strm->next_out */ - unsigned char *end; /* while out < end, enough space available */ - unsigned char *safe; /* can use chunkcopy provided out < safe */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned wnext; /* window write index */ - unsigned char *window; /* allocated sliding window, if wsize != 0 */ - - /* hold is a local copy of strm->hold. By default, hold satisfies the same - invariants that strm->hold does, namely that (hold >> bits) == 0. This - invariant is kept by loading bits into hold one byte at a time, like: - hold |= next_byte_of_input << bits; in++; bits += 8; - If we need to ensure that bits >= 15 then this code snippet is simply - repeated. Over one iteration of the outermost do/while loop, this - happens up to six times (48 bits of input), as described in the NOTES - above. - However, on some little endian architectures, it can be significantly - faster to load 64 bits once instead of 8 bits six times: - if (bits <= 16) { - hold |= next_8_bytes_of_input << bits; in += 6; bits += 48; - } - Unlike the simpler one byte load, shifting the next_8_bytes_of_input - by bits will overflow and lose those high bits, up to 2 bytes' worth. - The conservative estimate is therefore that we have read only 6 bytes - (48 bits). Again, as per the NOTES above, 48 bits is sufficient for the - rest of the iteration, and we will not need to load another 8 bytes. - Inside this function, we no longer satisfy (hold >> bits) == 0, but - this is not problematic, even if that overflow does not land on an 8 bit - byte boundary. Those excess bits will eventually shift down lower as the - Huffman decoder consumes input, and when new input bits need to be loaded - into the bits variable, the same input bits will be or'ed over those - existing bits. A bitwise or is idempotent: (a | b | b) equals (a | b). - Note that we therefore write that load operation as "hold |= etc" and not - "hold += etc". - Outside that loop, at the end of the function, hold is bitwise and'ed - with (1<hold >> state->bits) == 0. - */ - uint64_t hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const *lcode; /* local strm->lencode */ - code const *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - const code *here; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char *from; /* where to copy match from */ - unsigned extra_safe; /* copy chunks safely in all cases */ - - /* copy state to local variables */ - state = (struct inflate_state *)strm->state; - in = strm->next_in; - last = in + (strm->avail_in - (INFLATE_FAST_MIN_HAVE - 1)); - out = strm->next_out; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - (INFLATE_FAST_MIN_LEFT - 1)); - safe = out + strm->avail_out; -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - wnext = state->wnext; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* Detect if out and window point to the same memory allocation. In this instance it is - necessary to use safe chunk copy functions to prevent overwriting the window. If the - window is overwritten then future matches with far distances will fail to copy correctly. */ - extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } - here = lcode + (hold & lmask); - dolen: - DROPBITS(here->bits); - op = here->op; - if (op == 0) { /* literal */ - Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here->val)); - *out++ = (unsigned char)(here->val); - } else if (op & 16) { /* length base */ - len = here->val; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } - len += BITS(op); - DROPBITS(op); - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } - here = dcode + (hold & dmask); - dodist: - DROPBITS(here->bits); - op = here->op; - if (op & 16) { /* distance base */ - dist = here->val; - op &= 15; /* number of extra bits */ - if (bits < op) { - hold |= load_64_bits(in, bits); - in += 6; - bits += 48; - } - dist += BITS(op); -#ifdef INFLATE_STRICT - if (dist > dmax) { - SET_BAD("invalid distance too far back"); - break; - } -#endif - DROPBITS(op); - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - if (state->sane) { - SET_BAD("invalid distance too far back"); - break; - } -#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR - if (len <= op - whave) { - do { - *out++ = 0; - } while (--len); - continue; - } - len -= op - whave; - do { - *out++ = 0; - } while (--op > whave); - if (op == 0) { - from = out - dist; - do { - *out++ = *from++; - } while (--len); - continue; - } -#endif - } - from = window; - if (wnext == 0) { /* very common case */ - from += wsize - op; - } else if (wnext >= op) { /* contiguous in window */ - from += wnext - op; - } else { /* wrap around window */ - op -= wnext; - from += wsize - op; - if (op < len) { /* some from end of window */ - len -= op; - out = chunkcopy_safe(out, from, op, safe); - from = window; /* more from start of window */ - op = wnext; - /* This (rare) case can create a situation where - the first chunkcopy below must be checked. - */ - } - } - if (op < len) { /* still need some from output */ - len -= op; - out = chunkcopy_safe(out, from, op, safe); - out = functable.chunkunroll(out, &dist, &len); - out = chunkcopy_safe(out, out - dist, len, safe); - } else { - out = chunkcopy_safe(out, from, len, safe); - } - } else if (extra_safe) { - /* Whole reference is in range of current output. */ - if (dist >= len || dist >= state->chunksize) - out = chunkcopy_safe(out, out - dist, len, safe); - else - out = functable.chunkmemset_safe(out, dist, len, (unsigned)((safe - out) + 1)); - } else { - /* Whole reference is in range of current output. No range checks are - necessary because we start with room for at least 258 bytes of output, - so unroll and roundoff operations can write beyond `out+len` so long - as they stay within 258 bytes of `out`. - */ - if (dist >= len || dist >= state->chunksize) - out = functable.chunkcopy(out, out - dist, len); - else - out = functable.chunkmemset(out, dist, len); - } - } else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode + here->val + BITS(op); - goto dodist; - } else { - SET_BAD("invalid distance code"); - break; - } - } else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode + here->val + BITS(op); - goto dolen; - } else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } else { - SET_BAD("invalid literal/length code"); - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (UINT64_C(1) << bits) - 1; - - /* update state and return */ - strm->next_in = in; - strm->next_out = out; - strm->avail_in = (unsigned)(in < last ? (INFLATE_FAST_MIN_HAVE - 1) + (last - in) - : (INFLATE_FAST_MIN_HAVE - 1) - (in - last)); - strm->avail_out = (unsigned)(out < end ? (INFLATE_FAST_MIN_LEFT - 1) + (end - out) - : (INFLATE_FAST_MIN_LEFT - 1) - (out - end)); - - Assert(bits <= 32, "Remaining bits greater than 32"); - state->hold = (uint32_t)hold; - state->bits = bits; - return; -} /* inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): diff --git a/inffast.h b/inffast.h index e8d7e6e01d..cf9a3e2d2b 100644 --- a/inffast.h +++ b/inffast.h @@ -11,7 +11,6 @@ */ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm); -void Z_INTERNAL zng_inflate_fast_back(PREFIX3(stream) *strm, unsigned long start); #define INFLATE_FAST_MIN_HAVE 8 #define INFLATE_FAST_MIN_LEFT 258 diff --git a/inflate_p.h b/inflate_p.h index d2aab559f3..fd3343a9bf 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -70,17 +70,6 @@ bits = state->bits; \ } while (0) -/* Load registers with state in inflateBack() for speed */ -#define LOAD_BACK() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ @@ -92,17 +81,6 @@ state->bits = bits; \ } while (0) -/* Restore state from registers in inflateBack() */ -#define RESTORE_BACK() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = (z_const unsigned char *)next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - /* Clear the input bit accumulator */ #define INITBITS() \ do { \ From 6c4beb611d84a79dd7c9206104d8766fec774c45 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 6 Mar 2022 19:20:29 -0800 Subject: [PATCH 332/798] Revert "Reorganize inflate window layout" This reverts commit dc3b60841dbfa9cf37be3efb4568f055b4e15580. --- infback.c | 11 +++ inffast.c | 117 +++++++++++++++++++----- inffast.h | 2 +- inflate.c | 231 +++++++++++++++++++++++++----------------------- inflate.h | 4 - inflate_p.h | 78 +++------------- test/infcover.c | 12 ++- 7 files changed, 242 insertions(+), 213 deletions(-) diff --git a/infback.c b/infback.c index 8c43a7cef8..c3f0fccc8a 100644 --- a/infback.c +++ b/infback.c @@ -338,6 +338,17 @@ int32_t Z_EXPORT PREFIX(inflateBack)(PREFIX3(stream) *strm, in_func in, void *in state->mode = LEN; case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= INFLATE_FAST_MIN_HAVE && + left >= INFLATE_FAST_MIN_LEFT) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + zng_inflate_fast(strm, state->wsize); + LOAD(); + break; + } + /* get a literal, length, or end-of-block code */ for (;;) { here = state->lencode[BITS(state->lenbits)]; diff --git a/inffast.c b/inffast.c index 1dc1f789ec..36923317de 100644 --- a/inffast.c +++ b/inffast.c @@ -61,16 +61,22 @@ static inline uint64_t load_64_bits(const unsigned char *in, unsigned bits) { requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ -void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { +void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start) { + /* start: inflate()'s starting value for strm->avail_out */ struct inflate_state *state; z_const unsigned char *in; /* local strm->next_in */ const unsigned char *last; /* have enough input while in < last */ unsigned char *out; /* local strm->next_out */ + unsigned char *beg; /* inflate()'s initial strm->next_out */ unsigned char *end; /* while out < end, enough space available */ + unsigned char *safe; /* can use chunkcopy provided out < safe */ #ifdef INFLATE_STRICT unsigned dmax; /* maximum distance from zlib header */ #endif unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char *window; /* allocated sliding window, if wsize != 0 */ /* hold is a local copy of strm->hold. By default, hold satisfies the same invariants that strm->hold does, namely that (hold >> bits) == 0. This @@ -120,17 +126,24 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ unsigned dist; /* match distance */ + unsigned char *from; /* where to copy match from */ + unsigned extra_safe; /* copy chunks safely in all cases */ /* copy state to local variables */ state = (struct inflate_state *)strm->state; in = strm->next_in; last = in + (strm->avail_in - (INFLATE_FAST_MIN_HAVE - 1)); - wsize = state->wsize; - out = state->window + wsize + state->wnext; - end = state->window + (wsize * 2) - (INFLATE_FAST_MIN_LEFT - 1); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - (INFLATE_FAST_MIN_LEFT - 1)); + safe = out + strm->avail_out; #ifdef INFLATE_STRICT dmax = state->dmax; #endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; hold = state->hold; bits = state->bits; lcode = state->lencode; @@ -138,6 +151,11 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { lmask = (1U << state->lenbits) - 1; dmask = (1U << state->distbits) - 1; + /* Detect if out and window point to the same memory allocation. In this instance it is + necessary to use safe chunk copy functions to prevent overwriting the window. If the + window is overwritten then future matches with far distances will fail to copy correctly. */ + extra_safe = (wsize != 0 && out >= window && out + INFLATE_FAST_MIN_LEFT <= window + wsize); + /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { @@ -146,13 +164,6 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { in += 6; bits += 48; } - if (out >= end) { - state->wnext = (uint32_t)(out - (state->window + wsize)); - window_output_flush(strm); - out = state->window + state->wsize + state->wnext; - if (strm->avail_out == 0) - break; - } here = lcode + (hold & lmask); dolen: DROPBITS(here->bits); @@ -199,18 +210,76 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { #endif DROPBITS(op); Tracevv((stderr, "inflate: distance %u\n", dist)); - - if (out - dist < ((state->window + state->wsize) - state->whave)) { - if (state->sane) { - SET_BAD("invalid distance too far back"); - break; + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + SET_BAD("invalid distance too far back"); + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif } - } - - if (len > dist || dist < state->chunksize) { - out = functable.chunkmemset(out, dist, len); + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + } else if (wnext >= op) { /* contiguous in window */ + from += wnext - op; + } else { /* wrap around window */ + op -= wnext; + from += wsize - op; + if (op < len) { /* some from end of window */ + len -= op; + out = chunkcopy_safe(out, from, op, safe); + from = window; /* more from start of window */ + op = wnext; + /* This (rare) case can create a situation where + the first chunkcopy below must be checked. + */ + } + } + if (op < len) { /* still need some from output */ + len -= op; + out = chunkcopy_safe(out, from, op, safe); + out = functable.chunkunroll(out, &dist, &len); + out = chunkcopy_safe(out, out - dist, len, safe); + } else { + out = chunkcopy_safe(out, from, len, safe); + } + } else if (extra_safe) { + /* Whole reference is in range of current output. */ + if (dist >= len || dist >= state->chunksize) + out = chunkcopy_safe(out, out - dist, len, safe); + else + out = functable.chunkmemset_safe(out, dist, len, (unsigned)((safe - out) + 1)); } else { - out = functable.chunkcopy(out, out - dist, len); + /* Whole reference is in range of current output. No range checks are + necessary because we start with room for at least 258 bytes of output, + so unroll and roundoff operations can write beyond `out+len` so long + as they stay within 258 bytes of `out`. + */ + if (dist >= len || dist >= state->chunksize) + out = functable.chunkcopy(out, out - dist, len); + else + out = functable.chunkmemset(out, dist, len); } } else if ((op & 64) == 0) { /* 2nd level distance code */ here = dcode + here->val + BITS(op); @@ -230,7 +299,7 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { SET_BAD("invalid literal/length code"); break; } - } while (in < last); + } while (in < last && out < end); /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ len = bits >> 3; @@ -240,10 +309,12 @@ void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm) { /* update state and return */ strm->next_in = in; + strm->next_out = out; strm->avail_in = (unsigned)(in < last ? (INFLATE_FAST_MIN_HAVE - 1) + (last - in) : (INFLATE_FAST_MIN_HAVE - 1) - (in - last)); + strm->avail_out = (unsigned)(out < end ? (INFLATE_FAST_MIN_LEFT - 1) + (end - out) + : (INFLATE_FAST_MIN_LEFT - 1) - (out - end)); - state->wnext = (uint32_t)(out - (state->window + state->wsize)); Assert(bits <= 32, "Remaining bits greater than 32"); state->hold = (uint32_t)hold; state->bits = bits; diff --git a/inffast.h b/inffast.h index cf9a3e2d2b..179a65da60 100644 --- a/inffast.h +++ b/inffast.h @@ -10,7 +10,7 @@ subject to change. Applications should only use zlib.h. */ -void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm); +void Z_INTERNAL zng_inflate_fast(PREFIX3(stream) *strm, unsigned long start); #define INFLATE_FAST_MIN_HAVE 8 #define INFLATE_FAST_MIN_LEFT 258 diff --git a/inflate.c b/inflate.c index 419939b147..11f7b5b084 100644 --- a/inflate.c +++ b/inflate.c @@ -15,6 +15,7 @@ /* function prototypes */ static int inflateStateCheck(PREFIX3(stream) *strm); +static int updatewindow(PREFIX3(stream) *strm, const unsigned char *end, uint32_t copy); static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t len); static int inflateStateCheck(PREFIX3(stream) *strm) { @@ -60,6 +61,7 @@ int32_t Z_EXPORT PREFIX(inflateReset)(PREFIX3(stream) *strm) { if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state *)strm->state; + state->wsize = 0; state->whave = 0; state->wnext = 0; return PREFIX(inflateResetKeep)(strm); @@ -92,7 +94,6 @@ int32_t Z_EXPORT PREFIX(inflateReset2)(PREFIX3(stream) *strm, int32_t windowBits if (state->window != NULL && state->wbits != (unsigned)windowBits) { ZFREE_WINDOW(strm, state->window); state->window = NULL; - state->wsize = 0; } /* update state and reset the rest of it */ @@ -125,14 +126,12 @@ int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits strm->state = (struct internal_state *)state; state->strm = strm; state->window = NULL; - state->wsize = 0; state->mode = HEAD; /* to pass state test in inflateReset2() */ state->chunksize = functable.chunksize(); ret = PREFIX(inflateReset2)(strm, windowBits); if (ret != Z_OK) { ZFREE_STATE(strm, state); strm->state = NULL; - return ret; } return ret; } @@ -177,7 +176,7 @@ int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) { /* if it hasn't been done already, allocate space for the window */ if (state->window == NULL) { unsigned wsize = 1U << state->wbits; - state->window = (unsigned char *)ZALLOC_WINDOW(state->strm, (wsize * 2) + state->chunksize, sizeof(unsigned char)); + state->window = (unsigned char *)ZALLOC_WINDOW(state->strm, wsize + state->chunksize, sizeof(unsigned char)); if (state->window == NULL) return Z_MEM_ERROR; memset(state->window + wsize, 0, state->chunksize); @@ -193,6 +192,54 @@ int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) { return Z_OK; } +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t copy) { + struct inflate_state *state; + uint32_t dist; + + state = (struct inflate_state *)strm->state; + + if (inflate_ensure_window(state)) return 1; + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + memcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } else { + dist = state->wsize - state->wnext; + if (dist > copy) + dist = copy; + memcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + memcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } else { + state->wnext += dist; + if (state->wnext == state->wsize) + state->wnext = 0; + if (state->whave < state->wsize) + state->whave += dist; + } + } + return 0; +} + /* Private macros for inflate() Look in inflate_p.h for macros shared with inflateBack() @@ -298,6 +345,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { unsigned bits; /* bits in bit buffer */ uint32_t in, out; /* save starting available input and output */ unsigned copy; /* number of stored or match bytes to copy */ + unsigned char *from; /* where to copy match bytes from */ code here; /* current decoding table entry */ code last; /* parent table entry */ unsigned len; /* length to copy for repeats, bits to drop */ @@ -499,9 +547,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } - /* compute crc32 checksum if not in raw mode */ - if ((state->wrap & 4) && state->flags) - strm->adler = state->check = functable.crc32_fold_reset(&state->crc_fold); + strm->adler = state->check = CRC32_INITIAL_VALUE; state->mode = TYPE; break; #endif @@ -524,17 +570,6 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { goto inf_leave; case TYPEDO: - /* create window if it doesn't exist */ - if (state->window == NULL) { - RESTORE(); - ret = inflate_ensure_window(state); - if (ret != Z_OK) { - ZFREE_STATE(strm, state); - strm->state = NULL; - return ret; - } - LOAD(); - } /* determine and dispatch block type */ INFLATE_TYPEDO_HOOK(strm, flush); /* hook for IBM Z DFLTCC */ if (state->last) { @@ -591,24 +626,14 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* copy stored block from input to output */ copy = state->length; if (copy) { - unsigned char *end = state->window + (state->wsize * 2); - int64_t diff = end - put; - copy = MIN(copy, have); - if (copy > diff) { - if (left > 0) { - RESTORE(); - window_output_flush(strm); - LOAD(); - diff = end - put; - } - copy = MIN(copy, (uint32_t)diff); - } + copy = MIN(copy, left); if (copy == 0) goto inf_leave; memcpy(put, next, copy); have -= copy; next += copy; + left -= copy; put += copy; state->length -= copy; break; @@ -744,7 +769,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* use inflate_fast() if we have enough input and output */ if (have >= INFLATE_FAST_MIN_HAVE && left >= INFLATE_FAST_MIN_LEFT) { RESTORE(); - zng_inflate_fast(strm); + zng_inflate_fast(strm, out); LOAD(); if (state->mode == TYPE) state->back = -1; @@ -859,74 +884,70 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { Tracevv((stderr, "inflate: distance %u\n", state->offset)); state->mode = MATCH; - case MATCH: { + case MATCH: /* copy match from window to output */ if (left == 0) goto inf_leave; - - unsigned char *end = state->window + (state->wsize * 2); - int64_t buf_left = end - put; - copy = state->length; - RESTORE(); - if (copy > buf_left) { - if (strm->avail_out > 0) { - /* relies on RESTORE() above with no changes to those vars */ - window_output_flush(strm); - LOAD(); - buf_left = end - put; - } - copy = MIN(copy, (uint32_t)buf_left); - } - if (copy == 0) - goto inf_leave; - if (state->offset > state->wnext + state->whave) { - if (state->sane) { - SET_BAD("invalid distance too far back"); + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + SET_BAD("invalid distance too far back"); + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + copy = MIN(copy, state->length); + copy = MIN(copy, left); + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) + state->mode = LEN; break; +#endif } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } else { + from = state->window + (state->wnext - copy); + } + copy = MIN(copy, state->length); + copy = MIN(copy, left); + + put = chunkcopy_safe(put, from, copy, put + left); + } else { + copy = MIN(state->length, left); + + put = functable.chunkmemset_safe(put, state->offset, copy, left); } - unsigned char *next_out = state->window + state->wsize + state->wnext; - if (copy <= state->offset) { - chunkcopy_safe(next_out, next_out - state->offset, copy, put + buf_left); - } else { /* copy from output */ - functable.chunkmemset_safe(next_out, state->offset, copy, (uint32_t)buf_left); - } - state->wnext += copy; + left -= copy; state->length -= copy; - LOAD(); if (state->length == 0) state->mode = LEN; break; - } + case LIT: - if (put >= state->window + (state->wsize * 2)) { - RESTORE(); - window_output_flush(strm); - LOAD(); - } if (left == 0) goto inf_leave; *put++ = (unsigned char)(state->length); + left--; state->mode = LEN; break; case CHECK: - RESTORE(); - window_output_flush(strm); - LOAD(); - if (strm->avail_out == 0 && state->wnext) - goto inf_leave; if (state->wrap) { NEEDBITS(32); out -= left; strm->total_out += out; state->total += out; - - if (INFLATE_NEED_CHECKSUM(strm) && strm->total_out) { - /* compute crc32 final value if not in raw mode */ - if ((state->wrap & 4) && state->flags) - strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold); - } + if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out) + strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; if ((state->wrap & 4) && ( #ifdef GUNZIP @@ -976,21 +997,26 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer - error. + error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ inf_leave: RESTORE(); - - if (strm->avail_out && state->wnext) - window_output_flush(strm); - + if (INFLATE_NEED_UPDATEWINDOW(strm) && + (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH)))) { + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + } in -= strm->avail_in; out -= strm->avail_out; strm->total_in += in; strm->total_out += out; state->total += out; - + if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out) + strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) @@ -1031,10 +1057,8 @@ int32_t Z_EXPORT PREFIX(inflateGetDictionary)(PREFIX3(stream) *strm, uint8_t *di int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8_t *dictionary, uint32_t dictLength) { struct inflate_state *state; - unsigned long dictid, dict_copy, hist_copy; - const unsigned char *dict_from, *hist_from; - unsigned char *dict_to, *hist_to; - int ret; + unsigned long dictid; + int32_t ret; /* check state */ if (inflateStateCheck(strm)) @@ -1049,33 +1073,14 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8 if (dictid != state->check) return Z_DATA_ERROR; } - ret = inflate_ensure_window(state); - if (ret != Z_OK) - return Z_MEM_ERROR; - Tracec(state->wnext != 0, (stderr, "Setting dictionary with unflushed output")); - - /* copy dictionary to window and amend if necessary */ - dict_from = dictionary; - dict_copy = dictLength; - if (dict_copy > state->wsize) { - dict_copy = state->wsize; - dict_from += (dictLength - dict_copy); + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; } - dict_to = state->window + state->wsize - dict_copy; - - hist_from = state->window + state->wsize - state->whave; - hist_copy = state->wsize - dict_copy; - if (hist_copy > state->whave) - hist_copy = state->whave; - hist_to = dict_to - hist_copy; - - if (hist_copy) - memcpy(hist_to, hist_from, hist_copy); - if (dict_copy) - memcpy(dict_to, dict_from, dict_copy); - - state->whave = hist_copy + dict_copy; state->havedict = 1; Tracev((stderr, "inflate: dictionary set\n")); return Z_OK; @@ -1215,7 +1220,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou window = NULL; if (state->window != NULL) { wsize = 1U << state->wbits; - window = (unsigned char *)ZALLOC_WINDOW(state->strm, (wsize * 2) + state->chunksize, sizeof(unsigned char)); + window = (unsigned char *)ZALLOC_WINDOW(source, wsize, sizeof(unsigned char)); if (window == NULL) { ZFREE_STATE(source, copy); return Z_MEM_ERROR; @@ -1233,7 +1238,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou copy->next = copy->codes + (state->next - state->codes); if (window != NULL) { wsize = 1U << state->wbits; - memcpy(window, state->window, (wsize * 2) + state->chunksize); + memcpy(window, state->window, wsize); } copy->window = window; dest->state = (struct internal_state *)copy; diff --git a/inflate.h b/inflate.h index 3f57e78408..67041348f7 100644 --- a/inflate.h +++ b/inflate.h @@ -11,8 +11,6 @@ #ifndef INFLATE_H_ #define INFLATE_H_ -#include "crc32_fold.h" - /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ @@ -103,8 +101,6 @@ struct inflate_state { uint32_t wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if needed */ - struct crc32_fold_s ALIGNED_(16) crc_fold; - /* bit accumulator */ uint32_t hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ diff --git a/inflate_p.h b/inflate_p.h index fd3343a9bf..2735c581df 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -5,9 +5,6 @@ #ifndef INFLATE_P_H #define INFLATE_P_H -#include "zbuild.h" -#include "functable.h" - /* Architecture-specific hooks. */ #ifdef S390_DFLTCC_INFLATE # include "arch/s390/dfltcc_inflate.h" @@ -35,11 +32,18 @@ # define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0) #endif - /* * Macros shared by inflate() and inflateBack() */ +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? PREFIX(crc32)(check, buf, len) : functable.adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) functable.adler32(check, buf, len) +#endif + /* check macros for header crc */ #ifdef GUNZIP # define CRC2(check, word) \ @@ -62,7 +66,7 @@ /* Load registers with state in inflate() for speed */ #define LOAD() \ do { \ - put = state->window + state->wsize + state->wnext; \ + put = strm->next_out; \ left = strm->avail_out; \ next = strm->next_in; \ have = strm->avail_in; \ @@ -73,7 +77,7 @@ /* Restore state from registers in inflate() */ #define RESTORE() \ do { \ - state->wnext = (uint32_t)(put - (state->window + state->wsize)); \ + strm->next_out = put; \ strm->avail_out = left; \ strm->next_in = (z_const unsigned char *)next; \ strm->avail_in = have; \ @@ -123,68 +127,6 @@ strm->msg = (char *)errmsg; \ } while (0) - -static inline void inf_crc_copy(PREFIX3(stream) *strm, unsigned char *const dst, - const unsigned char *const src, size_t len) { - struct inflate_state *const state = (struct inflate_state *const)strm->state; - - if (!INFLATE_NEED_CHECKSUM(strm)) - return; - - /* compute checksum if not in raw mode */ - if (state->wrap & 4) { - /* check flags to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP - if (state->flags) - functable.crc32_fold_copy(&state->crc_fold, dst, src, len); - else -#endif - { - memcpy(dst, src, len); - strm->adler = state->check = functable.adler32(state->check, dst, len); - } - } else { - memcpy(dst, src, len); - } -} - -static inline void window_output_flush(PREFIX3(stream) *strm) { - struct inflate_state *const state = (struct inflate_state *const)strm->state; - size_t write_offset, read_offset, copy_size; - uint32_t out_bytes; - - if (state->wnext > strm->avail_out) { - out_bytes = strm->avail_out; - copy_size = state->wnext - out_bytes; - } else { - out_bytes = state->wnext; - copy_size = 0; - } - - /* Copy from pending buffer to stream output */ - inf_crc_copy(strm, strm->next_out, state->window + state->wsize, out_bytes); - - strm->avail_out -= out_bytes; - strm->next_out += out_bytes; - - /* Discard bytes in sliding window */ - if (state->whave + out_bytes > state->wsize) { - write_offset = 0; - read_offset = out_bytes; - copy_size += state->wsize; - } else { - read_offset = state->wsize - state->whave; - write_offset = read_offset - out_bytes; - copy_size += state->whave + out_bytes; - } - - memmove(state->window + write_offset, state->window + read_offset, copy_size); - - state->wnext -= out_bytes; - state->whave += out_bytes; - state->whave = MIN(state->whave, state->wsize); -} - /* Behave like chunkcopy, but avoid writing beyond of legal output. */ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, unsigned len, uint8_t *safe) { uint32_t safelen = (uint32_t)((safe - out) + 1); diff --git a/test/infcover.c b/test/infcover.c index 0c355aa99c..974185d0a3 100644 --- a/test/infcover.c +++ b/test/infcover.c @@ -287,10 +287,6 @@ static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int mem_setup(&strm); strm.avail_in = 0; strm.next_in = NULL; - - mem_limit(&strm, 1); - ret = PREFIX(inflateInit2)(&strm, win); assert(ret == Z_MEM_ERROR); - mem_limit(&strm, 0); ret = PREFIX(inflateInit2)(&strm, win); if (ret != Z_OK) { mem_done(&strm, what); @@ -323,6 +319,10 @@ static void inf(char *hex, char *what, unsigned step, int win, unsigned len, int if (ret == Z_NEED_DICT) { ret = PREFIX(inflateSetDictionary)(&strm, in, 1); assert(ret == Z_DATA_ERROR); + mem_limit(&strm, 1); + ret = PREFIX(inflateSetDictionary)(&strm, out, 0); + assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); ((struct inflate_state *)strm.state)->mode = DICT; ret = PREFIX(inflateSetDictionary)(&strm, out, 0); assert(ret == Z_OK); @@ -416,6 +416,10 @@ static void cover_wrap(void) { strm.next_in = (void *)"\x63"; strm.avail_out = 1; strm.next_out = (void *)&ret; + mem_limit(&strm, 1); + ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); + ret = PREFIX(inflate)(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); memset(dict, 0, 257); ret = PREFIX(inflateSetDictionary)(&strm, dict, 257); assert(ret == Z_OK); From 099d7ca7de877e206f4dc3960675808990d4d736 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 19 Mar 2022 15:34:09 -0700 Subject: [PATCH 333/798] Use zmemcmp_2 in 16-bit unaligned compare256 variant. --- compare256.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compare256.c b/compare256.c index 609e6181ae..3c05969f9f 100644 --- a/compare256.c +++ b/compare256.c @@ -61,16 +61,16 @@ static inline uint32_t compare256_unaligned_16_static(const uint8_t *src0, const uint32_t len = 0; do { - if (*(uint16_t *)src0 != *(uint16_t *)src1) + if (zmemcmp_2(src0, src1) != 0) return len + (*src0 == *src1); src0 += 2, src1 += 2, len += 2; - if (*(uint16_t *)src0 != *(uint16_t *)src1) + if (zmemcmp_2(src0, src1) != 0) return len + (*src0 == *src1); src0 += 2, src1 += 2, len += 2; - if (*(uint16_t *)src0 != *(uint16_t *)src1) + if (zmemcmp_2(src0, src1) != 0) return len + (*src0 == *src1); src0 += 2, src1 += 2, len += 2; - if (*(uint16_t *)src0 != *(uint16_t *)src1) + if (zmemcmp_2(src0, src1) != 0) return len + (*src0 == *src1); src0 += 2, src1 += 2, len += 2; } while (len < 256); From 7069f42c9ca511423dc6804390ad765122aab378 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 19 Mar 2022 15:53:30 -0700 Subject: [PATCH 334/798] Fixed missing checks around compare256 and longest_match definitions. --- cpu_features.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cpu_features.h b/cpu_features.h index 54b798b930..eb741ab864 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -117,8 +117,10 @@ typedef uint32_t (*compare256_func)(const uint8_t *src0, const uint8_t *src1); extern uint32_t compare256_c(const uint8_t *src0, const uint8_t *src1); #ifdef UNALIGNED_OK extern uint32_t compare256_unaligned_16(const uint8_t *src0, const uint8_t *src1); +#ifdef HAVE_BUILTIN_CTZ extern uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1); -#ifdef UNALIGNED64_OK +#endif +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) extern uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1); #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) @@ -142,8 +144,10 @@ extern void insert_string_acle(deflate_state *const s, const uint32_t str, uint3 extern uint32_t longest_match_c(deflate_state *const s, Pos cur_match); #ifdef UNALIGNED_OK extern uint32_t longest_match_unaligned_16(deflate_state *const s, Pos cur_match); +#ifdef HAVE_BUILTIN_CTZ extern uint32_t longest_match_unaligned_32(deflate_state *const s, Pos cur_match); -#ifdef UNALIGNED64_OK +#endif +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) extern uint32_t longest_match_unaligned_64(deflate_state *const s, Pos cur_match); #endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) From 7db13e652aad702f68331a929e1990679a8a771a Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 20 Mar 2022 11:44:32 -0400 Subject: [PATCH 335/798] Rename adler32_sse41 to adler32_ssse3 As it turns out, the sum of absolute differences instruction _did_ exist in SSSE3 all along. SSE41 introduced a stranger, less commonly used variation of the sum of absolute difference instruction. Knowing this, the old SSSE3 method can be axed entirely and the SSE41 method can now be used on CPUs only having SSSE3. Removing this extra functable entry shrinks the code and allows for a simpler planned refactor later for the adler checksum and copy elision. --- CMakeLists.txt | 6 +- arch/x86/Makefile.in | 7 - arch/x86/adler32_sse41.c | 169 ----------------------- arch/x86/adler32_ssse3.c | 193 ++++++++++++++++++--------- configure | 6 +- cpu_features.h | 3 - functable.c | 4 - test/benchmarks/benchmark_adler32.cc | 3 - 8 files changed, 130 insertions(+), 261 deletions(-) delete mode 100644 arch/x86/adler32_sse41.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e18a39451f..883e794585 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -734,11 +734,7 @@ if(WITH_OPTIM) if(WITH_SSE41) check_sse41_intrinsics() if(HAVE_SSE41_INTRIN) - add_definitions(-DX86_SSE41 -DX86_SSE41_ADLER32) - set(SSE41_SRCS ${ARCHDIR}/adler32_sse41.c) - add_feature_info(SSE4_ADLER32 1 "Support SSE41-accelerated adler32, using \"${SSE41FLAG}\"") - list(APPEND ZLIB_ARCH_SRCS ${SSE41_SRCS}) - set_property(SOURCE ${SSE41_SRCS} PROPERTY COMPILE_FLAGS "${SSE41FLAG} ${NOLTOFLAG}") + add_definitions(-DX86_SSE41) else() set(WITH_SSE41 OFF) endif() diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 2b90e2ad83..05cf144b3e 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -28,7 +28,6 @@ all: \ adler32_avx2.o adler32_avx2.lo \ adler32_avx512.o adler32_avx512.lo \ adler32_avx512_vnni.o adler32_avx512_vnni.lo \ - adler32_sse41.o adler32_sse41.lo \ adler32_ssse3.o adler32_ssse3.lo \ chunkset_avx.o chunkset_avx.lo \ chunkset_sse2.o chunkset_sse2.lo \ @@ -118,12 +117,6 @@ adler32_avx512_vnni.o: $(SRCDIR)/adler32_avx512_vnni.c adler32_avx512_vnni.lo: $(SRCDIR)/adler32_avx512_vnni.c $(CC) $(SFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c -adler32_sse41.o: $(SRCDIR)/adler32_sse41.c - $(CC) $(CFLAGS) $(SSE41FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_sse41.c - -adler32_sse41.lo: $(SRCDIR)/adler32_sse41.c - $(CC) $(SFLAGS) $(SSE41FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_sse41.c - adler32_ssse3.o: $(SRCDIR)/adler32_ssse3.c $(CC) $(CFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c diff --git a/arch/x86/adler32_sse41.c b/arch/x86/adler32_sse41.c deleted file mode 100644 index 602f8ec1de..0000000000 --- a/arch/x86/adler32_sse41.c +++ /dev/null @@ -1,169 +0,0 @@ -/* adler32_sse41.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler - * Authors: - * Adam Stylinski - * Brian Bockelman - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "../../zbuild.h" -#include "../../adler32_p.h" - -#ifdef X86_SSE41_ADLER32 - -#include - -static inline uint32_t partial_hsum(__m128i x) { - __m128i second_int = _mm_bsrli_si128(x, 8); - __m128i sum = _mm_add_epi32(x, second_int); - return _mm_cvtsi128_si32(sum); -} - -static inline uint32_t hsum(__m128i x) { - __m128i sum1 = _mm_unpackhi_epi64(x, x); - __m128i sum2 = _mm_add_epi32(x, sum1); - __m128i sum3 = _mm_shuffle_epi32(sum2, 0x01); - __m128i sum4 = _mm_add_epi32(sum2, sum3); - return _mm_cvtsi128_si32(sum4); -} - -Z_INTERNAL uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size_t len) { - uint32_t sum2; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) - return adler32_len_1(adler, buf, sum2); - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (UNLIKELY(buf == NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (UNLIKELY(len < 16)) - return adler32_len_16(adler, buf, len, sum2); - - const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); - const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); - const __m128i dot3v = _mm_set1_epi16(1); - const __m128i zero = _mm_setzero_si128(); - - __m128i vbuf, vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, - vbuf_0, v_sad_sum2, vsum2, vsum2_0; - - /* If our buffer is unaligned (likely), make the determination whether - * or not there's enough of a buffer to consume to make the scalar, aligning - * additions worthwhile or if it's worth it to just eat the cost of an unaligned - * load. This is a pretty simple test, just test if 16 - the remainder + len is - * < 16 */ - int max_iters = NMAX; - int rem = (uintptr_t)buf & 15; - int align_offset = 16 - rem; - int k = 0; - if (rem) { - if (len < 16 + align_offset) { - /* Let's eat the cost of this one unaligned load so that - * we don't completely skip over the vectorization. Doing - * 16 bytes at a time unaligned is is better than 16 + <= 15 - * sums */ - vbuf = _mm_loadu_si128((__m128i*)buf); - len -= 16; - buf += 16; - vs1 = _mm_cvtsi32_si128(adler); - vs2 = _mm_cvtsi32_si128(sum2); - vs3 = _mm_setzero_si128(); - vs1_0 = vs1; - goto unaligned_jmp; - } - - for (int i = 0; i < align_offset; ++i) { - adler += *(buf++); - sum2 += adler; - } - - /* lop off the max number of sums based on the scalar sums done - * above */ - len -= align_offset; - max_iters -= align_offset; - } - - - while (len >= 16) { - vs1 = _mm_cvtsi32_si128(adler); - vs2 = _mm_cvtsi32_si128(sum2); - vs3 = _mm_setzero_si128(); - vs2_0 = _mm_setzero_si128(); - vs1_0 = vs1; - - k = (len < max_iters ? (int)len : max_iters); - k -= k % 16; - len -= k; - - while (k >= 32) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - vbuf = _mm_load_si128((__m128i*)buf); - vbuf_0 = _mm_load_si128((__m128i*)(buf + 16)); - buf += 32; - k -= 32; - - v_sad_sum1 = _mm_sad_epu8(vbuf, zero); - v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); - vs1 = _mm_add_epi32(v_sad_sum1, vs1); - vs3 = _mm_add_epi32(vs1_0, vs3); - - vs1 = _mm_add_epi32(v_sad_sum2, vs1); - v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); - vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); - vs2 = _mm_add_epi32(vsum2, vs2); - vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); - vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); - vs1_0 = vs1; - } - - vs2 = _mm_add_epi32(vs2_0, vs2); - vs3 = _mm_slli_epi32(vs3, 5); - vs2 = _mm_add_epi32(vs3, vs2); - vs3 = _mm_setzero_si128(); - - while (k >= 16) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - vbuf = _mm_load_si128((__m128i*)buf); - buf += 16; - k -= 16; - -unaligned_jmp: - v_sad_sum1 = _mm_sad_epu8(vbuf, zero); - vs1 = _mm_add_epi32(v_sad_sum1, vs1); - vs3 = _mm_add_epi32(vs1_0, vs3); - v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); - vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vs2 = _mm_add_epi32(vsum2, vs2); - vs1_0 = vs1; - } - - vs3 = _mm_slli_epi32(vs3, 4); - vs2 = _mm_add_epi32(vs2, vs3); - - /* We don't actually need to do a full horizontal sum, since psadbw is actually doing - * a partial reduction sum implicitly and only summing to integers in vector positions - * 0 and 2. This saves us some contention on the shuffle port(s) */ - adler = partial_hsum(vs1) % BASE; - sum2 = hsum(vs2) % BASE; - max_iters = NMAX; - } - - /* Process tail (len < 16). */ - return adler32_len_16(adler, buf, len, sum2); -} - -#endif diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 57357d59c9..1767572a04 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -1,6 +1,7 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream +/* adler32_ssse3.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011 Mark Adler * Authors: + * Adam Stylinski * Brian Bockelman * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,6 +13,20 @@ #include +static inline uint32_t partial_hsum(__m128i x) { + __m128i second_int = _mm_bsrli_si128(x, 8); + __m128i sum = _mm_add_epi32(x, second_int); + return _mm_cvtsi128_si32(sum); +} + +static inline uint32_t hsum(__m128i x) { + __m128i sum1 = _mm_unpackhi_epi64(x, x); + __m128i sum2 = _mm_add_epi32(x, sum1); + __m128i sum3 = _mm_shuffle_epi32(sum2, 0x01); + __m128i sum4 = _mm_add_epi32(sum2, sum3); + return _mm_cvtsi128_si32(sum4); +} + Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t sum2; @@ -31,74 +46,120 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size if (UNLIKELY(len < 16)) return adler32_len_16(adler, buf, len, sum2); - uint32_t ALIGNED_(16) s1[4], s2[4]; - - s1[0] = s1[1] = s1[2] = 0; s1[3] = adler; - s2[0] = s2[1] = s2[2] = 0; s2[3] = sum2; - - char ALIGNED_(16) dot1[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; - __m128i dot1v = _mm_load_si128((__m128i*)dot1); - char ALIGNED_(16) dot2[16] = {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; - __m128i dot2v = _mm_load_si128((__m128i*)dot2); - short ALIGNED_(16) dot3[8] = {1, 1, 1, 1, 1, 1, 1, 1}; - __m128i dot3v = _mm_load_si128((__m128i*)dot3); - - // We will need to multiply by - //char ALIGNED_(16) shift[4] = {0, 0, 0, 4}; //{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}; + const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); + const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i dot3v = _mm_set1_epi16(1); + const __m128i zero = _mm_setzero_si128(); + + __m128i vbuf, vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, + vbuf_0, v_sad_sum2, vsum2, vsum2_0; + + /* If our buffer is unaligned (likely), make the determination whether + * or not there's enough of a buffer to consume to make the scalar, aligning + * additions worthwhile or if it's worth it to just eat the cost of an unaligned + * load. This is a pretty simple test, just test if 16 - the remainder + len is + * < 16 */ + int max_iters = NMAX; + int rem = (uintptr_t)buf & 15; + int align_offset = 16 - rem; + int k = 0; + if (rem) { + if (len < 16 + align_offset) { + /* Let's eat the cost of this one unaligned load so that + * we don't completely skip over the vectorization. Doing + * 16 bytes at a time unaligned is is better than 16 + <= 15 + * sums */ + vbuf = _mm_loadu_si128((__m128i*)buf); + len -= 16; + buf += 16; + vs1 = _mm_cvtsi32_si128(adler); + vs2 = _mm_cvtsi32_si128(sum2); + vs3 = _mm_setzero_si128(); + vs1_0 = vs1; + goto unaligned_jmp; + } + + for (int i = 0; i < align_offset; ++i) { + adler += *(buf++); + sum2 += adler; + } + + /* lop off the max number of sums based on the scalar sums done + * above */ + len -= align_offset; + max_iters -= align_offset; + } - char ALIGNED_(16) shift[16] = {4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - __m128i shiftv = _mm_load_si128((__m128i*)shift); while (len >= 16) { - __m128i vs1 = _mm_load_si128((__m128i*)s1); - __m128i vs2 = _mm_load_si128((__m128i*)s2); - __m128i vs1_0 = vs1; - - int k = (len < NMAX ? (int)len : NMAX); - k -= k % 16; - len -= k; - - while (k >= 16) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - - NOTE: 256-bit equivalents are: - _mm256_maddubs_epi16 <- operates on 32 bytes to 16 shorts - _mm256_madd_epi16 <- Sums 16 shorts to 8 int32_t. - We could rewrite the below to use 256-bit instructions instead of 128-bit. - */ - __m128i vbuf = _mm_loadu_si128((__m128i*)buf); - buf += 16; - k -= 16; - - __m128i v_short_sum1 = _mm_maddubs_epi16(vbuf, dot1v); // multiply-add, resulting in 8 shorts. - __m128i vsum1 = _mm_madd_epi16(v_short_sum1, dot3v); // sum 8 shorts to 4 int32_t; - __m128i v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); - vs1 = _mm_add_epi32(vsum1, vs1); - __m128i vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vs1_0 = _mm_sll_epi32(vs1_0, shiftv); - vsum2 = _mm_add_epi32(vsum2, vs2); - vs2 = _mm_add_epi32(vsum2, vs1_0); - vs1_0 = vs1; - } - - // At this point, we have partial sums stored in vs1 and vs2. There are AVX512 instructions that - // would allow us to sum these quickly (VP4DPWSSD). For now, just unpack and move on. - - uint32_t ALIGNED_(16) s1_unpack[4]; - uint32_t ALIGNED_(16) s2_unpack[4]; - - _mm_store_si128((__m128i*)s1_unpack, vs1); - _mm_store_si128((__m128i*)s2_unpack, vs2); - - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE); - adler %= BASE; - s1[3] = adler; - - sum2 = (s2_unpack[0] % BASE) + (s2_unpack[1] % BASE) + (s2_unpack[2] % BASE) + (s2_unpack[3] % BASE); - sum2 %= BASE; - s2[3] = sum2; + vs1 = _mm_cvtsi32_si128(adler); + vs2 = _mm_cvtsi32_si128(sum2); + vs3 = _mm_setzero_si128(); + vs2_0 = _mm_setzero_si128(); + vs1_0 = vs1; + + k = (len < max_iters ? (int)len : max_iters); + k -= k % 16; + len -= k; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_load_si128((__m128i*)buf); + vbuf_0 = _mm_load_si128((__m128i*)(buf + 16)); + buf += 32; + k -= 32; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + + vs1 = _mm_add_epi32(v_sad_sum2, vs1); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); + vs2 = _mm_add_epi32(vsum2, vs2); + vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); + vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); + vs1_0 = vs1; + } + + vs2 = _mm_add_epi32(vs2_0, vs2); + vs3 = _mm_slli_epi32(vs3, 5); + vs2 = _mm_add_epi32(vs3, vs2); + vs3 = _mm_setzero_si128(); + + while (k >= 16) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_load_si128((__m128i*)buf); + buf += 16; + k -= 16; + +unaligned_jmp: + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + vs3 = _mm_slli_epi32(vs3, 4); + vs2 = _mm_add_epi32(vs2, vs3); + + /* We don't actually need to do a full horizontal sum, since psadbw is actually doing + * a partial reduction sum implicitly and only summing to integers in vector positions + * 0 and 2. This saves us some contention on the shuffle port(s) */ + adler = partial_hsum(vs1) % BASE; + sum2 = hsum(vs2) % BASE; + max_iters = NMAX; } /* Process tail (len < 16). */ diff --git a/configure b/configure index 4bc0ee9cb1..b8216abf97 100755 --- a/configure +++ b/configure @@ -1536,10 +1536,8 @@ case "${ARCH}" in check_sse41_intrinsics if test ${HAVE_SSE41_INTRIN} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE41_ADLER32" - SFLAGS="${SFLAGS} -DX86_SSE41_ADLER32" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_sse41.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_sse41.lo" + CFLAGS="${CFLAGS} -DX86_SSE41" + SFLAGS="${SFLAGS} -DX86_SSE41" fi check_sse42_intrinsics diff --git a/cpu_features.h b/cpu_features.h index eb741ab864..7cc74a97ad 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -31,9 +31,6 @@ extern uint32_t adler32_neon(uint32_t adler, const unsigned char *buf, size_t le #ifdef PPC_VMX_ADLER32 extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len); #endif -#ifdef X86_SSE41_ADLER32 -extern uint32_t adler32_sse41(uint32_t adler, const unsigned char *buf, size_t len); -#endif #ifdef X86_SSSE3_ADLER32 extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); #endif diff --git a/functable.c b/functable.c index f39db29554..a4ad297802 100644 --- a/functable.c +++ b/functable.c @@ -161,10 +161,6 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ if (x86_cpu_has_ssse3) functable.adler32 = &adler32_ssse3; #endif -#ifdef X86_SSE41_ADLER32 - if (x86_cpu_has_sse41) - functable.adler32 = &adler32_sse41; -#endif #ifdef X86_AVX2_ADLER32 if (x86_cpu_has_avx2) functable.adler32 = &adler32_avx2; diff --git a/test/benchmarks/benchmark_adler32.cc b/test/benchmarks/benchmark_adler32.cc index 7aa46c2634..b691c23ff8 100644 --- a/test/benchmarks/benchmark_adler32.cc +++ b/test/benchmarks/benchmark_adler32.cc @@ -78,9 +78,6 @@ BENCHMARK_ADLER32(power8, adler32_power8, power_cpu_has_arch_2_07); #ifdef X86_SSSE3_ADLER32 BENCHMARK_ADLER32(ssse3, adler32_ssse3, x86_cpu_has_ssse3); #endif -#ifdef X86_SSE41_ADLER32 -BENCHMARK_ADLER32(sse41, adler32_sse41, x86_cpu_has_sse41); -#endif #ifdef X86_AVX2_ADLER32 BENCHMARK_ADLER32(avx2, adler32_avx2, x86_cpu_has_avx2); #endif From 523dfefc60c261bf0b8b73ab85116b5a3bc1bd29 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 21 Mar 2022 11:58:07 -0700 Subject: [PATCH 336/798] Update language around ABI compatibility with zlib. #1081 --- PORTING.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/PORTING.md b/PORTING.md index eda2608da4..1f2c7d62d5 100644 --- a/PORTING.md +++ b/PORTING.md @@ -9,11 +9,19 @@ zlib-compat mode Zlib-ng can be compiled in zlib-compat mode, suitable for zlib-replacement in a single application or system-wide. -Please note that zlib-ng in zlib-compat mode is API-compatible but not -ABI-compatible, meaning that you cannot simply replace the zlib library/dll -files and expect the application to work. The application will need to be +Please note that zlib-ng in zlib-compat mode tries to maintain both API and +ABI compatibility with the original zlib. Any issues regarding compatibility +can be reported as bugs. + +In certain instances you may not be able to simply replace the zlib library/dll +files and expect the application to work. The application may need to be recompiled against the zlib-ng headers and libs to ensure full compatibility. +It is also possible for the deflate output stream to differ from the original +zlib due to algorithmic differences between the two libraries. Any tests or +applications that depend on the exact length of the deflate stream being a +certain value will need to be updated. + **Advantages:** - Easy to port to, since it only requires a recompile of the application and no changes to the application code. From 23c9191c01bf54f9d1ee03e3e82fac0aebcc1f15 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Fri, 18 Mar 2022 19:18:10 -0400 Subject: [PATCH 337/798] Fix an issue with the ubsan for overflow While this didn't _actually_ cause any issues for us, technically the _mm512_reduce_add_epi32() intrinsics returns a signed integer and it does the very last summation in scalar GPRs as signed integers. While the ALU still did the math properly (the negative representation is the same addition in hardware, just interpreted differently), the sanitizer caught window of inputs here definitely outside the range of a signed integer for this immediate operation. The solution, as silly as it may seem, would be to implement our own 32 bit horizontal sum function that does all of the work in vector registers. This allows us to implicitly keep things in vector register domain and convert at the very end after we've summed the summation. The compiler's sanitizer doesn't know the wiser and the solution still results in being correct. --- CMakeLists.txt | 1 + arch/x86/adler32_avx512.c | 26 ++----------------- arch/x86/adler32_avx512_p.h | 46 ++++++++++++++++++++++++++++++++++ arch/x86/adler32_avx512_vnni.c | 27 ++------------------ 4 files changed, 51 insertions(+), 49 deletions(-) create mode 100644 arch/x86/adler32_avx512_p.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 883e794585..2bc748a8b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -711,6 +711,7 @@ if(WITH_OPTIM) list(APPEND AVX512_SRCS ${ARCHDIR}/adler32_avx512.c) add_feature_info(AVX512_ADLER32 1 "Support AVX512-accelerated adler32, using \"${AVX512FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${AVX512_SRCS}) + list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/adler32_avx512_p.h) if(HAVE_MASK_INTRIN) add_definitions(-DX86_MASK_INTRIN) endif() diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index c6327167a5..05f8068a60 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -10,32 +10,10 @@ #include "../../adler32_p.h" #include "../../cpu_features.h" #include "../../fallback_builtins.h" - #include +#include "adler32_avx512_p.h" #ifdef X86_AVX512_ADLER32 -static inline uint32_t partial_hsum(__m512i x) { - /* We need a permutation vector to extract every other integer. The - * rest are going to be zeros. Marking this const so the compiler stands - * a better chance of keeping this resident in a register through entire - * loop execution. We certainly have enough zmm registers (32) */ - const __m512i perm_vec = _mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, - 1, 1, 1, 1, 1, 1, 1, 1); - - __m512i non_zero = _mm512_permutexvar_epi32(perm_vec, x); - - /* From here, it's a simple 256 bit wide reduction sum */ - __m256i non_zero_avx = _mm512_castsi512_si256(non_zero); - - /* See Agner Fog's vectorclass for a decent reference. Essentially, phadd is - * pretty slow, much slower than the longer instruction sequence below */ - __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(non_zero_avx, 1), - _mm256_castsi256_si128(non_zero_avx)); - __m128i sum2 = _mm_add_epi32(sum1,_mm_unpackhi_epi64(sum1, sum1)); - __m128i sum3 = _mm_add_epi32(sum2,_mm_shuffle_epi32(sum2, 1)); - return (uint32_t)_mm_cvtsi128_si32(sum3); -} - Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t sum2; @@ -112,7 +90,7 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, siz adler = partial_hsum(vs1) % BASE; vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); - sum2 = _mm512_reduce_add_epi32(vs2) % BASE; + sum2 = _mm512_reduce_add_epu32(vs2) % BASE; vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); } diff --git a/arch/x86/adler32_avx512_p.h b/arch/x86/adler32_avx512_p.h new file mode 100644 index 0000000000..3751a449e1 --- /dev/null +++ b/arch/x86/adler32_avx512_p.h @@ -0,0 +1,46 @@ +#ifndef AVX512_FUNCS_H +#define AVX512_FUNCS_H + +#include +#include +/* Written because *_add_epi32(a) sets off ubsan */ +static inline uint32_t _mm512_reduce_add_epu32(__m512i x) { + __m256i a = _mm512_extracti64x4_epi64(x, 1); + __m256i b = _mm512_extracti64x4_epi64(x, 0); + + __m256i a_plus_b = _mm256_add_epi32(a, b); + __m128i c = _mm256_extracti128_si256(a_plus_b, 1); + __m128i d = _mm256_extracti128_si256(a_plus_b, 0); + __m128i c_plus_d = _mm_add_epi32(c, d); + + __m128i sum1 = _mm_unpackhi_epi64(c_plus_d, c_plus_d); + __m128i sum2 = _mm_add_epi32(sum1, c_plus_d); + __m128i sum3 = _mm_shuffle_epi32(sum2, 0x01); + __m128i sum4 = _mm_add_epi32(sum2, sum3); + + return _mm_cvtsi128_si32(sum4); +} + +static inline uint32_t partial_hsum(__m512i x) { + /* We need a permutation vector to extract every other integer. The + * rest are going to be zeros. Marking this const so the compiler stands + * a better chance of keeping this resident in a register through entire + * loop execution. We certainly have enough zmm registers (32) */ + const __m512i perm_vec = _mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, + 1, 1, 1, 1, 1, 1, 1, 1); + + __m512i non_zero = _mm512_permutexvar_epi32(perm_vec, x); + + /* From here, it's a simple 256 bit wide reduction sum */ + __m256i non_zero_avx = _mm512_castsi512_si256(non_zero); + + /* See Agner Fog's vectorclass for a decent reference. Essentially, phadd is + * pretty slow, much slower than the longer instruction sequence below */ + __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(non_zero_avx, 1), + _mm256_castsi256_si128(non_zero_avx)); + __m128i sum2 = _mm_add_epi32(sum1,_mm_unpackhi_epi64(sum1, sum1)); + __m128i sum3 = _mm_add_epi32(sum2,_mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} + +#endif diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index ff0a9b580b..180f7f413e 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -11,33 +11,10 @@ #include "../../adler32_p.h" #include "../../cpu_features.h" #include "../../fallback_builtins.h" - #include +#include "adler32_avx512_p.h" #ifdef X86_AVX512VNNI_ADLER32 - -static inline uint32_t partial_hsum(__m512i x) { - /* We need a permutation vector to extract every other integer. The - * rest are going to be zeros. Marking this const so the compiler stands - * a better chance of keeping this resident in a register through entire - * loop execution. We certainly have enough zmm registers (32) */ - const __m512i perm_vec = _mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, - 1, 1, 1, 1, 1, 1, 1, 1); - - __m512i non_zero = _mm512_permutexvar_epi32(perm_vec, x); - - /* From here, it's a simple 256 bit wide reduction sum */ - __m256i non_zero_avx = _mm512_castsi512_si256(non_zero); - - /* See Agner Fog's vectorclass for a decent reference. Essentially, phadd is - * pretty slow, much slower than the longer instruction sequence below */ - __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(non_zero_avx, 1), - _mm256_castsi256_si128(non_zero_avx)); - __m128i sum2 = _mm_add_epi32(sum1,_mm_unpackhi_epi64(sum1, sum1)); - __m128i sum3 = _mm_add_epi32(sum2,_mm_shuffle_epi32(sum2, 1)); - return (uint32_t)_mm_cvtsi128_si32(sum3); -} - Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t sum2; @@ -142,7 +119,7 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf adler = partial_hsum(vs1) % BASE; vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); - sum2 = _mm512_reduce_add_epi32(vs2) % BASE; + sum2 = _mm512_reduce_add_epu32(vs2) % BASE; vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); } From 3a900fe47b95c44a1c8a1812ebfdb623d828d1a9 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 22 Mar 2022 19:39:41 -0400 Subject: [PATCH 338/798] Fixed a warning about a comparison of an unsigned with a signed type --- arch/x86/adler32_ssse3.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 1767572a04..5d28ac95fc 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -59,10 +59,10 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size * additions worthwhile or if it's worth it to just eat the cost of an unaligned * load. This is a pretty simple test, just test if 16 - the remainder + len is * < 16 */ - int max_iters = NMAX; - int rem = (uintptr_t)buf & 15; - int align_offset = 16 - rem; - int k = 0; + uint32_t max_iters = NMAX; + uint32_t rem = (uintptr_t)buf & 15; + uint32_t align_offset = 16 - rem; + uint32_t k = 0; if (rem) { if (len < 16 + align_offset) { /* Let's eat the cost of this one unaligned load so that @@ -79,7 +79,7 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size goto unaligned_jmp; } - for (int i = 0; i < align_offset; ++i) { + for (uint32_t i = 0; i < align_offset; ++i) { adler += *(buf++); sum2 += adler; } @@ -98,7 +98,7 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size vs2_0 = _mm_setzero_si128(); vs1_0 = vs1; - k = (len < max_iters ? (int)len : max_iters); + k = (len < max_iters ? len : max_iters); k -= k % 16; len -= k; From 5d41da9c443ac5e2e51f356abb27e7f0034790be Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 18 Mar 2022 12:10:27 -0700 Subject: [PATCH 339/798] Add unit tests for compare256 variants. --- test/test_compare256.cc | 75 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 test/test_compare256.cc diff --git a/test/test_compare256.cc b/test/test_compare256.cc new file mode 100644 index 0000000000..3f0673e242 --- /dev/null +++ b/test/test_compare256.cc @@ -0,0 +1,75 @@ +/* test_compare256.cc -- compare256 unit tests + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include + +extern "C" { +# include "zbuild.h" +# include "zutil_p.h" +# include "cpu_features.h" +} + +#include + +#define MAX_COMPARE_SIZE (256) + +/* Ensure that compare256 returns the correct match length */ +static inline void compare256_match_check(compare256_func compare256) { + int32_t match_len, i; + uint8_t *str1; + uint8_t *str2; + + str1 = (uint8_t *)zng_alloc(MAX_COMPARE_SIZE); + ASSERT_TRUE(str1 != NULL); + memset(str1, 'a', MAX_COMPARE_SIZE); + + str2 = (uint8_t *)zng_alloc(MAX_COMPARE_SIZE); + ASSERT_TRUE(str2 != NULL); + memset(str2, 'a', MAX_COMPARE_SIZE); + + for (i = 0; i <= MAX_COMPARE_SIZE; i++) { + if (i < MAX_COMPARE_SIZE) + str2[i] = 0; + + match_len = compare256(str1, str2); + EXPECT_EQ(match_len, i); + + if (i < MAX_COMPARE_SIZE) + str2[i] = 'a'; + } + + zng_free(str1); + zng_free(str2); +} + +#define TEST_COMPARE256(name, func, support_flag) \ + TEST(compare256, name) { \ + if (!support_flag) { \ + GTEST_SKIP(); \ + return; \ + } \ + compare256_match_check(func); \ + } + +TEST_COMPARE256(c, compare256_c, 1) + +#ifdef UNALIGNED_OK +TEST_COMPARE256(unaligned_16, compare256_unaligned_16, 1) +#ifdef HAVE_BUILTIN_CTZ +TEST_COMPARE256(unaligned_32, compare256_unaligned_32, 1) +#endif +#if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) +TEST_COMPARE256(unaligned_64, compare256_unaligned_64, 1) +#endif +#endif + +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) +TEST_COMPARE256(unaligned_sse2, compare256_unaligned_sse2, x86_cpu_has_sse2) +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) +TEST_COMPARE256(unaligned_avx2, compare256_unaligned_avx2, x86_cpu_has_avx2) +#endif From 7592681e97a572399dccf65814280bc103ebaedc Mon Sep 17 00:00:00 2001 From: Rich Ercolani <214141+rincebrain@users.noreply.github.com> Date: Fri, 25 Mar 2022 10:06:39 -0400 Subject: [PATCH 340/798] Correct typo in functable Now, I could be wrong about this being an error, but I don't see any discussion suggesting this was intended, so... --- functable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functable.c b/functable.c index a4ad297802..bd1e4cea70 100644 --- a/functable.c +++ b/functable.c @@ -133,7 +133,7 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc # endif # if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_sse2) - functable.longest_match = &longest_match_slow_unaligned_sse2; + functable.longest_match_slow = &longest_match_slow_unaligned_sse2; # endif # if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) if (x86_cpu_has_avx2) From d979b89e00b398d548460daebb99c104f88267bc Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 16 Mar 2022 14:10:14 -0700 Subject: [PATCH 341/798] Fixed MSVC warnings in chunkcopy_safe. inflate_p.h(244,18): warning C4018: '>': signed/unsigned mismatch inflate_p.h(234,38): warning C4244: 'initializing': conversion from '__int64' to 'int', possible loss of data inffast.c inflate_p.h(244,18): warning C4018: '>': signed/unsigned mismatch inflate_p.h(234,38): warning C4244: 'initializing': conversion from '__int64' to 'int', possible loss of data inflate.c inflate_p.h(244,18): warning C4018: '>': signed/unsigned mismatch inflate_p.h(234,38): warning C4244: 'initializing': conversion from '__int64' to 'int', possible loss of data --- inflate_p.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/inflate_p.h b/inflate_p.h index 2735c581df..87529aa6d4 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -128,12 +128,12 @@ } while (0) /* Behave like chunkcopy, but avoid writing beyond of legal output. */ -static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, unsigned len, uint8_t *safe) { +static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, size_t len, uint8_t *safe) { uint32_t safelen = (uint32_t)((safe - out) + 1); len = MIN(len, safelen); - int olap_src = from >= out && from < out + len; - int olap_dst = out >= from && out < from + len; - int tocopy; + int32_t olap_src = from >= out && from < out + len; + int32_t olap_dst = out >= from && out < from + len; + size_t tocopy; /* For all cases without overlap, memcpy is ideal */ if (!(olap_src || olap_dst)) { @@ -146,7 +146,7 @@ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, unsigned len, * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look * behind or lookahead distance */ - int non_olap_size = (from > out) ? from - out : out - from; + int32_t non_olap_size = (int32_t)((from > out) ? from - out : out - from); memcpy(out, from, non_olap_size); out += non_olap_size; From 80ab22f10065ca7756d79d7ca3ea7af728e38105 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 16 Mar 2022 14:20:23 -0700 Subject: [PATCH 342/798] Fixed signed/unsigned warning in chunkmemset. chunkset_tpl.h(107,24): warning C4018: '>': signed/unsigned mismatch --- chunkset_tpl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 9ea37225ec..f0539921ad 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -100,9 +100,9 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { { /* This code takes string of length dist from "from" and repeats * it for as many times as can fit in a chunk_t (vector register) */ - int32_t cpy_dist; - int32_t bytes_remaining = sizeof(chunk_t); - uint8_t *cur_chunk = (uint8_t*)&chunk_load; + uint32_t cpy_dist; + uint32_t bytes_remaining = sizeof(chunk_t); + uint8_t *cur_chunk = (uint8_t *)&chunk_load; while (bytes_remaining) { cpy_dist = MIN(dist, bytes_remaining); memcpy(cur_chunk, from, cpy_dist); From d49ed2d4e1d416335cb734208482f4dfd24522c1 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 16 Mar 2022 14:21:33 -0700 Subject: [PATCH 343/798] Fixed operator precedence warnings in slide_hash_sse2. slide_hash_sse2.c(58,5): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence slide_hash_sse2.c(59,5): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence --- arch/x86/slide_hash_sse2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/slide_hash_sse2.c b/arch/x86/slide_hash_sse2.c index 1bd2bebf56..5daac4a739 100644 --- a/arch/x86/slide_hash_sse2.c +++ b/arch/x86/slide_hash_sse2.c @@ -55,8 +55,8 @@ Z_INTERNAL void slide_hash_sse2(deflate_state *s) { uint16_t wsize = (uint16_t)s->w_size; const __m128i xmm_wsize = _mm_set1_epi16((short)wsize); - assert(((uintptr_t)s->head) & 15 == 0); - assert(((uintptr_t)s->prev) & 15 == 0); + assert(((uintptr_t)s->head & 15) == 0); + assert(((uintptr_t)s->prev & 15) == 0); slide_hash_chain(s->head, s->prev, HASH_SIZE, wsize, xmm_wsize); } From 7f30cc5270444792673a20a3a23fb62bbb9bfd18 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 19 Mar 2022 19:39:06 -0700 Subject: [PATCH 344/798] Fixed unused opaque variable in aligned alloc test. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test_aligned_alloc.cc: In function ‘void* zng_calloc_unaligned(void*, unsigned int, unsigned int)’: test_aligned_alloc.cc:14:34: warning: unused parameter ‘opaque’ [-Wunused-parameter] test_aligned_alloc.cc: In function ‘void zng_cfree_unaligned(void*, void*)’: test_aligned_alloc.cc:28:32: warning: unused parameter ‘opaque’ [-Wunused-parameter] --- test/test_aligned_alloc.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_aligned_alloc.cc b/test/test_aligned_alloc.cc index 43324d3db5..5d8517163f 100644 --- a/test/test_aligned_alloc.cc +++ b/test/test_aligned_alloc.cc @@ -13,6 +13,7 @@ extern "C" { void *zng_calloc_unaligned(void *opaque, unsigned items, unsigned size) { uint8_t *pointer = (uint8_t *)calloc(1, (items * size) + 2); + Z_UNUSED(opaque); if (pointer == NULL) return pointer; /* Store whether or not our allocation is aligned */ @@ -27,6 +28,7 @@ void *zng_calloc_unaligned(void *opaque, unsigned items, unsigned size) { void zng_cfree_unaligned(void *opaque, void *ptr) { uint8_t *pointer = (uint8_t *)ptr; + Z_UNUSED(opaque); pointer--; /* Get whether or not our original memory pointer was aligned */ if (*pointer) { From d955c068db33a51b1a7ab559b5dd882cbf42542a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 19 Mar 2022 19:41:24 -0700 Subject: [PATCH 345/798] Fixed signed comparison warning in zng_calloc_aligned. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit zutil.c: In function ‘zng_calloc_aligned’: zutil.c:133:20: warning: comparison of integer expressions of different signedness: ‘int32_t’ {aka ‘int’} and ‘long unsigned int’ [-Wsign-compare] --- zutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zutil.c b/zutil.c index c3ef19f5bc..2ca6aae4b2 100644 --- a/zutil.c +++ b/zutil.c @@ -114,7 +114,7 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr) { * we have to ask for extra memory and return an aligned pointer. */ void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align) { uintptr_t return_ptr, original_ptr; - int32_t alloc_size, align_diff; + uint32_t alloc_size, align_diff; void *ptr; /* If no custom calloc function used then call zlib-ng's aligned calloc */ From 10d6c17bf5f141c0a287254549b03db8486f7809 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 24 Mar 2022 13:01:21 -0700 Subject: [PATCH 346/798] Fixed error with compare256_unaligned_avx2 undefined if unaligned access is disabled. --- test/benchmarks/benchmark_compare256.cc | 5 ++--- test/test_compare256.cc | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index 09a4bbc2a6..bdfdd6bf97 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -69,11 +69,10 @@ BENCHMARK_COMPARE256(unaligned_32, compare256_unaligned_32, 1); #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) BENCHMARK_COMPARE256(unaligned_64, compare256_unaligned_64, 1); #endif -#endif - -#ifdef X86_SSE2 +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) BENCHMARK_COMPARE256(unaligned_sse2, compare256_unaligned_sse2, x86_cpu_has_sse2); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) BENCHMARK_COMPARE256(unaligned_avx2, compare256_unaligned_avx2, x86_cpu_has_avx2); #endif +#endif diff --git a/test/test_compare256.cc b/test/test_compare256.cc index 3f0673e242..2c2f3aaa87 100644 --- a/test/test_compare256.cc +++ b/test/test_compare256.cc @@ -65,11 +65,10 @@ TEST_COMPARE256(unaligned_32, compare256_unaligned_32, 1) #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) TEST_COMPARE256(unaligned_64, compare256_unaligned_64, 1) #endif -#endif - #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) TEST_COMPARE256(unaligned_sse2, compare256_unaligned_sse2, x86_cpu_has_sse2) #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) TEST_COMPARE256(unaligned_avx2, compare256_unaligned_avx2, x86_cpu_has_avx2) #endif +#endif From 33e621e3149394d4cc1db1850ae02aa06bae4425 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 26 Mar 2022 08:05:19 -0700 Subject: [PATCH 347/798] Remove detect_leaks=0 from non-ASAN cmake jobs. --- .github/workflows/cmake.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index f9e97d314c..aee9fb366b 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -132,7 +132,6 @@ jobs: - name: Ubuntu GCC ARM SF Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-arm.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabi g++-arm-linux-gnueabi libc-dev-armel-cross codecov: ubuntu_gcc_armsf_compat_no_opt @@ -160,7 +159,6 @@ jobs: - name: Ubuntu GCC ARM HF Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-armhf.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf libc-dev-armel-cross codecov: ubuntu_gcc_armhf_compat_no_opt @@ -174,42 +172,36 @@ jobs: - name: Ubuntu GCC AARCH64 No ACLE UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_ACLE=OFF -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_no_acle - name: Ubuntu GCC AARCH64 No NEON UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DWITH_NEON=OFF -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_no_neon - name: Ubuntu GCC AARCH64 Compat No Opt UBSAN os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-aarch64.cmake -DZLIB_COMPAT=ON -DWITH_NEW_STRATEGIES=OFF -DWITH_OPTIM=OFF -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc-dev-arm64-cross codecov: ubuntu_gcc_aarch64_compat_no_opt - name: Ubuntu GCC PPC os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc-dev-powerpc-cross codecov: ubuntu_gcc_ppc - name: Ubuntu GCC PPC No Power8 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc.cmake -DWITH_POWER8=OFF - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc-dev-powerpc-cross codecov: ubuntu_gcc_ppc_no_power8 - name: Ubuntu GCC PPC64 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64.cmake - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc64-linux-gnu g++-powerpc64-linux-gnu libc-dev-ppc64-cross ldflags: -static codecov: ubuntu_gcc_ppc64 @@ -217,14 +209,12 @@ jobs: - name: Ubuntu GCC PPC64LE os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc64le.cmake - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu libc-dev-ppc64el-cross codecov: ubuntu_gcc_ppc64le - name: Ubuntu GCC SPARC64 os: ubuntu-latest cmake-args: -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-sparc64.cmake - asan-options: detect_leaks=0 packages: qemu qemu-user gcc-sparc64-linux-gnu g++-sparc64-linux-gnu libc-dev-sparc64-cross ldflags: -static codecov: ubuntu_gcc_sparc64 @@ -259,7 +249,6 @@ jobs: compiler: gcc cxx-compiler: g++ cmake-args: -DZLIB_COMPAT=ON -DWITH_DFLTCC_DEFLATE=ON -DWITH_DFLTCC_INFLATE=ON -DWITH_SANITIZER=Undefined - asan-options: detect_leaks=0 ldflags: -static codecov: ubuntu_gcc_s390x_dfltcc_compat From 1bcfc5c7a289405fb4030241b21579ec525adc44 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 26 Mar 2022 08:47:01 -0700 Subject: [PATCH 348/798] Use HAVE instead of HAS for variable name for consistency. --- cmake/detect-sanitizer.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/detect-sanitizer.cmake b/cmake/detect-sanitizer.cmake index ae3d37317c..f9521ec2f5 100644 --- a/cmake/detect-sanitizer.cmake +++ b/cmake/detect-sanitizer.cmake @@ -32,12 +32,12 @@ macro(check_sanitizer_support known_checks supported_checks) set(CMAKE_REQUIRED_FLAGS -fsanitize=${compile_checks}) - check_c_source_compiles("int main() { return 0; }" HAS_SANITIZER_${check} + check_c_source_compiles("int main() { return 0; }" HAVE_SANITIZER_${check} FAIL_REGEX "not supported|unrecognized command|unknown option") set(CMAKE_REQUIRED_FLAGS) - if(HAS_SANITIZER_${check}) + if(HAVE_SANITIZER_${check}) set(available_checks ${compile_checks}) endif() endforeach() From 348f4155c7d54cf002c0f28031ac8e1668307e4c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 26 Mar 2022 10:37:29 -0700 Subject: [PATCH 349/798] Remove unistd.h include from gzguts.h which is already included from zconf.h via zlib.h. --- gzguts.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/gzguts.h b/gzguts.h index 4e71eb4b1b..7db7099088 100644 --- a/gzguts.h +++ b/gzguts.h @@ -38,10 +38,6 @@ # include #endif -#if !defined(_MSC_VER) || defined(__MINGW__) -# include /* for lseek(), read(), close(), write(), unlink() */ -#endif - #if defined(_WIN32) # include # define WIDECHAR From fadaca4a6aa20cd8bb6f70688c5bf8644b32b067 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 27 Mar 2022 09:14:45 -0700 Subject: [PATCH 350/798] Use specific gcovr version 5.0 due to parser errors with 5.1. https://github.com/gcovr/gcovr/issues/583 --- .github/workflows/cmake.yml | 2 +- .github/workflows/pigz.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index aee9fb366b..0525836169 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -486,7 +486,7 @@ jobs: if: matrix.codecov shell: bash run: | - python3 -u -m pip install --user gcovr + python3 -u -m pip install --user gcovr==5.0 python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root ${{ matrix.build-src-dir || '.' }} --xml --output coverage.xml -j 3 --verbose - name: Upload coverage report diff --git a/.github/workflows/pigz.yml b/.github/workflows/pigz.yml index 46d549f45e..e7193ee668 100644 --- a/.github/workflows/pigz.yml +++ b/.github/workflows/pigz.yml @@ -88,7 +88,7 @@ jobs: - name: Generate coverage report if: matrix.codecov run: | - python3 -u -m pip install --user gcovr + python3 -u -m pip install --user gcovr==5.0 python3 -m gcovr --exclude-unreachable-branches --gcov-executable "${{ matrix.gcov-exec || 'gcov' }}" --root . --xml --output coverage.xml -j 3 --verbose - name: Upload coverage report From 41faa0843d77f100d2f4770cecb92007cc3ea9ca Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 27 Mar 2022 13:44:58 -0700 Subject: [PATCH 351/798] Fixed clang signed/unsigned warning in chunkcopy_safe. inflate_p.h:159:18: warning: comparison of integers of different signs: 'int32_t' (aka 'int') and 'size_t' (aka 'unsigned long') [-Wsign-compare] tocopy = MIN(non_olap_size, len); ^ ~~~~~~~~~~~~~ ~~~ zbuild.h:74:24: note: expanded from macro 'MIN' #define MIN(a, b) ((a) > (b) ? (b) : (a)) ~ ^ ~ --- inflate_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inflate_p.h b/inflate_p.h index 87529aa6d4..ecc1060642 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -146,7 +146,7 @@ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, size_t len, u * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look * behind or lookahead distance */ - int32_t non_olap_size = (int32_t)((from > out) ? from - out : out - from); + size_t non_olap_size = ((from > out) ? from - out : out - from); memcpy(out, from, non_olap_size); out += non_olap_size; From 8550a90de4dcb8589a7d48fe308c4c45bba5a466 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sat, 12 Mar 2022 16:09:02 -0500 Subject: [PATCH 352/798] Leverage inline CRC + copy This brings back a bit of the performance that may have been sacrificed by reverting the reorganized inflate window. Doing a copy at the same time as a CRC is basically free. --- arch/x86/crc32_fold_pclmulqdq.c | 16 +++++-- crc32_fold.c | 9 ++++ crc32_fold.h | 1 + functable.c | 11 +++++ functable.h | 1 + inflate.c | 83 ++++++++++++++++++++++++++++----- inflate.h | 4 ++ 7 files changed, 108 insertions(+), 17 deletions(-) diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 1a7e77f0e8..9072a47e7d 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -398,18 +398,23 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t __m128i xmm_t0, xmm_t1, xmm_t2, xmm_t3; __m128i xmm_crc0, xmm_crc1, xmm_crc2, xmm_crc3, xmm_crc_part; __m128i xmm_initial = _mm_cvtsi32_si128(init_crc); - int32_t first = 1; + xmm_crc_part = _mm_setzero_si128(); + int32_t first = init_crc != 0; /* Technically the CRC functions don't even call this for input < 64, but a bare minimum of 31 * bytes of input is needed for the aligning load that occurs. If there's an initial CRC, to * carry it forward through the folded CRC there must be 16 - src % 16 + 16 bytes available, which * by definition can be up to 15 bytes + one full vector load. */ - assert(len >= 31); + assert(len >= 31 || first == 0); crc32_fold_load((__m128i *)crc->fold, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3); + if (len < 16) { + goto partial_nocpy; + } + algn_diff = ((uintptr_t)16 - ((uintptr_t)src & 0xF)) & 0xF; if (algn_diff) { - if (algn_diff >= 4) { + if (algn_diff >= 4 || init_crc == 0) { xmm_crc_part = _mm_loadu_si128((__m128i *)src); src += algn_diff; @@ -428,9 +433,9 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t src += (algn_diff + 16); len -= (algn_diff + 16); } - } - xmm_crc_part = _mm_setzero_si128(); + xmm_crc_part = _mm_setzero_si128(); + } #ifdef X86_VPCLMULQDQ_CRC if (x86_cpu_has_vpclmulqdq && x86_cpu_has_avx512 && (len >= 256)) { @@ -497,6 +502,7 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t src += 16; } +partial_nocpy: if (len) { memcpy(&xmm_crc_part, src, len); partial_fold((size_t)len, &xmm_crc0, &xmm_crc1, &xmm_crc2, &xmm_crc3, &xmm_crc_part); diff --git a/crc32_fold.c b/crc32_fold.c index 1800ed0a06..b3072e374b 100644 --- a/crc32_fold.c +++ b/crc32_fold.c @@ -17,6 +17,15 @@ Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t * memcpy(dst, src, len); } +Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { + /* Note: while this is basically the same thing as the vanilla CRC function, we still need + * a functable entry for it so that we can generically dispatch to this function with the + * same arguments for the versions that _do_ do a folding CRC but we don't want a copy. The + * init_crc is an unused argument in this context */ + Z_UNUSED(init_crc); + crc->value = functable.crc32(crc->value, src, len); +} + Z_INTERNAL uint32_t crc32_fold_final_c(crc32_fold *crc) { return crc->value; } diff --git a/crc32_fold.h b/crc32_fold.h index 8bd0b6bc2a..ecfad454e6 100644 --- a/crc32_fold.h +++ b/crc32_fold.h @@ -15,6 +15,7 @@ typedef struct crc32_fold_s { Z_INTERNAL uint32_t crc32_fold_reset_c(crc32_fold *crc); Z_INTERNAL void crc32_fold_copy_c(crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); +Z_INTERNAL void crc32_fold_c(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); Z_INTERNAL uint32_t crc32_fold_final_c(crc32_fold *crc); #endif diff --git a/functable.c b/functable.c index bd1e4cea70..3e23c54e59 100644 --- a/functable.c +++ b/functable.c @@ -206,6 +206,16 @@ Z_INTERNAL void crc32_fold_copy_stub(crc32_fold *crc, uint8_t *dst, const uint8_ functable.crc32_fold_copy(crc, dst, src, len); } +Z_INTERNAL void crc32_fold_stub(crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc) { + functable.crc32_fold = &crc32_fold_c; + cpu_check_features(); +#ifdef X86_PCLMULQDQ_CRC + if (x86_cpu_has_pclmulqdq) + functable.crc32_fold = &crc32_fold_pclmulqdq; +#endif + functable.crc32_fold(crc, src, len, init_crc); +} + Z_INTERNAL uint32_t crc32_fold_final_stub(crc32_fold *crc) { functable.crc32_fold_final = &crc32_fold_final_c; cpu_check_features(); @@ -402,6 +412,7 @@ Z_INTERNAL Z_TLS struct functable_s functable = { crc32_stub, crc32_fold_reset_stub, crc32_fold_copy_stub, + crc32_fold_stub, crc32_fold_final_stub, compare256_stub, chunksize_stub, diff --git a/functable.h b/functable.h index a106c93aab..61dde2105f 100644 --- a/functable.h +++ b/functable.h @@ -14,6 +14,7 @@ struct functable_s { uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); uint32_t (* crc32_fold_reset) (crc32_fold *crc); void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); + void (* crc32_fold) (crc32_fold *crc, const uint8_t *src, size_t len, uint32_t init_crc); uint32_t (* crc32_fold_final) (crc32_fold *crc); uint32_t (* compare256) (const uint8_t *src0, const uint8_t *src1); uint32_t (* chunksize) (void); diff --git a/inflate.c b/inflate.c index 11f7b5b084..1a0914859b 100644 --- a/inflate.c +++ b/inflate.c @@ -15,9 +15,35 @@ /* function prototypes */ static int inflateStateCheck(PREFIX3(stream) *strm); -static int updatewindow(PREFIX3(stream) *strm, const unsigned char *end, uint32_t copy); +static int updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t copy); static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t len); +static inline void inf_chksum_cpy(PREFIX3(stream) *strm, uint8_t *dst, + const uint8_t *src, uint32_t copy) { + struct inflate_state *state = (struct inflate_state*)strm->state; +#ifdef GUNZIP + if (state->flags) { + functable.crc32_fold_copy(&state->crc_fold, dst, src, copy); + } else +#endif + { + strm->adler = state->check = functable.adler32(state->check, src, copy); + memcpy(dst, src, copy); + } +} + +static inline void inf_chksum(PREFIX3(stream) *strm, const uint8_t *src, uint32_t len) { + struct inflate_state *state = (struct inflate_state*)strm->state; +#ifdef GUNZIP + if (state->flags) { + functable.crc32_fold(&state->crc_fold, src, len, 0); + } else +#endif + { + strm->adler = state->check = functable.adler32(state->check, src, len); + } +} + static int inflateStateCheck(PREFIX3(stream) *strm) { struct inflate_state *state; if (strm == NULL || strm->zalloc == NULL || strm->zfree == NULL) @@ -216,17 +242,39 @@ static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t /* copy state->wsize or less output bytes into the circular window */ if (copy >= state->wsize) { - memcpy(state->window, end - state->wsize, state->wsize); + /* Only do this if the caller specifies to checksum bytes AND the platform requires + * it (s/390 being the primary exception to this. Also, for now, do the adler checksums + * if not a gzip based header. The inline adler checksums will come in the near future, + * possibly the next commit */ + if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4)) { + /* We have to split the checksum over non-copied and copied bytes */ + if (copy > state->wsize) + inf_chksum(strm, end - copy, copy - state->wsize); + inf_chksum_cpy(strm, state->window, end - state->wsize, state->wsize); + } else { + memcpy(state->window, end - state->wsize, state->wsize); + } + state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; - if (dist > copy) - dist = copy; - memcpy(state->window + state->wnext, end - copy, dist); + /* Only do this if the caller specifies to checksum bytes AND the platform requires + * We need to maintain the correct order here for the checksum */ + dist = MIN(dist, copy); + if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4)) { + inf_chksum_cpy(strm, state->window + state->wnext, end - copy, dist); + } else { + memcpy(state->window + state->wnext, end - copy, dist); + } copy -= dist; if (copy) { - memcpy(state->window, end - copy, copy); + if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4)) { + inf_chksum_cpy(strm, state->window, end - copy, copy); + } else { + memcpy(state->window, end - copy, copy); + } + state->wnext = copy; state->whave = state->wsize; } else { @@ -480,8 +528,9 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } - if ((state->flags & 0x0200) && (state->wrap & 4)) + if ((state->flags & 0x0200) && (state->wrap & 4)) { state->check = PREFIX(crc32)(state->check, next, copy); + } have -= copy; next += copy; state->length -= copy; @@ -547,7 +596,9 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->head->hcrc = (int)((state->flags >> 9) & 1); state->head->done = 1; } - strm->adler = state->check = CRC32_INITIAL_VALUE; + /* compute crc32 checksum if not in raw mode */ + if ((state->wrap & 4) && state->flags) + strm->adler = state->check = functable.crc32_fold_reset(&state->crc_fold); state->mode = TYPE; break; #endif @@ -946,8 +997,17 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { out -= left; strm->total_out += out; state->total += out; - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out) - strm->adler = state->check = UPDATE(state->check, put - out, out); + + /* compute crc32 checksum if not in raw mode */ + if (INFLATE_NEED_CHECKSUM(strm) && state->wrap & 4) { + if (out) { + inf_chksum(strm, put - out, out); + } +#ifdef GUNZIP + if (state->flags) + strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold); +#endif + } out = left; if ((state->wrap & 4) && ( #ifdef GUNZIP @@ -1015,8 +1075,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { strm->total_in += in; strm->total_out += out; state->total += out; - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out) - strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) diff --git a/inflate.h b/inflate.h index 67041348f7..3f57e78408 100644 --- a/inflate.h +++ b/inflate.h @@ -11,6 +11,8 @@ #ifndef INFLATE_H_ #define INFLATE_H_ +#include "crc32_fold.h" + /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. For shared libraries, gzip decoding should be left enabled. */ @@ -101,6 +103,8 @@ struct inflate_state { uint32_t wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if needed */ + struct crc32_fold_s ALIGNED_(16) crc_fold; + /* bit accumulator */ uint32_t hold; /* input bit accumulator */ unsigned bits; /* number of bits in "in" */ From 81633227813d4b275a2f5a6178b3af3e683db180 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 27 Mar 2022 13:18:03 -0700 Subject: [PATCH 353/798] Allow SSE2 and AVX2 functions with -DWITH_UNALIGNED=OFF. Even though they use unaligned loads, they don't result in undefined behavior. --- arch/x86/compare256_avx2.c | 15 ++++---- arch/x86/compare256_sse2.c | 14 ++++---- cpu_features.h | 18 +++++----- functable.c | 48 ++++++++++++------------- test/benchmarks/benchmark_compare256.cc | 6 ++-- test/test_compare256.cc | 6 ++-- 6 files changed, 53 insertions(+), 54 deletions(-) diff --git a/arch/x86/compare256_avx2.c b/arch/x86/compare256_avx2.c index e25fa93eb9..1318a0e333 100644 --- a/arch/x86/compare256_avx2.c +++ b/arch/x86/compare256_avx2.c @@ -14,8 +14,7 @@ # include #endif -/* AVX2 unaligned intrinsic comparison */ -static inline uint32_t compare256_unaligned_avx2_static(const uint8_t *src0, const uint8_t *src1) { +static inline uint32_t compare256_avx2_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; do { @@ -46,18 +45,18 @@ static inline uint32_t compare256_unaligned_avx2_static(const uint8_t *src0, con return 256; } -Z_INTERNAL uint32_t compare256_unaligned_avx2(const uint8_t *src0, const uint8_t *src1) { - return compare256_unaligned_avx2_static(src0, src1); +Z_INTERNAL uint32_t compare256_avx2(const uint8_t *src0, const uint8_t *src1) { + return compare256_avx2_static(src0, src1); } -#define LONGEST_MATCH longest_match_unaligned_avx2 -#define COMPARE256 compare256_unaligned_avx2_static +#define LONGEST_MATCH longest_match_avx2 +#define COMPARE256 compare256_avx2_static #include "match_tpl.h" #define LONGEST_MATCH_SLOW -#define LONGEST_MATCH longest_match_slow_unaligned_avx2 -#define COMPARE256 compare256_unaligned_avx2_static +#define LONGEST_MATCH longest_match_slow_avx2 +#define COMPARE256 compare256_avx2_static #include "match_tpl.h" diff --git a/arch/x86/compare256_sse2.c b/arch/x86/compare256_sse2.c index bd5d62cf7b..aad4bd240d 100644 --- a/arch/x86/compare256_sse2.c +++ b/arch/x86/compare256_sse2.c @@ -11,7 +11,7 @@ #include -static inline uint32_t compare256_unaligned_sse2_static(const uint8_t *src0, const uint8_t *src1) { +static inline uint32_t compare256_sse2_static(const uint8_t *src0, const uint8_t *src1) { uint32_t len = 0; int align_offset = ((uintptr_t)src0) & 15; const uint8_t *end0 = src0 + 256; @@ -78,18 +78,18 @@ static inline uint32_t compare256_unaligned_sse2_static(const uint8_t *src0, con return 256; } -Z_INTERNAL uint32_t compare256_unaligned_sse2(const uint8_t *src0, const uint8_t *src1) { - return compare256_unaligned_sse2_static(src0, src1); +Z_INTERNAL uint32_t compare256_sse2(const uint8_t *src0, const uint8_t *src1) { + return compare256_sse2_static(src0, src1); } -#define LONGEST_MATCH longest_match_unaligned_sse2 -#define COMPARE256 compare256_unaligned_sse2_static +#define LONGEST_MATCH longest_match_sse2 +#define COMPARE256 compare256_sse2_static #include "match_tpl.h" #define LONGEST_MATCH_SLOW -#define LONGEST_MATCH longest_match_slow_unaligned_sse2 -#define COMPARE256 compare256_unaligned_sse2_static +#define LONGEST_MATCH longest_match_slow_sse2 +#define COMPARE256 compare256_sse2_static #include "match_tpl.h" diff --git a/cpu_features.h b/cpu_features.h index 7cc74a97ad..5607672178 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -120,12 +120,12 @@ extern uint32_t compare256_unaligned_32(const uint8_t *src0, const uint8_t *src1 #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) extern uint32_t compare256_unaligned_64(const uint8_t *src0, const uint8_t *src1); #endif +#endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t compare256_unaligned_sse2(const uint8_t *src0, const uint8_t *src1); +extern uint32_t compare256_sse2(const uint8_t *src0, const uint8_t *src1); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t compare256_unaligned_avx2(const uint8_t *src0, const uint8_t *src1); -#endif +extern uint32_t compare256_avx2(const uint8_t *src0, const uint8_t *src1); #endif #ifdef DEFLATE_H_ @@ -147,12 +147,12 @@ extern uint32_t longest_match_unaligned_32(deflate_state *const s, Pos cur_match #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) extern uint32_t longest_match_unaligned_64(deflate_state *const s, Pos cur_match); #endif +#endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t longest_match_unaligned_sse2(deflate_state *const s, Pos cur_match); +extern uint32_t longest_match_sse2(deflate_state *const s, Pos cur_match); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t longest_match_unaligned_avx2(deflate_state *const s, Pos cur_match); -#endif +extern uint32_t longest_match_avx2(deflate_state *const s, Pos cur_match); #endif /* longest_match_slow */ @@ -163,12 +163,12 @@ extern uint32_t longest_match_slow_unaligned_32(deflate_state *const s, Pos cur_ #ifdef UNALIGNED64_OK extern uint32_t longest_match_slow_unaligned_64(deflate_state *const s, Pos cur_match); #endif +#endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t longest_match_slow_unaligned_sse2(deflate_state *const s, Pos cur_match); +extern uint32_t longest_match_slow_sse2(deflate_state *const s, Pos cur_match); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -extern uint32_t longest_match_slow_unaligned_avx2(deflate_state *const s, Pos cur_match); -#endif +extern uint32_t longest_match_slow_avx2(deflate_state *const s, Pos cur_match); #endif /* quick_insert_string */ diff --git a/functable.c b/functable.c index 3e23c54e59..ffb0d3f479 100644 --- a/functable.c +++ b/functable.c @@ -106,17 +106,17 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { # else functable.longest_match = &longest_match_unaligned_16; # endif -# if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_sse2) - functable.longest_match = &longest_match_unaligned_sse2; -# endif -# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - functable.longest_match = &longest_match_unaligned_avx2; -# endif #else functable.longest_match = &longest_match_c; #endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_sse2) + functable.longest_match = &longest_match_sse2; +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_avx2) + functable.longest_match = &longest_match_avx2; +#endif return functable.longest_match(s, cur_match); } @@ -131,17 +131,17 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc # else functable.longest_match_slow = &longest_match_slow_unaligned_16; # endif -# if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_sse2) - functable.longest_match_slow = &longest_match_slow_unaligned_sse2; -# endif -# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - functable.longest_match_slow = &longest_match_slow_unaligned_avx2; -# endif #else functable.longest_match_slow = &longest_match_slow_c; #endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_sse2) + functable.longest_match_slow = &longest_match_slow_sse2; +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_avx2) + functable.longest_match_slow = &longest_match_slow_avx2; +#endif return functable.longest_match_slow(s, cur_match); } @@ -391,17 +391,17 @@ Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { # else functable.compare256 = &compare256_unaligned_16; # endif -# if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_sse2) - functable.compare256 = &compare256_unaligned_sse2; -# endif -# if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) - if (x86_cpu_has_avx2) - functable.compare256 = &compare256_unaligned_avx2; -# endif #else functable.compare256 = &compare256_c; #endif +#if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_sse2) + functable.compare256 = &compare256_sse2; +#endif +#if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) + if (x86_cpu_has_avx2) + functable.compare256 = &compare256_avx2; +#endif return functable.compare256(src0, src1); } diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index bdfdd6bf97..e690e8effe 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -69,10 +69,10 @@ BENCHMARK_COMPARE256(unaligned_32, compare256_unaligned_32, 1); #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) BENCHMARK_COMPARE256(unaligned_64, compare256_unaligned_64, 1); #endif +#endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) -BENCHMARK_COMPARE256(unaligned_sse2, compare256_unaligned_sse2, x86_cpu_has_sse2); +BENCHMARK_COMPARE256(sse2, compare256_sse2, x86_cpu_has_sse2); #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -BENCHMARK_COMPARE256(unaligned_avx2, compare256_unaligned_avx2, x86_cpu_has_avx2); -#endif +BENCHMARK_COMPARE256(avx2, compare256_avx2, x86_cpu_has_avx2); #endif diff --git a/test/test_compare256.cc b/test/test_compare256.cc index 2c2f3aaa87..c252cfada7 100644 --- a/test/test_compare256.cc +++ b/test/test_compare256.cc @@ -65,10 +65,10 @@ TEST_COMPARE256(unaligned_32, compare256_unaligned_32, 1) #if defined(UNALIGNED64_OK) && defined(HAVE_BUILTIN_CTZLL) TEST_COMPARE256(unaligned_64, compare256_unaligned_64, 1) #endif +#endif #if defined(X86_SSE2) && defined(HAVE_BUILTIN_CTZ) -TEST_COMPARE256(unaligned_sse2, compare256_unaligned_sse2, x86_cpu_has_sse2) +TEST_COMPARE256(sse2, compare256_sse2, x86_cpu_has_sse2) #endif #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) -TEST_COMPARE256(unaligned_avx2, compare256_unaligned_avx2, x86_cpu_has_avx2) -#endif +TEST_COMPARE256(avx2, compare256_avx2, x86_cpu_has_avx2) #endif From 98d4908aa67437e199544493fa63d84c16070c54 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 28 Mar 2022 16:52:02 -0700 Subject: [PATCH 354/798] Use standalone fuzzing runner only when fuzzing engine is not found. --- CMakeLists.txt | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bc748a8b3..8241d32eae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1252,12 +1252,30 @@ if(ZLIB_ENABLE_TESTS) -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) if(WITH_FUZZERS) + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + enable_language(CXX) + + if(DEFINED ENV{LIB_FUZZING_ENGINE}) + set(FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE}) + set(FUZZING_ENGINE_FOUND ON) + else() + find_library(FUZZING_ENGINE "FuzzingEngine") + endif() + endif() + set(FUZZERS checksum compress example_small example_large example_flush example_dict minigzip) file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*") foreach(FUZZER ${FUZZERS}) - add_executable(fuzzer_${FUZZER} test/fuzz/fuzzer_${FUZZER}.c test/fuzz/standalone_fuzz_target_runner.c) + set(FUZZER_SRCS test/fuzz/fuzzer_${FUZZER}.c) + if(NOT FUZZING_ENGINE_FOUND) + list(APPEND FUZZER_SRCS test/fuzz/standalone_fuzz_target_runner.c) + endif() + add_executable(fuzzer_${FUZZER} ${FUZZER_SRCS}) configure_test_executable(fuzzer_${FUZZER}) target_link_libraries(fuzzer_${FUZZER} zlib) + if(FUZZING_ENGINE_FOUND) + target_link_libraries(fuzzer_${FUZZER} ${FUZZING_ENGINE}) + endif() set(FUZZER_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ ${ALL_SRC_FILES}) add_test(NAME fuzzer_${FUZZER} COMMAND ${FUZZER_COMMAND}) endforeach() From e43e0b21893b55d6b44d3f8b7105fcb655e87f5a Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 27 Mar 2022 19:20:08 -0400 Subject: [PATCH 355/798] Use size_t types for len arithmetic, matching signature This suppresses a warning and keeps everything safely the same type. While it's unlikely that the input for any of this will exceed the size of an unsigned 32 bit integer, this approach is cleaner than casting and should not result in a performance degradation. --- arch/x86/adler32_ssse3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 5d28ac95fc..014c89a881 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -59,10 +59,10 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size * additions worthwhile or if it's worth it to just eat the cost of an unaligned * load. This is a pretty simple test, just test if 16 - the remainder + len is * < 16 */ - uint32_t max_iters = NMAX; - uint32_t rem = (uintptr_t)buf & 15; - uint32_t align_offset = 16 - rem; - uint32_t k = 0; + size_t max_iters = NMAX; + size_t rem = (uintptr_t)buf & 15; + size_t align_offset = 16 - rem; + size_t k = 0; if (rem) { if (len < 16 + align_offset) { /* Let's eat the cost of this one unaligned load so that @@ -79,7 +79,7 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size goto unaligned_jmp; } - for (uint32_t i = 0; i < align_offset; ++i) { + for (size_t i = 0; i < align_offset; ++i) { adler += *(buf++); sum2 += adler; } From 4a2a1eca93a6be83443f03e2eea01ba374548d29 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 26 Mar 2022 17:26:16 -0700 Subject: [PATCH 356/798] Added missing -F argument for Z_FIXED strategy in minideflate. --- test/minideflate.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/minideflate.c b/test/minideflate.c index d4d8423a9f..8ef5ed917b 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -263,6 +263,8 @@ int main(int argc, char **argv) { keep = 1; else if (strcmp(argv[i], "-f") == 0) strategy = Z_FILTERED; + else if (strcmp(argv[i], "-F") == 0) + strategy = Z_FIXED; else if (strcmp(argv[i], "-h") == 0) strategy = Z_HUFFMAN_ONLY; else if (strcmp(argv[i], "-R") == 0) @@ -321,7 +323,7 @@ int main(int argc, char **argv) { free(out_file); } } - + if (window_bits == INT32_MAX) { window_bits = MAX_WBITS; /* Auto-detect wrapper for inflateInit */ From 0bc80afea09c9a3c37d610c0019739ee057baa0d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 26 Mar 2022 17:49:49 -0700 Subject: [PATCH 357/798] Added unit test against CVE-2018-25032. Sample input from https://www.openwall.com/lists/oss-security/2022/03/26/1. Co-authored-by: Tavis Ormandy --- CMakeLists.txt | 9 +++++++++ test/CVE-2018-25032/test.txt | 1 + test/README.md | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 test/CVE-2018-25032/test.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 8241d32eae..f60e6025ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1353,6 +1353,15 @@ if(ZLIB_ENABLE_TESTS) -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake) endforeach() + add_test(NAME CVE-2018-25032 + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIDEFLATE_COMMAND}" + "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-F" + "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15" + -DGZIP_VERIFY=OFF + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/test.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) + # Run tests targeting tools include(cmake/test-tools.cmake) diff --git a/test/CVE-2018-25032/test.txt b/test/CVE-2018-25032/test.txt new file mode 100644 index 0000000000..5ccca248c5 --- /dev/null +++ b/test/CVE-2018-25032/test.txt @@ -0,0 +1 @@ +AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZABBABCABDABEABFABGABHABIABJABKABLABMABNABOABPABQABRABSABTABUABVABWABXABYABZACBACCACDACEACFACGACHACIACJACKACLACMACNACOACPACQACRACSACTACUACVACWACXACYACZADBADCADDADEADFADGADHADIADJADKADLADMADNADOADPADQADRADSADTADUADVADWADXADYADZAEBAECAEDAEEAEFAEGAEHAEIAEJAEKAELAEMAENAEOAEPAEQAERAESAETAEUAEVAEWAEXAEYAEZAFBAFCAFDAFEAFFAFGAFHAFIAFJAFKAFLAFMAFNAFOAFPAFQAFRAFSAFTAFUAFVAFWAFXAFYAFZAGBAGCAGDAGEAGFAGGAGHAGIAGJAGKAGLAGMAGNAGOAGPAGQAGRAGSAGTAGUAGVAGWAGXAGYAGZAHBAHCAHDAHEAHFAHGAHHAHIAHJAHKAHLAHMAHNAHOAHPAHQAHRAHSAHTAHUAHVAHWAHXAHYAHZAIBAICAIDAIEAIFAIGAIHAIIAIJAIKAILAIMAINAIOAIPAIQAIRAISAITAIUAIVAIWAIXAIYAIZAJBAJCAJDAJEAJFAJGAJHAJIAJJAJKAJLAJMAJNAJOAJPAJQAJRAJSAJTAJUAJVAJWAJXAJYAJZAKBAKCAKDAKEAKFAKGAKHAKIAKJAKKAKLAKMAKNAKOAKPAKQAKRAKSAKTAKUAKVAKWAKXAKYAKZALBALCALDALEALFALGALHALIALJALKALLALMALNALOALPALQALRALSALTALUALVALWALXALYALZAMBAMCAMDAMEAMFAMGAMHAMIAMJAMKAMLAMMAMNAMOAMPAMQAMRAMSAMTAMUAMVAMWAMXAMYAMZANBANCANDANEANFANGANHANIANJANKANLANMANNANOANPANQANRANSANTANUANVANWANXANYANZAOBAOCAODAOEAOFAOGAOHAOIAOJAOKAOLAOMAONAOOAOPAOQAORAOSAOTAOUAOVAOWAOXAOYAOZAPBAPCAPDAPEAPFAPGAPHAPIAPJAPKAPLAPMAPNAPOAPPAPQAPRAPSAPTAPUAPVAPWAPXAPYAPZAQBAQCAQDAQEAQFAQGAQHAQIAQJAQKAQLAQMAQNAQOAQPAQQAQRAQSAQTAQUAQVAQWAQXAQYAQZARBARCARDAREARFARGARHARIARJARKARLARMARNAROARPARQARRARSARTARUARVARWARXARYARZASBASCASDASEASFASGASHASIASJASKASLASMASNASOASPASQASRASSASTASUASVASWASXASYASZATBATCATDATEATFATGATHATIATJATKATLATMATNATOATPATQATRATSATTATUATVATWATXATYATZAUBAUCAUDAUEAUFAUGAUHAUIAUJAUKAULAUMAUNAUOAUPAUQAURAUSAUTAUUAUVAUWAUXAUYAUZAVBAVCAVDAVEAVFAVGAVHAVIAVJAVKAVLAVMAVNAVOAVPAVQAVRAVSAVTAVUAVVAVWAVXAVYAVZAWBAWCAWDAWEAWFAWGAWHAWIAWJAWKAWLAWMAWNAWOAWPAWQAWRAWSAWTAWUAWVAWWAWXAWYAWZAXBAXCAXDAXEAXFAXGAXHAXIAXJAXKAXLAXMAXNAXOAXPAXQAXRAXSAXTAXUAXVAXWAXXAXYAXZAYBAYCAYDAYEAYFAYGAYHAYIAYJAYKAYLAYMAYNAYOAYPAYQAYRAYSAYTAYUAYVAYWAYXAYYAYZAZBAZCAZDAZEAZFAZGAZHAZIAZJAZKAZLAZMAZNAZOAZPAZQAZRAZSAZTAZUAZVAZWAZXAZYAZZBBBCBBDBBEBBFBBGBBHBBIBBJBBKBBLBBMBBNBBOBBPBBQBBRBBSBBTBBUBBVBBWBBXBBYBBZBCCBCDBCEBCFBCGBCHBCIBCJBCKBCLBCMBCNBCOBCPBCQBCRBCSBCTBCUBCVBCWBCXBCYBCZBDCBDDBDEBDFBDGBDHBDIBDJBDKBDLBDMBDNBDOBDPBDQBDRBDSBDTBDUBDVBDWBDXBDYBDZBECBEDBEEBEFBEGBEHBEIBEJBEKBELBEMBENBEOBEPBEQBERBESBETBEUBEVBEWBEXBEYBEZBFCBFDBFEBFFBFGBFHBFIBFJBFKBFLBFMBFNBFOBFPBFQBFRBFSBFTBFUBFVBFWBFXBFYBFZBGCBGDBGEBGFBGGBGHBGIBGJBGKBGLBGMBGNBGOBGPBGQBGRBGSBGTBGUBGVBGWBGXBGYBGZBHCBHDBHEBHFBHGBHHBHIBHJBHKBHLBHMBHNBHOBHPBHQBHRBHSBHTBHUBHVBHWBHXBHYBHZBICBIDBIEBIFBIGBIHBIIBIJBIKBILBIMBINBIOBIPBIQBIRBISBITBIUBIVBIWBIXBIYBIZBJCBJDBJEBJFBJGBJHBJIBJJBJKBJLBJMBJNBJOBJPBJQBJRBJSBJTBJUBJVBJWBJXBJYBJZBKCBKDBKEBKFBKGBKHBKIBKJBKKBKLBKMBKNBKOBKPBKQBKRBKSBKTBKUBKVBKWBKXBKYBKZBLCBLDBLEBLFBLGBLHBLIBLJBLKBLLBLMBLNBLOBLPBLQBLRBLSBLTBLUBLVBLWBLXBLYBLZBMCBMDBMEBMFBMGBMHBMIBMJBMKBMLBMMBMNBMOBMPBMQBMRBMSBMTBMUBMVBMWBMXBMYBMZBNCBNDBNEBNFBNGBNHBNIBNJBNKBNLBNMBNNBNOBNPBNQBNRBNSBNTBNUBNVBNWBNXBNYBNZBOCBODBOEBOFBOGBOHBOIBOJBOKBOLBOMBONBOOBOPBOQBORBOSBOTBOUBOVBOWBOXBOYBOZBPCBPDBPEBPFBPGBPHBPIBPJBPKBPLBPMBPNBPOBPPBPQBPRBPSBPTBPUBPVBPWBPXBPYBPZBQCBQDBQEBQFBQGBQHBQIBQJBQKBQLBQMBQNBQOBQPBQQBQRBQSBQTBQUBQVBQWBQXBQYBQZBRCBRDBREBRFBRGBRHBRIBRJBRKBRLBRMBRNBROBRPBRQBRRBRSBRTBRUBRVBRWBRXBRYBRZBSCBSDBSEBSFBSGBSHBSIBSJBSKBSLBSMBSNBSOBSPBSQBSRBSSBSTBSUBSVBSWBSXBSYBSZBTCBTDBTEBTFBTGBTHBTIBTJBTKBTLBTMBTNBTOBTPBTQBTRBTSBTTBTUBTVBTWBTXBTYBTZBUCBUDBUEBUFBUGBUHBUIBUJBUKBULBUMBUNBUOBUPBUQBURBUSBUTBUUBUVBUWBUXBUYBUZBVCBVDBVEBVFBVGBVHBVIBVJBVKBVLBVMBVNBVOBVPBVQBVRBVSBVTBVUBVVBVWBVXBVYBVZBWCBWDBWEBWFBWGBWHBWIBWJBWKBWLBWMBWNBWOBWPBWQBWRBWSBWTBWUBWVBWWBWXBWYBWZBXCBXDBXEBXFBXGBXHBXIBXJBXKBXLBXMBXNBXOBXPBXQBXRBXSBXTBXUBXVBXWBXXBXYBXZBYCBYDBYEBYFBYGBYHBYIBYJBYKBYLBYMBYNBYOBYPBYQBYRBYSBYTBYUBYVBYWBYXBYYBYZBZCBZDBZEBZFBZGBZHBZIBZJBZKBZLBZMBZNBZOBZPBZQBZRBZSBZTBZUBZVBZWBZXBZYBZZCCCDCCECCFCCGCCHCCICCJCCKCCLCCMCCNCCOCCPCCQCCRCCSCCTCCUCCVCCWCCXCCYCCZCDDCDECDFCDGCDHCDICDJCDKCDLCDMCDNCDOCDPCDQCDRCDSCDTCDUCDVCDWCDXCDYCDZCEDCEECEFCEGCEHCEICEJCEKCELCEMCENCEOCEPCEQCERCESCETCEUCEVCEWCEXCEYCEZCFDCFECFFCFGCFHCFICFJCFKCFLCFMCFNCFOCFPCFQCFRCFSCFTCFUCFVCFWCFXCFYCFZCGDCGECGFCGGCGHCGICGJCGKCGLCGMCGNCGOCGPCGQCGRCGSCGTCGUCGVCGWCGXCGYCGZCHDCHECHFCHGCHHCHICHJCHKCHLCHMCHNCHOCHPCHQCHRCHSCHTCHUCHVCHWCHXCHYCHZCIDCIECIFCIGCIHCIICIJCIKCILCIMCINCIOCIPCIQCIRCISCITCIUCIVCIWCIXCIYCIZCJDCJECJFCJGCJHCJICJJCJKCJLCJMCJNCJOCJPCJQCJRCJSCJTCJUCJVCJWCJXCJYCJZCKDCKECKFCKGCKHCKICKJCKKCKLCKMCKNCKOCKPCKQCKRCKSCKTCKUCKVCKWCKXCKYCKZCLDCLECLFCLGCLHCLICLJCLKCLLCLMCLNCLOCLPCLQCLRCLSCLTCLUCLVCLWCLXCLYCLZCMDCMECMFCMGCMHCMICMJCMKCMLCMMCMNCMOCMPCMQCMRCMSCMTCMUCMVCMWCMXCMYCMZCNDCNECNFCNGCNHCNICNJCNKCNLCNMCNNCNOCNPCNQCNRCNSCNTCNUCNVCNWCNXCNYCNZCODCOECOFCOGCOHCOICOJCOKCOLCOMCONCOOCOPCOQCORCOSCOTCOUCOVCOWCOXCOYCOZCPDCPECPFCPGCPHCPICPJCPKCPLCPMCPNCPOCPPCPQCPRCPSCPTCPUCPVCPWCPXCPYCPZCQDCQECQFCQGCQHCQICQJCQKCQLCQMCQNCQOCQPCQQCQRCQSCQTCQUCQVCQWCQXCQYCQZCRDCRECRFCRGCRHCRICRJCRKCRLCRMCRNCROCRPCRQCRRCRSCRTCRUCRVCRWCRXCRYCRZCSDCSECSFCSGCSHCSICSJCSKCSLCSMCSNCSOCSPCSQCSRCSSCSTCSUCSVCSWCSXCSYCSZCTDCTECTFCTGCTHCTICTJCTKCTLCTMCTNCTOCTPCTQCTRCTSCTTCTUCTVCTWCTXCTYCTZCUDCUECUFCUGCUHCUICUJCUKCULCUMCUNCUOCUPCUQCURCUSCUTCUUCUVCUWCUXCUYCUZCVDCVECVFCVGCVHCVICVJCVKCVLCVMCVNCVOCVPCVQCVRCVSCVTCVUCVVCVWCVXCVYCVZCWDCWECWFCWGCWHCWICWJCWKCWLCWMCWNCWOCWPCWQCWRCWSCWTCWUCWVCWWCWXCWYCWZCXDCXECXFCXGCXHCXICXJCXKCXLCXMCXNCXOCXPCXQCXRCXSCXTCXUCXVCXWCXXCXYCXZCYDCYECYFCYGCYHCYICYJCYKCYLCYMCYNCYOCYPCYQCYRCYSCYTCYUCYVCYWCYXCYYCYZCZDCZECZFCZGCZHCZICZJCZKCZLCZMCZNCZOCZPCZQCZRCZSCZTCZUCZVCZWCZXCZYCZZDDDEDDFDDGDDHDDIDDJDDKDDLDDMDDNDDODDPDDQDDRDDSDDTDDUDDVDDWDDXDDYDDZDEEDEFDEGDEHDEIDEJDEKDELDEMDENDEODEPDEQDERDESDETDEUDEVDEWDEXDEYDEZDFEDFFDFGDFHDFIDFJDFKDFLDFMDFNDFODFPDFQDFRDFSDFTDFUDFVDFWDFXDFYDFZDGEDGFDGGDGHDGIDGJDGKDGLDGMDGNDGODGPDGQDGRDGSDGTDGUDGVDGWDGXDGYDGZDHEDHFDHGDHHDHIDHJDHKDHLDHMDHNDHODHPDHQDHRDHSDHTDHUDHVDHWDHXDHYDHZDIEDIFDIGDIHDIIDIJDIKDILDIMDINDIODIPDIQDIRDISDITDIUDIVDIWDIXDIYDIZDJEDJFDJGDJHDJIDJJDJKDJLDJMDJNDJODJPDJQDJRDJSDJTDJUDJVDJWDJXDJYDJZDKEDKFDKGDKHDKIDKJDKKDKLDKMDKNDKODKPDKQDKRDKSDKTDKUDKVDKWDKXDKYDKZDLEDLFDLGDLHDLIDLJDLKDLLDLMDLNDLODLPDLQDLRDLSDLTDLUDLVDLWDLXDLYDLZDMEDMFDMGDMHDMIDMJDMKDMLDMMDMNDMODMPDMQDMRDMSDMTDMUDMVDMWDMXDMYDMZDNEDNFDNGDNHDNIDNJDNKDNLDNMDNNDNODNPDNQDNRDNSDNTDNUDNVDNWDNXDNYDNZDOEDOFDOGDOHDOIDOJDOKDOLDOMDONDOODOPDOQDORDOSDOTDOUDOVDOWDOXDOYDOZDPEDPFDPGDPHDPIDPJDPKDPLDPMDPNDPODPPDPQDPRDPSDPTDPUDPVDPWDPXDPYDPZDQEDQFDQGDQHDQIDQJDQKDQLDQMDQNDQODQPDQQDQRDQSDQTDQUDQVDQWDQXDQYDQZDREDRFDRGDRHDRIDRJDRKDRLDRMDRNDRODRPDRQDRRDRSDRTDRUDRVDRWDRXDRYDRZDSEDSFDSGDSHDSIDSJDSKDSLDSMDSNDSODSPDSQDSRDSSDSTDSUDSVDSWDSXDSYDSZDTEDTFDTGDTHDTIDTJDTKDTLDTMDTNDTODTPDTQDTRDTSDTTDTUDTVDTWDTXDTYDTZDUEDUFDUGDUHDUIDUJDUKDULDUMDUNDUODUPDUQDURDUSDUTDUUDUVDUWDUXDUYDUZDVEDVFDVGDVHDVIDVJDVKDVLDVMDVNDVODVPDVQDVRDVSDVTDVUDVVDVWDVXDVYDVZDWEDWFDWGDWHDWIDWJDWKDWLDWMDWNDWODWPDWQDWRDWSDWTDWUDWVDWWDWXDWYDWZDXEDXFDXGDXHDXIDXJDXKDXLDXMDXNDXODXPDXQDXRDXSDXTDXUDXVDXWDXXDXYDXZDYEDYFDYGDYHDYIDYJDYKDYLDYMDYNDYODYPDYQDYRDYSDYTDYUDYVDYWDYXDYYDYZDZEDZFDZGDZHDZIDZJDZKDZLDZMDZNDZODZPDZQDZRDZSDZTDZUDZVDZWDZXDZYDZZEEEFEEGEEHEEIEEJEEKEELEEMEENEEOEEPEEQEEREESEETEEUEEVEEWEEXEEYEEZEFFEFGEFHEFIEFJEFKEFLEFMEFNEFOEFPEFQEFREFSEFTEFUEFVEFWEFXEFYEFZEGFEGGEGHEGIEGJEGKEGLEGMEGNEGOEGPEGQEGREGSEGTEGUEGVEGWEGXEGYEGZEHFEHGEHHEHIEHJEHKEHLEHMEHNEHOEHPEHQEHREHSEHTEHUEHVEHWEHXEHYEHZEIFEIGEIHEIIEIJEIKEILEIMEINEIOEIPEIQEIREISEITEIUEIVEIWEIXEIYEIZEJFEJGEJHEJIEJJEJKEJLEJMEJNEJOEJPEJQEJREJSEJTEJUEJVEJWEJXEJYEJZEKFEKGEKHEKIEKJEKKEKLEKMEKNEKOEKPEKQEKREKSEKTEKUEKVEKWEKXEKYEKZELFELGELHELIELJELKELLELMELNELOELPELQELRELSELTELUELVELWELXELYELZEMFEMGEMHEMIEMJEMKEMLEMMEMNEMOEMPEMQEMREMSEMTEMUEMVEMWEMXEMYEMZENFENGENHENIENJENKENLENMENNENOENPENQENRENSENTENUENVENWENXENYENZEOFEOGEOHEOIEOJEOKEOLEOMEONEOOEOPEOQEOREOSEOTEOUEOVEOWEOXEOYEOZEPFEPGEPHEPIEPJEPKEPLEPMEPNEPOEPPEPQEPREPSEPTEPUEPVEPWEPXEPYEPZEQFEQGEQHEQIEQJEQKEQLEQMEQNEQOEQPEQQEQREQSEQTEQUEQVEQWEQXEQYEQZERFERGERHERIERJERKERLERMERNEROERPERQERRERSERTERUERVERWERXERYERZESFESGESHESIESJESKESLESMESNESOESPESQESRESSESTESUESVESWESXESYESZETFETGETHETIETJETKETLETMETNETOETPETQETRETSETTETUETVETWETXETYETZEUFEUGEUHEUIEUJEUKEULEUMEUNEUOEUPEUQEUREUSEUTEUUEUVEUWEUXEUYEUZEVFEVGEVHEVIEVJEVKEVLEVMEVNEVOEVPEVQEVREVSEVTEVUEVVEVWEVXEVYEVZEWFEWGEWHEWIEWJEWKEWLEWMEWNEWOEWPEWQEWREWSEWTEWUEWVEWWEWXEWYEWZEXFEXGEXHEXIEXJEXKEXLEXMEXNEXOEXPEXQEXREXSEXTEXUEXVEXWEXXEXYEXZEYFEYGEYHEYIEYJEYKEYLEYMEYNEYOEYPEYQEYREYSEYTEYUEYVEYWEYXEYYEYZEZFEZGEZHEZIEZJEZKEZLEZMEZNEZOEZPEZQEZREZSEZTEZUEZVEZWEZXEZYEZZFFFGFFHFFIFFJFFKFFLFFMFFNFFOFFPFFQFFRFFSFFTFFUFFVFFWFFXFFYFFZFGGFGHFGIFGJFGKFGLFGMFGNFGOFGPFGQFGRFGSFGTFGUFGVFGWFGXFGYFGZFHGFHHFHIFHJFHKFHLFHMFHNFHOFHPFHQFHRFHSFHTFHUFHVFHWFHXFHYFHZFIGFIHFIIFIJFIKFILFIMFINFIOFIPFIQFIRFISFITFIUFIVFIWFIXFIYFIZFJGFJHFJIFJJFJKFJLFJMFJNFJOFJPFJQFJRFJSFJTFJUFJVFJWFJXFJYFJZFKGFKHFKIFKJFKKFKLFKMFKNFKOFKPFKQFKRFKSFKTFKUFKVFKWFKXFKYFKZFLGFLHFLIFLJFLKFLLFLMFLNFLOFLPFLQFLRFLSFLTFLUFLVFLWFLXFLYFLZFMGFMHFMIFMJFMKFMLFMMFMNFMOFMPFMQFMRFMSFMTFMUFMVFMWFMXFMYFMZFNGFNHFNIFNJFNKFNLFNMFNNFNOFNPFNQFNRFNSFNTFNUFNVFNWFNXFNYFNZFOGFOHFOIFOJFOKFOLFOMFONFOOFOPFOQFORFOSFOTFOUFOVFOWFOXFOYFOZFPGFPHFPIFPJFPKFPLFPMFPNFPOFPPFPQFPRFPSFPTFPUFPVFPWFPXFPYFPZFQGFQHFQIFQJFQKFQLFQMFQNFQOFQPFQQFQRFQSFQTFQUFQVFQWFQXFQYFQZFRGFRHFRIFRJFRKFRLFRMFRNFROFRPFRQFRRFRSFRTFRUFRVFRWFRXFRYFRZFSGFSHFSIFSJFSKFSLFSMFSNFSOFSPFSQFSRFSSFSTFSUFSVFSWFSXFSYFSZFTGFTHFTIFTJFTKFTLFTMFTNFTOFTPFTQFTRFTSFTTFTUFTVFTWFTXFTYFTZFUGFUHFUIFUJFUKFULFUMFUNFUOFUPFUQFURFUSFUTFUUFUVFUWFUXFUYFUZFVGFVHFVIFVJFVKFVLFVMFVNFVOFVPFVQFVRFVSFVTFVUFVVFVWFVXFVYFVZFWGFWHFWIFWJFWKFWLFWMFWNFWOFWPFWQFWRFWSFWTFWUFWVFWWFWXFWYFWZFXGFXHFXIFXJFXKFXLFXMFXNFXOFXPFXQFXRFXSFXTFXUFXVFXWFXXFXYFXZFYGFYHFYIFYJFYKFYLFYMFYNFYOFYPFYQFYRFYSFYTFYUFYVFYWFYXFYYFYZFZGFZHFZIFZJFZKFZLFZMFZNFZOFZPFZQFZRFZSFZTFZUFZVFZWFZXFZYFZZGGGHGGIGGJGGKGGLGGMGGNGGOGGPGGQGGRGGSGGTGGUGGVGGWGGXGGYGGZGHHGHIGHJGHKGHLGHMGHNGHOGHPGHQGHRGHSGHTGHUGHVGHWGHXGHYGHZGIHGIIGIJGIKGILGIMGINGIOGIPGIQGIRGISGITGIUGIVGIWGIXGIYGIZGJHGJIGJJGJKGJLGJMGJNGJOGJPGJQGJRGJSGJTGJUGJVGJWGJXGJYGJZGKHGKIGKJGKKGKLGKMGKNGKOGKPGKQGKRGKSGKTGKUGKVGKWGKXGKYGKZGLHGLIGLJGLKGLLGLMGLNGLOGLPGLQGLRGLSGLTGLUGLVGLWGLXGLYGLZGMHGMIGMJGMKGMLGMMGMNGMOGMPGMQGMRGMSGMTGMUGMVGMWGMXGMYGMZGNHGNIGNJGNKGNLGNMGNNGNOGNPGNQGNRGNSGNTGNUGNVGNWGNXGNYGNZGOHGOIGOJGOKGOLGOMGONGOOGOPGOQGORGOSGOTGOUGOVGOWGOXGOYGOZGPHGPIGPJGPKGPLGPMGPNGPOGPPGPQGPRGPSGPTGPUGPVGPWGPXGPYGPZGQHGQIGQJGQKGQLGQMGQNGQOGQPGQQGQRGQSGQTGQUGQVGQWGQXGQYGQZGRHGRIGRJGRKGRLGRMGRNGROGRPGRQGRRGRSGRTGRUGRVGRWGRXGRYGRZGSHGSIGSJGSKGSLGSMGSNGSOGSPGSQGSRGSSGSTGSUGSVGSWGSXGSYGSZGTHGTIGTJGTKGTLGTMGTNGTOGTPGTQGTRGTSGTTGTUGTVGTWGTXGTYGTZGUHGUIGUJGUKGULGUMGUNGUOGUPGUQGURGUSGUTGUUGUVGUWGUXGUYGUZGVHGVIGVJGVKGVLGVMGVNGVOGVPGVQGVRGVSGVTGVUGVVGVWGVXGVYGVZGWHGWIGWJGWKGWLGWMGWNGWOGWPGWQGWRGWSGWTGWUGWVGWWGWXGWYGWZGXHGXIGXJGXKGXLGXMGXNGXOGXPGXQGXRGXSGXTGXUGXVGXWGXXGXYGXZGYHGYIGYJGYKGYLGYMGYNGYOGYPGYQGYRGYSGYTGYUGYVGYWGYXGYYGYZGZHGZIGZJGZKGZLGZMGZNGZOGZPGZQGZRGZSGZTGZUGZVGZWGZXGZYGZZHHHIHHJHHKHHLHHMHHNHHOHHPHHQHHRHHSHHTHHUHHVHHWHHXHHYHHZHIIHIJHIKHILHIMHINHIOHIPHIQHIRHISHITHIUHIVHIWHIXHIYHIZHJIHJJHJKHJLHJMHJNHJOHJPHJQHJRHJSHJTHJUHJVHJWHJXHJYHJZHKIHKJHKKHKLHKMHKNHKOHKPHKQHKRHKSHKTHKUHKVHKWHKXHKYHKZHLIHLJHLKHLLHLMHLNHLOHLPHLQHLRHLSHLTHLUHLVHLWHLXHLYHLZHMIHMJHMKHMLHMMHMNHMOHMPHMQHMRHMSHMTHMUHMVHMWHMXHMYHMZHNIHNJHNKHNLHNMHNNHNOHNPHNQHNRHNSHNTHNUHNVHNWHNXHNYHNZHOIHOJHOKHOLHOMHONHOOHOPHOQHORHOSHOTHOUHOVHOWHOXHOYHOZHPIHPJHPKHPLHPMHPNHPOHPPHPQHPRHPSHPTHPUHPVHPWHPXHPYHPZHQIHQJHQKHQLHQMHQNHQOHQPHQQHQRHQSHQTHQUHQVHQWHQXHQYHQZHRIHRJHRKHRLHRMHRNHROHRPHRQHRRHRSHRTHRUHRVHRWHRXHRYHRZHSIHSJHSKHSLHSMHSNHSOHSPHSQHSRHSSHSTHSUHSVHSWHSXHSYHSZHTIHTJHTKHTLHTMHTNHTOHTPHTQHTRHTSHTTHTUHTVHTWHTXHTYHTZHUIHUJHUKHULHUMHUNHUOHUPHUQHURHUSHUTHUUHUVHUWHUXHUYHUZHVIHVJHVKHVLHVMHVNHVOHVPHVQHVRHVSHVTHVUHVVHVWHVXHVYHVZHWIHWJHWKHWLHWMHWNHWOHWPHWQHWRHWSHWTHWUHWVHWWHWXHWYHWZHXIHXJHXKHXLHXMHXNHXOHXPHXQHXRHXSHXTHXUHXVHXWHXXHXYHXZHYIHYJHYKHYLHYMHYNHYOHYPHYQHYRHYSHYTHYUHYVHYWHYXHYYHYZHZIHZJHZKHZLHZMHZNHZOHZPHZQHZRHZSHZTHZUHZVHZWHZXHZYHZZIIIJIIKIILIIMIINIIOIIPIIQIIRIISIITIIUIIVIIWIIXIIYIIZIJJIJKIJLIJMIJNIJOIJPIJQIJRIJSIJTIJUIJVIJWIJXIJYIJZIKJIKKIKLIKMIKNIKOIKPIKQIKRIKSIKTIKUIKVIKWIKXIKYIKZILJILKILLILMILNILOILPILQILRILSILTILUILVILWILXILYILZIMJIMKIMLIMMIMNIMOIMPIMQIMRIMSIMTIMUIMVIMWIMXIMYIMZINJINKINLINMINNINOINPINQINRINSINTINUINVINWINXINYINZIOJIOKIOLIOMIONIOOIOPIOQIORIOSIOTIOUIOVIOWIOXIOYIOZIPJIPKIPLIPMIPNIPOIPPIPQIPRIPSIPTIPUIPVIPWIPXIPYIPZIQJIQKIQLIQMIQNIQOIQPIQQIQRIQSIQTIQUIQVIQWIQXIQYIQZIRJIRKIRLIRMIRNIROIRPIRQIRRIRSIRTIRUIRVIRWIRXIRYIRZISJISKISLISMISNISOISPISQISRISSISTISUISVISWISXISYISZITJITKITLITMITNITOITPITQITRITSITTITUITVITWITXITYITZIUJIUKIULIUMIUNIUOIUPIUQIURIUSIUTIUUIUVIUWIUXIUYIUZIVJIVKIVLIVMIVNIVOIVPIVQIVRIVSIVTIVUIVVIVWIVXIVYIVZIWJIWKIWLIWMIWNIWOIWPIWQIWRIWSIWTIWUIWVIWWIWXIWYIWZIXJIXKIXLIXMIXNIXOIXPIXQIXRIXSIXTIXUIXVIXWIXXIXYIXZIYJIYKIYLIYMIYNIYOIYPIYQIYRIYSIYTIYUIYVIYWIYXIYYIYZIZJIZKIZLIZMIZNIZOIZPIZQIZRIZSIZTIZUIZVIZWIZXIZYIZZJJJKJJLJJMJJNJJOJJPJJQJJRJJSJJTJJUJJVJJWJJXJJYJJZJKKJKLJKMJKNJKOJKPJKQJKRJKSJKTJKUJKVJKWJKXJKYJKZJLKJLLJLMJLNJLOJLPJLQJLRJLSJLTJLUJLVJLWJLXJLYJLZJMKJMLJMMJMNJMOJMPJMQJMRJMSJMTJMUJMVJMWJMXJMYJMZJNKJNLJNMJNNJNOJNPJNQJNRJNSJNTJNUJNVJNWJNXJNYJNZJOKJOLJOMJONJOOJOPJOQJORJOSJOTJOUJOVJOWJOXJOYJOZJPKJPLJPMJPNJPOJPPJPQJPRJPSJPTJPUJPVJPWJPXJPYJPZJQKJQLJQMJQNJQOJQPJQQJQRJQSJQTJQUJQVJQWJQXJQYJQZJRKJRLJRMJRNJROJRPJRQJRRJRSJRTJRUJRVJRWJRXJRYJRZJSKJSLJSMJSNJSOJSPJSQJSRJSSJSTJSUJSVJSWJSXJSYJSZJTKJTLJTMJTNJTOJTPJTQJTRJTSJTTJTUJTVJTWJTXJTYJTZJUKJULJUMJUNJUOJUPJUQJURJUSJUTJUUJUVJUWJUXJUYJUZJVKJVLJVMJVNJVOJVPJVQJVRJVSJVTJVUJVVJVWJVXJVYJVZJWKJWLJWMJWNJWOJWPJWQJWRJWSJWTJWUJWVJWWJWXJWYJWZJXKJXLJXMJXNJXOJXPJXQJXRJXSJXTJXUJXVJXWJXXJXYJXZJYKJYLJYMJYNJYOJYPJYQJYRJYSJYTJYUJYVJYWJYXJYYJYZJZKJZLJZMJZNJZOJZPJZQJZRJZSJZTJZUJZVJZWJZXJZYJZZKKKLKKMKKNKKOKKPKKQKKRKKSKKTKKUKKVKKWKKXKKYKKZKLLKLMKLNKLOKLPKLQKLRKLSKLTKLUKLVKLWKLXKLYKLZKMLKMMKMNKMOKMPKMQKMRKMSKMTKMUKMVKMWKMXKMYKMZKNLKNMKNNKNOKNPKNQKNRKNSKNTKNUKNVKNWKNXKNYKNZKOLKOMKONKOOKOPKOQKORKOSKOTKOUKOVKOWKOXKOYKOZKPLKPMKPNKPOKPPKPQKPRKPSKPTKPUKPVKPWKPXKPYKPZKQLKQMKQNKQOKQPKQQKQRKQSKQTKQUKQVKQWKQXKQYKQZKRLKRMKRNKROKRPKRQKRRKRSKRTKRUKRVKRWKRXKRYKRZKSLKSMKSNKSOKSPKSQKSRKSSKSTKSUKSVKSWKSXKSYKSZKTLKTMKTNKTOKTPKTQKTRKTSKTTKTUKTVKTWKTXKTYKTZKULKUMKUNKUOKUPKUQKURKUSKUTKUUKUVKUWKUXKUYKUZKVLKVMKVNKVOKVPKVQKVRKVSKVTKVUKVVKVWKVXKVYKVZKWLKWMKWNKWOKWPKWQKWRKWSKWTKWUKWVKWWKWXKWYKWZKXLKXMKXNKXOKXPKXQKXRKXSKXTKXUKXVKXWKXXKXYKXZKYLKYMKYNKYOKYPKYQKYRKYSKYTKYUKYVKYWKYXKYYKYZKZLKZMKZNKZOKZPKZQKZRKZSKZTKZUKZVKZWKZXKZYKZZLLLMLLNLLOLLPLLQLLRLLSLLTLLULLVLLWLLXLLYLLZLMMLMNLMOLMPLMQLMRLMSLMTLMULMVLMWLMXLMYLMZLNMLNNLNOLNPLNQLNRLNSLNTLNULNVLNWLNXLNYLNZLOMLONLOOLOPLOQLORLOSLOTLOULOVLOWLOXLOYLOZLPMLPNLPOLPPLPQLPRLPSLPTLPULPVLPWLPXLPYLPZLQMLQNLQOLQPLQQLQRLQSLQTLQULQVLQWLQXLQYLQZLRMLRNLROLRPLRQLRRLRSLRTLRULRVLRWLRXLRYLRZLSMLSNLSOLSPLSQLSRLSSLSTLSULSVLSWLSXLSYLSZLTMLTNLTOLTPLTQLTRLTSLTTLTULTVLTWLTXLTYLTZLUMLUNLUOLUPLUQLURLUSLUTLUULUVLUWLUXLUYLUZLVMLVNLVOLVPLVQLVRLVSLVTLVULVVLVWLVXLVYLVZLWMLWNLWOLWPLWQLWRLWSLWTLWULWVLWWLWXLWYLWZLXMLXNLXOLXPLXQLXRLXSLXTLXULXVLXWLXXLXYLXZLYMLYNLYOLYPLYQLYRLYSLYTLYULYVLYWLYXLYYLYZLZMLZNLZOLZPLZQLZRLZSLZTLZULZVLZWLZXLZYLZZMMMNMMOMMPMMQMMRMMSMMTMMUMMVMMWMMXMMYMMZMNNMNOMNPMNQMNRMNSMNTMNUMNVMNWMNXMNYMNZMONMOOMOPMOQMORMOSMOTMOUMOVMOWMOXMOYMOZMPNMPOMPPMPQMPRMPSMPTMPUMPVMPWMPXMPYMPZMQNMQOMQPMQQMQRMQSMQTMQUMQVMQWMQXMQYMQZMRNMROMRPMRQMRRMRSMRTMRUMRVMRWMRXMRYMRZMSNMSOMSPMSQMSRMSSMSTMSUMSVMSWMSXMSYMSZMTNMTOMTPMTQMTRMTSMTTMTUMTVMTWMTXMTYMTZMUNMUOMUPMUQMURMUSMUTMUUMUVMUWMUXMUYMUZMVNMVOMVPMVQMVRMVSMVTMVUMVVMVWMVXMVYMVZMWNMWOMWPMWQMWRMWSMWTMWUMWVMWWMWXMWYMWZMXNMXOMXPMXQMXRMXSMXTMXUMXVMXWMXXMXYMXZMYNMYOMYPMYQMYRMYSMYTMYUMYVMYWMYXMYYMYZMZNMZOMZPMZQMZRMZSMZTMZUMZVMZWMZXMZYMZZNNNONNPNNQNNRNNSNNTNNUNNVNNWNNXNNYNNZNOONOPNOQNORNOSNOTNOUNOVNOWNOXNOYNOZNPONPPNPQNPRNPSNPTNPUNPVNPWNPXNPYNPZNQONQPNQQNQRNQSNQTNQUNQVNQWNQXNQYNQZNRONRPNRQNRRNRSNRTNRUNRVNRWNRXNRYNRZNSONSPNSQNSRNSSNSTNSUNSVNSWNSXNSYNSZNTONTPNTQNTRNTSNTTNTUNTVNTWNTXNTYNTZNUONUPNUQNURNUSNUTNUUNUVNUWNUXNUYNUZNVONVPNVQNVRNVSNVTNVUNVVNVWNVXNVYNVZNWONWPNWQNWRNWSNWTNWUNWVNWWNWXNWYNWZNXONXPNXQNXRNXSNXTNXUNXVNXWNXXNXYNXZNYONYPNYQNYRNYSNYTNYUNYVNYWNYXNYYNYZNZONZPNZQNZRNZSNZTNZUNZVNZWNZXNZYNZZOOOPOOQOOROOSOOTOOUOOVOOWOOXOOYOOZOPPOPQOPROPSOPTOPUOPVOPWOPXOPYOPZOQPOQQOQROQSOQTOQUOQVOQWOQXOQYOQZORPORQORRORSORTORUORVORWORXORYORZOSPOSQOSROSSOSTOSUOSVOSWOSXOSYOSZOTPOTQOTROTSOTTOTUOTVOTWOTXOTYOTZOUPOUQOUROUSOUTOUUOUVOUWOUXOUYOUZOVPOVQOVROVSOVTOVUOVVOVWOVXOVYOVZOWPOWQOWROWSOWTOWUOWVOWWOWXOWYOWZOXPOXQOXROXSOXTOXUOXVOXWOXXOXYOXZOYPOYQOYROYSOYTOYUOYVOYWOYXOYYOYZOZPOZQOZROZSOZTOZUOZVOZWOZXOZYOZZPPPQPPRPPSPPTPPUPPVPPWPPXPPYPPZPQQPQRPQSPQTPQUPQVPQWPQXPQYPQZPRQPRRPRSPRTPRUPRVPRWPRXPRYPRZPSQPSRPSSPSTPSUPSVPSWPSXPSYPSZPTQPTRPTSPTTPTUPTVTABUABVABWABXABYABZACBACCACDACEACFACGACHACIACJACKACLACMACNACOACPACQACRACSACTACUACVACWACXACYACZADBADCADDADEADFADGADHADIADJADKADLADMADAAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASAATAAUAAVAAWAAXAAYAAZABBABCABDABEABFABGABHABIABJABKABLABMABNABOABPABQABRABSABHAFIAFJAFKAFLAFMAFNAFOAFPAFQAFRAFSAFTAFUAFVAFWAFXAFYAFZAGBAGCAGDAGEAGFAGGAGHAGIAGJAGKAGLAGMAGNAGOAGPAGQAGRAGSAGTAGUAGVAGWAGXAGYAGZAHNADOADPADQADRADSADTADUADVADWADXADYADZAEBAECAEDAEEAEFAEGAEHAEIAEJAEKAELAEMAENAEOAEPAEQAERAESAETAEUAEVAEWAEXAEYAEZAFBAFCAFDAFEAFFAFGAFUAIVAIWAIXAIYAIZAJBAJCAJDAJEAJFAJGAJHAJIAJJAJKAJLAJMAJNAJOAJPAJQAJRAJSAJTAJUAJVAJWAJXAJYAJZAKBAKCAKDAKEAKFAKGAKHAKIAKJAKKAKLAKMAKNAKBAHCAHDAHEAHFAHGAHHAHIAHJAHKAHLAHMAHNAHOAHPAHQAHRAHSAHTAHUAHVAHWAHXAHYAHZAIBAICAIDAIEAIFAIGAIHAIIAIJAIKAILAIMAINAIOAIPAIQAIRAISAITAIIAMJAMKAMLAMMAMNAMOAMPAMQAMRAMSAMTAMUAMVAMWAMXAMYAMZANBANCANDANEANFANGANHANIANJANKANLANMANNANOANPANQANRANSANTANUANVANWANXANYANZAOBAOOAKPAKQAKRAKSAKTAKUAKVAKWAKXAKYAKZALBALCALDALEALFALGALHALIALJALKALLALMALNALOALPALQALRALSALTALUALVALWALXALYALZAMBAMCAMDAMEAMFAMGAMHAMVAPWAPXAPYAPZAQBAQCAQDAQEAQFAQGAQHAQIAQJAQKAQLAQMAQNAQOAQPAQQAQRAQSAQTAQUAQVAQWAQXAQYAQZARBARCARDAREARFARGARHARIARJARKARLARMARNAROARCAODAOEAOFAOGAOHAOIAOJAOKAOLAOMAONAOOAOPAOQAORAOSAOTAOUAOVAOWAOXAOYAOZAPBAPCAPDAPEAPFAPGAPHAPIAPJAPKAPLAPMAPNAPOAPPAPQAPRAPSAPTAPUAPJATKATLATMATNATOATPATQATRATSATTATUATVATWATXATYATZAUBAUCAUDAUEAUFAUGAUHAUIAUJAUKAULAUMAUNAUOAUPAUQAURAUSAUTAUUAUVAUWAUXAUYAUZAVBAVCAVPARQARRARSARTARUARVARWARXARYARZASBASCASDASEASFASGASHASIASJASKASLASMASNASOASPASQASRASSASTASUASVASWASXASYASZATBATCATDATEATFATGATHATIATWAWXAWYAWZAXBAXCAXDAXEAXFAXGAXHAXIAXJAXKAXLAXMAXNAXOAXPAXQAXRAXSAXTAXUAXVAXWAXXAXYAXZAYBAYCAYDAYEAYFAYGAYHAYIAYJAYKAYLAYMAYNAYOAYPAYDAVEAVFAVGAVHAVIAVJAVKAVLAVMAVNAVOAVPAVQAVRAVSAVTAVUAVVAVWAVXAVYAVZAWBAWCAWDAWEAWFAWGAWHAWIAWJAWKAWLAWMAWNAWOAWPAWQAWRAWSAWTAWUAWVAWBLBBMBBNBBOBBPBBQBBRBBSBBTBBUBBVBBWBBXBBYBBZBCCBCDBCEBCFBCGBCHBCIBCJBCKBCLBCMBCNBCOBCPBCQBCRBCSBCTBCUBCVBCWBCXBCYBCZBDCBDDBDEBDFBDGBQAYRAYSAYTAYUAYVAYWAYXAYYAYZAZBAZCAZDAZEAZFAZGAZHAZIAZJAZKAZLAZMAZNAZOAZPAZQAZRAZSAZTAZUAZVAZWAZXAZYAZZBBBCBBDBBEBBFBBGBBHBBIBBJBBKBFDBFEBFFBFGBFHBFIBFJBFKBFLBFMBFNBFOBFPBFQBFRBFSBFTBFUBFVBFWBFXBFYBFZBGCBGDBGEBGFBGGBGHBGIBGJBGKBGLBGMBGNBGOBGPBGQBGRBGSBGTBGUBGVBGWBDHBDIBDJBDKBDLBDMBDNBDOBDPBDQBDRBDSBDTBDUBDVBDWBDXBDYBDZBECBEDBEEBEFBEGBEHBEIBEJBEKBELBEMBENBEOBEPBEQBERBESBETBEUBEVBEWBEXBEYBEZBFCBITBIUBIVBIWBIXBIYBIZBJCBJDBJEBJFBJGBJHBJIBJJBJKBJLBJMBJNBJOBJPBJQBJRBJSBJTBJUBJVBJWBJXBJYBJZBKCBKDBKEBKFBKGBKHBKIBKJBKKBKLBKMBKNBKOBGXBGYBGZBHCBHDBHEBHFBHGBHHBHIBHJBHKBHLBHMBHNBHOBHPBHQBHRBHSBHTBHUBHVBHWBHXBHYBHZBICBIDBIEBIFBIGBIHBIIBIJBIKBILBIMBINBIOBIPBIQBIRBISBMLBMMBMNBMOBMPBMQBMRBMSBMTBMUBMVBMWBMXBMYBMZBNCBNDBNEBNFBNGBNHBNIBNJBNKBNLBNMBNNBNOBNPBNQBNRBNSBNTBNUBNVBNWBNXBNYBNZBOCBODBOEBOFBOGBKPBKQBKRBKSBKTBKUBKVBKWBKXBKYBKZBLCBLDBLEBLFBLGBLHBLIBLJBLKBLLBLMBLNBLOBLPBLQBLRBLSBLTBLUBLVBLWBLXBLYBLZBMCBMDBMEBMFBMGBMHBMIBMJBMKBQDBQEBQFBQGBQHBQIBQJBQKBQLBQMBQNBQOBQPBQQBQRBQSBQTBQUBQVBQWBQXBQYBQZBRCBRDBREBRFBRGBRHBRIBRJBRKBRLBRMBRNBROBRPBRQBRRBRSBRTBRUBRVBRWBOHBOIBOJBOKBOLBOMBONBOOBOPBOQBORBOSBOTBOUBOVBOWBOXBOYBOZBPCBPDBPEBPFBPGBPHBPIBPJBPKBPLBPMBPNBPOBPPBPQBPRBPSBPTBPUBPVBPWBPXBPYBPZBQCBTTBTUBTVBTWBTXBTYBTZBUCBUDBUEBUFBUGBUHBUIBUJBUKBULBUMBUNBUOBUPBUQBURBUSBUTBUUBUVBUWBUXBUYBUZBVCBVDBVEBVFBVGBVHBVIBVJBVKBVLBVMBVNBVOBRXBRYBRZBSCBSDBSEBSFBSGBSHBSIBSJBSKBSLBSMBSNBSOBSPBSQBSRBSSBSTBSUBSVBSWBSXBSYBSZBTCBTDBTEBTFBTGBTHBTIBTJBTKBTLBTMBTNBTOBTPBTQBTRBTSBXLBXMBXNBXOBXPBXQBXRBXSBXTBXUBXVBXWBXXBXYBXZBYCBYDBYEBYFBYGBYHBYIBYJBYKBYLBYMBYNBYOBYPBYQBYRBYSBYTBYUBYVBYWBYXBYYBYZBZCBZDBZEBZFBZGBVPBVQBVRBVSBVTBVUBVVBVWBVXBVYBVZBWCBWDBWEBWFBWGBWHBWIBWJBWKBWLBWMBWNBWOBWPBWQBWRBWSBWTBWUBWVBWWBWXBWYBWZBXCBXDBXEBXFBXGBXHBXIBXJBXKBCDFCDGCDHCDICDJCDKCDLCDMCDNCDOCDPCDQCDRCDSCDTCDUCDVCDWCDXCDYCDZCEDCEECEFCEGCEHCEICEJCEKCELCEMCENCEOCEPCEQCERCESCETCEUCEVCEWCEXCEYCEZZHBZIBZJBZKBZLBZMBZNBZOBZPBZQBZRBZSBZTBZUBZVBZWBZXBZYBZZCCCDCCECCFCCGCCHCCICCJCCKCCLCCMCCNCCOCCPCCQCCRCCSCCTCCUCCVCCWCCXCCYCCZCDDCDECGYCGZCHDCHECHFCHGCHHCHICHJCHKCHLCHMCHNCHOCHPCHQCHRCHSCHTCHUCHVCHWCHXCHYCHZCIDCIECIFCIGCIHCIICIJCIKCILCIMCINCIOCIPCIQCIRCISCITCIUCIVCFDCFECFFCFGCFHCFICFJCFKCFLCFMCFNCFOCFPCFQCFRCFSCFTCFUCFVCFWCFXCFYCFZCGDCGECGFCGGCGHCGICGJCGKCGLCGMCGNCGOCGPCGQCGRCGSCGTCGUCGVCGWCGXCKUCKVCKWCKXCKYCKZCLDCLECLFCLGCLHCLICLJCLKCLLCLMCLNCLOCLPCLQCLRCLSCLTCLUCLVCLWCLXCLYCLZCMDCMECMFCMGCMHCMICMJCMKCMLCMMCMNCMOCMPCMQCMRCIWCIXCIYCIZCJDCJECJFCJGCJHCJICJJCJKCJLCJMCJNCJOCJPCJQCJRCJSCJTCJUCJVCJWCJXCJYCJZCKDCKECKFCKGCKHCKICKJCKKCKLCKMCKNCKOCKPCKQCKRCKSCKTCOQCORCOSCOTCOUCOVCOWCOXCOYCOZCPDCPECPFCPGCPHCPICPJCPKCPLCPMCPNCPOCPPCPQCPRCPSCPTCPUCPVCPWCPXCPYCPZCQDCQECQFCQGCQHCQICQJCQKCQLCQMCQNCMSCMTCMUCMVCMWCMXCMYCMZCNDCNECNFCNGCNHCNICNJCNKCNLCNMCNNCNOCNPCNQCNRCNSCNTCNUCNVCNWCNXCNYCNZCODCOECOFCOGCOHCOICOJCOKCOLCOMCONCOOCOPCSMCSNCSOCSPCSQCSRCSSCSTCSUCSVCSWCSXCSYCSZCTDCTECTFCTGCTHCTICTJCTKCTLCTMCTNCTOCTPCTQCTRCTSCTTCTUCTVCTWCTXCTYCTZCUDCUECUFCUGCUHCUICUJCQOCQPCQQCQRCQSCQTCQUCQVCQWCQXCQYCQZCRDCRECRFCRGCRHCRICRJCRKCRLCRMCRNCROCRPCRQCRRCRSCRTCRUCRVCRWCRXCRYCRZCSDCSECSFCSGCSHCSICSJCSKCSLCWICWJCWKCWLCWMCWNCWOCWPCWQCWRCWSCWTCWUCWVCWWCWXCWYCWZCXDCXECXFCXGCXHCXICXJCXKCXLCXMCXNCXOCXPCXQCXRCXSCXTCXUCXVCXWCXXCXYCXZCYDCYECYFCUKCULCUMCUNCUOCUPCUQCURCUSCUTCUUCUVCUWCUXCUYCUZCVDCVECVFCVGCVHCVICVJCVKCVLCVMCVNCVOCVPCVQCVRCVSCVTCVUCVVCVWCVXCVYCVZCWDCWECWFCWGCWHEDDFDDGDDHDDIDDJDDKDDLDDMDDNDDODDPDDQDDRDDSDDTDDUDDVDDWDDXDDYDDZDEEDEFDEGDEHDEIDEJDEKDELDEMDENDEODEPDEQDERDESDETDEUDEVDEWDEXDEYDEZDFCYGCYHCYICYJCYKCYLCYMCYNCYOCYPCYQCYRCYSCYTCYUCYVCYWCYXCYYCYZCZDCZECZFCZGCZHCZICZJCZKCZLCZMCZNCZOCZPCZQCZRCZSCZTCZUCZVCZWCZXCZYCZZDDDEDHFDHGDHHDHIDHJDHKDHLDHMDHNDHODHPDHQDHRDHSDHTDHUDHVDHWDHXDHYDHZDIEDIFDIGDIHDIIDIJDIKDILDIMDINDIODIPDIQDIRDISDITDIUDIVDIWDIXDIYDIZDJEDFFDFGDFHDFIDFJDFKDFLDFMDFNDFODFPDFQDFRDFSDFTDFUDFVDFWDFXDFYDFZDGEDGFDGGDGHDGIDGJDGKDGLDGMDGNDGODGPDGQDGRDGSDGTDGUDGVDGWDGXDGYDGZDHEDLFDLGDLHDLIDLJDLKDLLDLMDLNDLODLPDLQDLRDLSDLTDLUDLVDLWDLXDLYDLZDMEDMFDMGDMHDMIDMJDMKDMLDMMDMNDMODMPDMQDMRDMSDMTDMUDMVDMWDMXDMYDMZDNEDJFDJGDJHDJIDJJDJKDJLDJMDJNDJODJPDJQDJRDJSDJTDJUDJVDJWDJXDJYDJZDKEDKFDKGDKHDKIDKJDKKDKLDKMDKNDKODKPDKQDKRDKSDKTDKUDKVDKWDKXDKYDKZDLEDPFDPGDPHDPIDPJDPKDPLDPMDPNDPODPPDPQDPRDPSDPTDPUDPVDPWDPXDPYDPZDQEDQFDQGDQHDQIDQJDQKDQLDQMDQNDQODQPDQQDQRDQSDQTDQUDQVDQWDQXDQYDQZDREDNFDNGDNHDNIDNJDNKDNLDNMDNNDNODNPDNQDNRDNSDNTDNUDNVDNWDNXDNYDNZDOEDOFDOGDOHDOIDOJDOKDOLDOMDONDOODOPDOQDORDOSDOTDOUDOVDOWDOXDOYDOZDPEDTFDTGDTHDTIDTJDTKDTLDTMDTNDTODTPDTQDTRDTSDTTDTUDTVDTWDTXDTYDTZDUEDUFDUGDUHDUIDUJDUKDULDUMDUNDUODUPDUQDURDUSDUTDUUDUVDUWDUXDUYDUZDVEDRFDRGDRHDRIDRJDRKDRLDRMDRNDRODRPDRQDRRDRSDRTDRUDRVDRWDRXDRYDRZDSEDSFDSGDSHDSIDSJDSKDSLDSMDSNDSODSPDSQDSRDSSDSTDSUDSVDSWDSXDSYDSZDTEDXFDXGDXHDXIDXJDXKDXLDXMDXNDXODXPDXQDXRDXSDXTDXUDXVDXWDXXDXYDXZDYEDYFDYGDYHDYIDYJDYKDYLDYMDYNDYODYPDYQDYRDYSDYTDYUDYVDYWDYXDYYDYZDZEDVFDVGDVHDVIDVJDVKDVLDVMDVNDVODVPDVQDVRDVSDVTDVUDVVDVWDVXDVYDVZDWEDWFDWGDWHDWIDWJDWKDWLDWMDWNDWODWPDWQDWRDWSDWTDWUDWVDWWDWXDWYDWZDXFGEFHEFIEFJEFKEFLEFMEFNEFOEFPEFQEFREFSEFTEFUEFVEFWEFXEFYEFZEGFEGGEGHEGIEGJEGKEGLEGMEGNEGOEGPEGQEGREGSEGTEGUEGVEGWEGXEGYEGZEHFEHGEHHEEDZFDZGDZHDZIDZJDZKDZLDZMDZNDZODZPDZQDZRDZSDZTDZUDZVDZWDZXDZYDZZEEEFEEGEEHEEIEEJEEKEELEEMEENEEOEEPEEQEEREESEETEEUEEVEEWEEXEEYEEZEFFEJKEJLEJMEJNEJOEJPEJQEJREJSEJTEJUEJVEJWEJXEJYEJZEKFEKGEKHEKIEKJEKKEKLEKMEKNEKOEKPEKQEKREKSEKTEKUEKVEKWEKXEKYEKZELFELGELHELIELJELKELLEHIEHJEHKEHLEHMEHNEHOEHPEHQEHREHSEHTEHUEHVEHWEHXEHYEHZEIFEIGEIHEIIEIJEIKEILEIMEINEIOEIPEIQEIREISEITEIUEIVEIWEIXEIYEIZEJFEJGEJHEJIEJJENOENPENQENRENSENTENUENVENWENXENYENZEOFEOGEOHEOIEOJEOKEOLEOMEONEOOEOPEOQEOREOSEOTEOUEOVEOWEOXEOYEOZEPFEPGEPHEPIEPJEPKEPLEPMEPNEPOEPPELMELNELOELPELQELRELSELTELUELVELWELXELYELZEMFEMGEMHEMIEMJEMKEMLEMMEMNEMOEMPEMQEMREMSEMTEMUEMVEMWEMXEMYEMZENFENGENHENIENJENKENLENMENNERSERTERUERVERWERXERYERZESFESGESHESIESJESKESLESMESNESOESPESQESRESSESTESUESVESWESXESYESZETFETGETHETIETJETKETLETMETNETOETPETQETRETSETTEPQEPREPSEPTEPUEPVEPWEPXEPYEPZEQFEQGEQHEQIEQJEQKEQLEQMEQNEQOEQPEQQEQREQSEQTEQUEQVEQWEQXEQYEQZERFERGERHERIERJERKERLERMERNEROERPERQERREVWEVXEVYEVZEWFEWGEWHEWIEWJEWKEWLEWMEWNEWOEWPEWQEWREWSEWTEWUEWVEWWEWXEWYEWZEXFEXGEXHEXIEXJEXKEXLEXMEXNEXOEXPEXQEXREXSEXTEXUEXVEXWEXXETUETVETWETXETYETZEUFEUGEUHEUIEUJEUKEULEUMEUNEUOEUPEUQEUREUSEUTEUUEUVEUWEUXEUYEUZEVFEVGEVHEVIEVJEVKEVLEVMEVNEVOEVPEVQEVREVSEVTEVUEVVEFFGFFHFFIFFJFFKFFLFFMFFNFFOFFPFFQFFRFFSFFTFFUFFVFFWFFXFFYFFZFGGFGHFGIFGJFGKFGLFGMFGNFGOFGPFGQFGRFGSFGTFGUFGVFGWFGXFGYFGZFHGFHHFHIFHJXYEXZEYFEYGEYHEYIEYJEYKEYLEYMEYNEYOEYPEYQEYREYSEYTEYUEYVEYWEYXEYYEYZEZFEZGEZHEZIEZJEZKEZLEZMEZNEZOEZPEZQEZREZSEZTEZUEZVEZWEZXEZYEZZFFJOFJPFJQFJRFJSFJTFJUFJVFJWFJXFJYFJZFKGFKHFKIFKJFKKFKLFKMFKNFKOFKPFKQFKRFKSFKTFKUFKVFKWFKXFKYFKZFLGFLHFLIFLJFLKFLLFLMFLNFLOFLPFLQFLRFHKFHLFHMFHNFHOFHPFHQFHRFHSFHTFHUFHVFHWFHXFHYFHZFIGFIHFIIFIJFIKFILFIMFINFIOFIPFIQFIRFISFITFIUFIVFIWFIXFIYFIZFJGFJHFJIFJJFJKFJLFJMFJNFNWFNXFNYFNZFOGFOHFOIFOJFOKFOLFOMFONFOOFOPFOQFORFOSFOTFOUFOVFOWFOXFOYFOZFPGFPHFPIFPJFPKFPLFPMFPNFPOFPPFPQFPRFPSFPTFPUFPVFPWFPXFPYFPZFLSFLTFLUFLVFLWFLXFLYFLZFMGFMHFMIFMJFMKFMLFMMFMNFMOFMPFMQFMRFMSFMTFMUFMVFMWFMXFMYFMZFNGFNHFNIFNJFNKFNLFNMFNNFNOFNPFNQFNRFNSFNTFNUFNVFSKFSLFSMFSNFSOFSPFSQFSRFSSFSTFSUFSVFSWFSXFSYFSZFTGFTHFTIFTJFTKFTLFTMFTNFTOFTPFTQFTRFTSFTTFTUFTVFTWFTXFTYFTZFUGFUHFUIFUJFUKFULFUMFUNFQGFQHFQIFQJFQKFQLFQMFQNFQOFQPFQQFQRFQSFQTFQUFQVFQWFQXFQYFQZFRGFRHFRIFRJFRKFRLFRMFRNFROFRPFRQFRRFRSFRTFRUFRVFRWFRXFRYFRZFSGFSHFSIFSJFWSFWTFWUFWVFWWFWXFWYFWZFXGFXHFXIFXJFXKFXLFXMFXNFXOFXPFXQFXRFXSFXTFXUFXVFXWFXXFXYFXZFYGFYHFYIFYJFYKFYLFYMFYNFYOFYPFYQFYRFYSFYTFYUFYVFUOFUPFUQFURFUSFUTFUUFUVFUWFUXFUYFUZFVGFVHFVIFVJFVKFVLFVMFVNFVOFVPFVQFVRFVSFVTFVUFVVFVWFVXFVYFVZFWGFWHFWIFWJFWKFWLFWMFWNFWOFWPFWQFWRHGHIGHJGHKGHLGHMGHNGHOGHPGHQGHRGHSGHTGHUGHVGHWGHXGHYGHZGIHGIIGIJGIKGILGIMGINGIOGIPGIQGIRGISGITGIUGIVGIWGIXGIYGIZGJHGJIGJJGJKGJLGJMGJFYWFYXFYYFYZFZGFZHFZIFZJFZKFZLFZMFZNFZOFZPFZQFZRFZSFZTFZUFZVFZWFZXFZYFZZGGGHGGIGGJGGKGGLGGMGGNGGOGGPGGQGGRGGSGGTGGUGGVGGWGGXGGYGGZGHTGLUGLVGLWGLXGLYGLZGMHGMIGMJGMKGMLGMMGMNGMOGMPGMQGMRGMSGMTGMUGMVGMWGMXGMYGMZGNHGNIGNJGNKGNLGNMGNNGNOGNPGNQGNRGNSGNTGNUGNVGNWGNXGNYGNNGJOGJPGJQGJRGJSGJTGJUGJVGJWGJXGJYGJZGKHGKIGKJGKKGKLGKMGKNGKOGKPGKQGKRGKSGKTGKUGKVGKWGKXGKYGKZGLHGLIGLJGLKGLLGLMGLNGLOGLPGLQGLRGLSGLMGQNGQOGQPGQQGQRGQSGQTGQUGQVGQWGQXGQYGQZGRHGRIGRJGRKGRLGRMGRNGROGRPGRQGRRGRSGRTGRUGRVGRWGRXGRYGRZGSHGSIGSJGSKGSLGSMGSNGSOGSPGSQGSRGSZGOHGOIGOJGOKGOLGOMGONGOOGOPGOQGORGOSGOTGOUGOVGOWGOXGOYGOZGPHGPIGPJGPKGPLGPMGPNGPOGPPGPQGPRGPSGPTGPUGPVGPWGPXGPYGPZGQHGQIGQJGQKGQLGQYGUZGVHGVIGVJGVKGVLGVMGVNGVOGVPGVQGVRGVSGVTGVUGVVGVWGVXGVYGVZGWHGWIGWJGWKGWLGWMGWNGWOGWPGWQGWRGWSGWTGWUGWVGWWGWXGWYGWZGXHGXIGXJGXKGXSGSTGSUGSVGSWGSXGSYGSZGTHGTIGTJGTKGTLGTMGTNGTOGTPGTQGTRGTSGTTGTUGTVGTWGTXGTYGTZGUHGUIGUJGUKGULGUMGUNGUOGUPGUQGURGUSGUTGUUGUVGUWGUXGURGZSGZTGZUGZVGZWGZXGZYGZZHHHIHHJHHKHHLHHMHHNHHOHHPHHQHHRHHSHHTHHUHHVHHWHHXHHYHHZHIIHIJHIKHILHIMHINHIOHIPHIQHIRHISHITHIUHIVHIWHIXHIYHLGXMGXNGXOGXPGXQGXRGXSGXTGXUGXVGXWGXXGXYGXZGYHGYIGYJGYKGYLGYMGYNGYOGYPGYQGYRGYSGYTGYUGYVGYWGYXGYYGYZGZHGZIGZJGZKGZLGZMGZNGZOGZPGZQGZLPHLQHLRHLSHLTHLUHLVHLWHLXHLYHLZHMIHMJHMKHMLHMMHMNHMOHMPHMQHMRHMSHMTHMUHMVHMWHMXHMYHMZHNIHNJHNKHNLHNMHNNHNOHNPHNQHNRHNSHNTHNUHNVHNWHIZHJIHJJHJKHJLHJMHJNHJOHJPHJQHJRHJSHJTHJUHJVHJWHJXHJYHJZHKIHKJHKKHKLHKMHKNHKOHKPHKQHKRHKSHKTHKUHKVHKWHKXHKYHKZHLIHLJHLKHLLHLMHLNHLOHQNHQOHQPHQQHQRHQSHQTHQUHQVHQWHQXHQYHQZHRIHRJHRKHRLHRMHRNHROHRPHRQHRRHRSHRTHRUHRVHRWHRXHRYHRZHSIHSJHSKHSLHSMHSNHSOHSPHSQHSRHSSHSTHSUHNXHNYHNZHOIHOJHOKHOLHOMHONHOOHOPHOQHORHOSHOTHOUHOVHOWHOXHOYHOZHPIHPJHPKHPLHPMHPNHPOHPPHPQHPRHPSHPTHPUHPVHPWHPXHPYHPZHQIHQJHQKHQLHQMHVLHVMHVNHVOHVPHVQHVRHVSHVTHVUHVVHVWHVXHVYHVZHWIHWJHWKHWLHWMHWNHWOHWPHWQHWRHWSHWTHWUHWVHWWHWXHWYHWZHXIHXJHXKHXLHXMHXNHXOHXPHXQHXRHXSHSVHSWHSXHSYHSZHTIHTJHTKHTLHTMHTNHTOHTPHTQHTRHTSHTTHTUHTVHTWHTXHTYHTZHUIHUJHUKHULHUMHUNHUOHUPHUQHURHUSHUTHUUHUVHUWHUXHUYHUZHVIHVJHVKHIIKIILIIMIINIIOIIPIIQIIRIISIITIIUIIVIIWIIXIIYIIZIJJIJKIJLIJMIJNIJOIJPIJQIJRIJSIJTIJUIJVIJWIJXIJYIJZIKJIKKIKLIKMIKNIKOIKPIKQIKRIKSIKTXTHXUHXVHXWHXXHXYHXZHYIHYJHYKHYLHYMHYNHYOHYPHYQHYRHYSHYTHYUHYVHYWHYXHYYHYZHZIHZJHZKHZLHZMHZNHZOHZPHZQHZRHZSHZTHZUHZVHZWHZXHZYHZZIIIJINNINOINPINQINRINSINTINUINVINWINXINYINZIOJIOKIOLIOMIONIOOIOPIOQIORIOSIOTIOUIOVIOWIOXIOYIOZIPJIPKIPLIPMIPNIPOIPPIPQIPRIPSIPTIPUIPVIPWIKUIKVIKWIKXIKYIKZILJILKILLILMILNILOILPILQILRILSILTILUILVILWILXILYILZIMJIMKIMLIMMIMNIMOIMPIMQIMRIMSIMTIMUIMVIMWIMXIMYIMZINJINKINLINMISQISRISSISTISUISVISWISXISYISZITJITKITLITMITNITOITPITQITRITSITTITUITVITWITXITYITZIUJIUKIULIUMIUNIUOIUPIUQIURIUSIUTIUUIUVIUWIUXIUYIUZIPXIPYIPZIQJIQKIQLIQMIQNIQOIQPIQQIQRIQSIQTIQUIQVIQWIQXIQYIQZIRJIRKIRLIRMIRNIROIRPIRQIRRIRSIRTIRUIRVIRWIRXIRYIRZISJISKISLISMISNISOISPIXTIXUIXVIXWIXXIXYIXZIYJIYKIYLIYMIYNIYOIYPIYQIYRIYSIYTIYUIYVIYWIYXIYYIYZIZJIZKIZLIZMIZNIZOIZPIZQIZRIZSIZTIZUIZVIZWIZXIZYIZZJJJKJJLJJIVJIVKIVLIVMIVNIVOIVPIVQIVRIVSIVTIVUIVVIVWIVXIVYIVZIWJIWKIWLIWMIWNIWOIWPIWQIWRIWSIWTIWUIWVIWWIWXIWYIWZIXJIXKIXLIXMIXNIXOIXPIXQIXRIXSYJLZJMKJMLJMMJMNJMOJMPJMQJMRJMSJMTJMUJMVJMWJMXJMYJMZJNKJNLJNMJNNJNOJNPJNQJNRJNSJNTJNUJNVJNWJNXJNYJNZJOKJOLJOMJONJOOJOPJOQJORJOSJOTJOMJJNJJOJJPJJQJJRJJSJJTJJUJJVJJWJJXJJYJJZJKKJKLJKMJKNJKOJKPJKQJKRJKSJKTJKUJKVJKWJKXJKYJKZJLKJLLJLMJLNJLOJLPJLQJLRJLSJLTJLUJLVJLWJLXJLQJRRJRSJRTJRUJRVJRWJRXJRYJRZJSKJSLJSMJSNJSOJSPJSQJSRJSSJSTJSUJSVJSWJSXJSYJSZJTKJTLJTMJTNJTOJTPJTQJTRJTSJTTJTUJTVJTWJTXJTYJTZJUKJULJUUJOVJOWJOXJOYJOZJPKJPLJPMJPNJPOJPPJPQJPRJPSJPTJPUJPVJPWJPXJPYJPZJQKJQLJQMJQNJQOJQPJQQJQRJQSJQTJQUJQVJQWJQXJQYJQZJRKJRLJRMJRNJROJRPJRYJWZJXKJXLJXMJXNJXOJXPJXQJXRJXSJXTJXUJXVJXWJXXJXYJXZJYKJYLJYMJYNJYOJYPJYQJYRJYSJYTJYUJYVJYWJYXJYYJYZJZKJZLJZMJZNJZOJZPJZQJZRJZSJZTJZMJUNJUOJUPJUQJURJUSJUTJUUJUVJUWJUXJUYJUZJVKJVLJVMJVNJVOJVPJVQJVRJVSJVTJVUJVVJVWJVXJVYJVZJWKJWLJWMJWNJWOJWPJWQJWRJWSJWTJWUJWVJWWJWXJWMTKMUKMVKMWKMXKMYKMZKNLKNMKNNKNOKNPKNQKNRKNSKNTKNUKNVKNWKNXKNYKNZKOLKOMKONKOOKOPKOQKORKOSKOTKOUKOVKOWKOXKOYKOZKPLKPMKPNKPOKPPKPQKPRKUJZVJZWJZXJZYJZZKKKLKKMKKNKKOKKPKKQKKRKKSKKTKKUKKVKKWKKXKKYKKZKLLKLMKLNKLOKLPKLQKLRKLSKLTKLUKLVKLWKLXKLYKLZKMLKMMKMNKMOKMPKMQKMRKMSKSRKSSKSTKSUKSVKSWKSXKSYKSZKTLKTMKTNKTOKTPKTQKTRKTSKTTKTUKTVKTWKTXKTYKTZKULKUMKUNKUOKUPKUQKURKUSKUTKUUKUVKUWKUXKUYKUZKVLKVMKVNKVOKVPKPSKPTKPUKPVKPWKPXKPYKPZKQLKQMKQNKQOKQPKQQKQRKQSKQTKQUKQVKQWKQXKQYKQZKRLKRMKRNKROKRPKRQKRRKRSKRTKRUKRVKRWKRXKRYKRZKSLKSMKSNKSOKSPKSQKYPKYQKYRKYSKYTKYUKYVKYWKYXKYYKYZKZLKZMKZNKZOKZPKZQKZRKZSKZTKZUKZVKZWKZXKZYKZZLLLMLLNLLOLLPLLQLLRLLSLLTLLULLVLLWLLXLLYLLZLMMLMNLMOLMPVQKVRKVSKVTKVUKVVKVWKVXKVYKVZKWLKWMKWNKWOKWPKWQKWRKWSKWTKWUKWVKWWKWXKWYKWZKXLKXMKXNKXOKXPKXQKXRKXSKXTKXUKXVKXWKXXKXYKXZKYLKYMKYNKYOKLPSLPTLPULPVLPWLPXLPYLPZLQMLQNLQOLQPLQQLQRLQSLQTLQULQVLQWLQXLQYLQZLRMLRNLROLRPLRQLRRLRSLRTLRULRVLRWLRXLRYLRZLSMLSNLSOLSPLSQLSRLSSLSTLMQLMRLMSLMTLMULMVLMWLMXLMYLMZLNMLNNLNOLNPLNQLNRLNSLNTLNULNVLNWLNXLNYLNZLOMLONLOOLOPLOQLORLOSLOTLOULOVLOWLOXLOYLOZLPMLPNLPOLPPLPQLPRLVWLVXLVYLVZLWMLWNLWOLWPLWQLWRLWSLWTLWULWVLWWLWXLWYLWZLXMLXNLXOLXPLXQLXRLXSLXTLXULXVLXWLXXLXYLXZLYMLYNLYOLYPLYQLYRLYSLYTLYULYVLYWLYXLSULSVLSWLSXLSYLSZLTMLTNLTOLTPLTQLTRLTSLTTLTULTVLTWLTXLTYLTZLUMLUNLUOLUPLUQLURLUSLUTLUULUVLUWLUXLUYLUZLVMLVNLVOLVPLVQLVRLVSLVTLVULVVOMOPMOQMORMOSMOTMOUMOVMOWMOXMOYMOZMPNMPOMPPMPQMPRMPSMPTMPUMPVMPWMPXMPYMPZMQNMQOMQPMQQMQRMQSMQTMQUMQVMQWMQXMQYMQZMRNMROMRPMRQMRRMRSMRLYYLYZLZMLZNLZOLZPLZQLZRLZSLZTLZULZVLZWLZXLZYLZZMMMNMMOMMPMMQMMRMMSMMTMMUMMVMMWMMXMMYMMZMNNMNOMNPMNQMNRMNSMNTMNUMNVMNWMNXMNYMNZMONMOYMUZMVNMVOMVPMVQMVRMVSMVTMVUMVVMVWMVXMVYMVZMWNMWOMWPMWQMWRMWSMWTMWUMWVMWWMWXMWYMWZMXNMXOMXPMXQMXRMXSMXTMXUMXVMXWMXXMXYMXZMYNMYOMYPMYTMRUMRVMRWMRXMRYMRZMSNMSOMSPMSQMSRMSSMSTMSUMSVMSWMSXMSYMSZMTNMTOMTPMTQMTRMTSMTTMTUMTVMTWMTXMTYMTZMUNMUOMUPMUQMURMUSMUTMUUMUVMUWMUXMUOXNOYNOZNPONPPNPQNPRNPSNPTNPUNPVNPWNPXNPYNPZNQONQPNQQNQRNQSNQTNQUNQVNQWNQXNQYNQZNRONRPNRQNRRNRSNRTNRUNRVNRWNRXNRYNRZNSONSPNSQNSRNSSNQMYRMYSMYTMYUMYVMYWMYXMYYMYZMZNMZOMZPMZQMZRMZSMZTMZUMZVMZWMZXMZYMZZNNNONNPNNQNNRNNSNNTNNUNNVNNWNNXNNYNNZNOONOPNOQNORNOSNOTNOUNOVNOWNWPNWQNWRNWSNWTNWUNWVNWWNWXNWYNWZNXONXPNXQNXRNXSNXTNXUNXVNXWNXXNXYNXZNYONYPNYQNYRNYSNYTNYUNYVNYWNYXNYYNYZNZONZPNZQNZRNZSNZTNZUNZVNZWNSTNSUNSVNSWNSXNSYNSZNTONTPNTQNTRNTSNTTNTUNTVNTWNTXNTYNTZNUONUPNUQNURNUSNUTNUUNUVNUWNUXNUYNUZNVONVPNVQNVRNVSNVTNVUNVVNVWNVXNVYNVZNWONORXORYORZOSPOSQOSROSSOSTOSUOSVOSWOSXOSYOSZOTPOTQOTROTSOTTOTUOTVOTWOTXOTYOTZOUPOUQOUROUSOUTOUUOUVOUWOUXOUYOUZOVPOVQOVROVSOVTOVUOVVOVWZXNZYNZZOOOPOOQOOROOSOOTOOUOOVOOWOOXOOYOOZOPPOPQOPROPSOPTOPUOPVOPWOPXOPYOPZOQPOQQOQROQSOQTOQUOQVOQWOQXOQYOQZORPORQORRORSORTORUORVORWOZXOZYOZZPPPQPPRPPSPPTPPUPPVPPWPPXPPYPPZPQQPQRPQSPQTPQUPQVPQWPQXPQYPQZPRQPRRPRSPRTPRUPRVPRWPRXPRYPRZPSQPSRPSSPSTPSUPSVPSWPSXPSYPSZPTOVXOVYOVZOWPOWQOWROWSOWTOWUOWVOWWOWXOWYOWZOXPOXQOXROXSOXTOXUOXVOXWOXXOXYOXZOYPOYQOYROYSOYTOYUOYVOYWOYXOYYOYZOZPOZQOZROZSOZTOZUOZVOZWQPTRPTSPTTPTUPTV \ No newline at end of file diff --git a/test/README.md b/test/README.md index af655f15cb..d844ba530f 100644 --- a/test/README.md +++ b/test/README.md @@ -7,7 +7,8 @@ Contents |[CVE-2002-0059](https://nvd.nist.gov/vuln/detail/CVE-2002-0059)|inflateEnd to release memory more than once| |[CVE-2004-0797](https://nvd.nist.gov/vuln/detail/CVE-2004-0797)|Error handling in inflate and inflateBack causes crash| |[CVE-2005-1849](https://nvd.nist.gov/vuln/detail/CVE-2005-1849)|inftrees.h bug causes crash| -|[CVE-2005-2096](https://nvd.nist.gov/vuln/detail/CVE-2005-2096)|Buffer overflow when incomplete code description +|[CVE-2005-2096](https://nvd.nist.gov/vuln/detail/CVE-2005-2096)|Buffer overflow when incomplete code description| +|[CVE-2018-25032](https://nvd.nist.gov/vuln/detail/CVE-2018-25032)|Memory corruption when compressing if the input has many distant matches.| |[GH-361](https://github.com/zlib-ng/zlib-ng/issues/361)|Test case for overlapping matches| |[GH-364](https://github.com/zlib-ng/zlib-ng/issues/364)|Test case for switching compression levels| |[GH-382](https://github.com/zlib-ng/zlib-ng/issues/382)|Test case for deflateEnd returning -3 in deflate quick| From 469d3a6308bb89e2ca8b6b0a45a2281ec6730bc0 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 28 Mar 2022 07:53:55 -0700 Subject: [PATCH 358/798] Added unit test against CVE-2018-25032 with default strategy. Co-authored-by: Eric Biggers --- CMakeLists.txt | 13 +++++++++++-- test/CVE-2018-25032/default.txt | 1 + test/CVE-2018-25032/{test.txt => fixed.txt} | 0 3 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 test/CVE-2018-25032/default.txt rename test/CVE-2018-25032/{test.txt => fixed.txt} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f60e6025ac..a08a8f5f47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1353,13 +1353,22 @@ if(ZLIB_ENABLE_TESTS) -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake) endforeach() - add_test(NAME CVE-2018-25032 + add_test(NAME CVE-2018-25032-fixed COMMAND ${CMAKE_COMMAND} "-DTARGET=${MINIDEFLATE_COMMAND}" "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-F" "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15" -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/test.txt + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/fixed.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) + + add_test(NAME CVE-2018-25032-default + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIDEFLATE_COMMAND}" + "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;" + "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15" + -DGZIP_VERIFY=OFF + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/default.txt -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) # Run tests targeting tools diff --git a/test/CVE-2018-25032/default.txt b/test/CVE-2018-25032/default.txt new file mode 100644 index 0000000000..5edbff6480 --- /dev/null +++ b/test/CVE-2018-25032/default.txt @@ -0,0 +1 @@ +OBXESYMXQLOTSVVWGIMGKKJOVTYKPPMYROFHSCXQPOFVHKBKAFYYAFTWCVOBPXWDSSFZCKBJOJUWPUQHKBNYZMCYEDEBXLAOREOASIEPAISNAZSXQKMWJSABFVSOXNKTGDCZKRSNBTWWGRNRZWGQEHKKQJGSGGFWJCETJVULWEJAQPAILMMQBVWJWMHWBSIOAXOQNEJYAQSPEOACRIFYOFHTBLZFSHOYGQFDGLLCDEHGPRAUFMANGCKZNZJBMEAEDDPZPJMMFEQGEUOHYFEQUKKHTOELBFUVDMNCEGPTLQYPDFTUGGOEUMUIAKAAZNXAEAKZREKXSZZAKFMHDZJFQDLLSILAMUHDQJTVMYIZWFEOPCKWVSXYDEOSGVWACWZNDDTOOYSFCOYHMCUSELFMSBJIUMPFOGDDJGHELQJSUAEEOWQEJMWRRBBAANVFEUMJZRQGDIWXOYXCZZLMDRHPJAYGUUJENSDDGBKDFRXMINPXRZJNAUPBIOAAKLMFUTZWAEWIBUTYOLPPNUWMFYJQIEMJYKVRNKRXGODFFRMMSKDBBKRJGUWOFMNKQPJLCCNDOTIWVGNWVIQINFPLJLEQRMNSVYFGNWMWYGKHBRSLPCCPHUNXIDKDGIELLDUIOXAJOZGIJVKGBJMGSCOHPRFVUPXJREGBMUXNSCBBRASVMNZHELWNHROPZGWIYMKESWGWNANICQTNICGQBJLAONQEEDEYUIGAOQCDTVBLSSACVCUAURKRLCYIHAYHZZCBVMLALYJKNVJTHYTFDDZVOQBUSDTPERXSTYJKCOGGFLBRQIARKTDBQHSFBBEEWYIEOOHUWKUGACNGZQMAHWPFJJOHMJGULPPXYTCIHIAVYTAHIZMBMYYZXBPLTRWNEDAALDOWVQLNFWZEVSDWQBBYHUYNOJYXVFQYGKSHGCRDPPRSVZWXECEXCWOYSBRWIBPZLHJKHWVTZYXEYGUWAXEUONCVLUGHLTCUTVSUQEVBRYYCIZESPFTGKDJKDQYNIXWZZYSCWIULGKVRJOLQNMWMKJKYOZGXFDUHXEFEFHUMHYKYINHXMINEEJAFYQLHEXBTTEBWGWEAWYODLKRFWATZYJXAFECXRPEDRKPJTJBHFQYFWLCYPMTASYYIHDGURAAUJYTKAMDUNZHXYGPHJVJPODIJAXYXONXEULMKEQRKUYAHLJLTVJUPMYUQSEMEKYCYBPNDDXRNZUQYHDBITAYHMBXSOETYJDWDAKRJGBIUSIUIKBQPSHOVDRCNSBUYDPAPAXBKHLIGEPMOUBYFXAMXDEASVXOUIMPVLCQQJRQNLIDVIRYOEXXIUASCSMSTQECGPPHPGDLJLCRJTWSHVOUNQNFTQEHOIQIUWTOFEIKBCWNLDYIJDUWPBIBBERKPKYYUWNIMOCMAUEVBLHBYLQEALQVTQYNTGASZMJWOPCUVKMJEZFKJZMCOORIKNUZQAPHVYTTSJUBBYFJJHTJRYCPRHVLZFPNXSSXXJDWDJQVSJVUKVWUYGPLBGUTBVLMNOFYUKIKIVBDCIKAKVEQIPBPQRLOSZXNIGIDKNGCLILUSTJXYFJZKRAJONNYAANNTWVDXYTIESYFRGQVIOLUBOHGNAGKAKZTRSYYIBADADFBHLJXDYPQKWAVHQGWZKKWUVAFWGXBEBNVPUDWCOMMSXJIVVLDHAWNUTQAPKVFGTYMOKTBDBQZTHHAWGRANXNAVWIOIPILFNUKUFVLNNLAFFPHBLFYMHYOZKABEYKKEDHYMBDIGAFUHTJOOIOWOLLKINJMOPYNNMBMRXNYZAHQYOTDNKWDIDBPSZJOEBQWPYHZZTHSFVJAQDFBJHBOBLOKJKIOEQTWPFSXZCKWWOXNEIDFXVWFPPEFTXLPHMFVPZYRKZVHHDWXVHCASKVDKHWNIUMJUEAAKSFYAGUUKLYGDVDPWMKIDQEUEDLZWQJLRSDMLSHKIOSDUQIDIAGIDEQZBUTVLPUFEXJCCJRGCFXNVXRRNSTWXCXEORNNMFJFJUMOWOSLUUYCOQKLTTUTVGSUCKXQGPHWFZOHALSARGDPDYOIFBXZCDEMHVNTDXTHZOZDOGCZYRXEWLWLPTMCTPCTYWJXNRGSYJDRCFIRRCLFSZMTVXMHASZQGVHHHFLGZKDGMGAHVNHXROKDARLQWIYXXRYTERPSEDVYETTARZTXOTUGAHTOHOOTMCJBZKNBBQHAECEJFUEQQYXNXWBAUIESPQGIOEABZTMSUIVNUIOFYGLSTUVHKPIVBBHAPSDEXZPPAFSLSJSKGEGKXQZGZYYYBFHEKOQUZEMBMTLXLLAJMEFEWLECDLUWLMQLNZDXGDHRMCOOTGWXKTDFKFGEJSLUEYWDGRAONPHKSKCTXQZCEYMQSUIWTNCQLAMABCIZAAOJCLGRBWRFCQKSTYSDDYOZOSEPYBBVEKIFDJOEVAAZBYYKHPKNNWKNIGMIBUDADWHVKSWCMSWBKQAHBNFMWKFPRSBAJMJCAFAENZBVDSYGEPAYDMDRJOUZCGHQNDAQQZHSBMLPWOFGNNODEZZZSJUOOOPBYSEJFZOSJQGTSUBQCOTVNAXIZFMVJUFWGDDJWRBHDUTNQOSYJEWTEZXOYUQXKOZSBYEQKHOAEUEUYOMJLRHGQKKCICCLNIKCMAXLJZEWOYSTVZWXDXSXWVEWJRTDDJIDEWOYXXKGKBHDEPXZFUPVYWJDHXJENZANIEAUIZBXRIZFHMVKOUHRKRUALDIQSAOLIBFSRNBNFZHAUSGGMYSXJROAPNFXOWSFWNRJCAEFJDNDCRQDEOACSMGQQSQIVVVPSTTEPWFLQGJFOXUKFEMTQTUZRNMUPLLQQPNYAIIOMGQETSURJIJDOVGGWQDIKSGZYSJCSVPETTGRKXOXPMRPEMCXAXDDQTVOWDUGPKRCKRRCBRBDEMASKWEPIRHBKGOFGUNVXQMTSKOLAYJKMAGDLLMOPHDAHXBDQMYMGVVREVFLEZPXEXXFORECDRSTSWXGRNRQPSAXXIZXOQPDLEBDHDAUOMAGPFWVMWCQLMXDXKSFAJZBLNQLLRYDBYPWDWXFCTGFHNJVKMYONKAAGXCALJCRHZWYODYFRXVGVIGYJIQMUOUYPGDHFVEUTZRLFILMZXFRXHNELGMKVNYKNITXYHGZDGYGLXJXBODBAIITGQNUJOKJTAUDJFRKLEVFWBARAXPOPPXXDAFZBWAYFAQICNUIRRVRZURUHGWMXELBHDGYVRNEFNEFSPZUNOTCUNGFOAWYCMKVCDTNPIHWLJLWXVORXFNSKJVRAHBJCFMQHVMLKAKBQPMGQYUEPHLQSZJBORIOJAPWJLHYBCXTMZPZUWJIZVRBOYWQIHRWXGYWQQZLTLNHZBSJLIBKJBQNNWSFLYVBYXUZFSGQZZYRPPKHYJCCYZBIEWATBDYLJLJGNCAUHLELJZVYRPJNFQIFLIGLEPQEVOVKASMSJZRUPZNQTWZJHXLVRBCNXKUXZCNQKHIJMBFPXNLPBPYUOWEIINXMUYGYRWPNQPBQPRFCBCIIKWKJWKQNRNZAFQCXUUZFPHBMQDSLYKQJKAJNAHBETGJPYAHMWHMNUJWMUHKZHPNPDZQEPDZZKGDQOUWIUPWSBPJQSBXAVFXJJUFTOCRKJGHKASOTJXBLQRKVOLJTOUUUYXQQNUSJCOILWWGYRJAZXXWCXAZFQITHUYREGZILSHQWSADJRTIVYTZSAGAXQHDZYZERPDHQOLOFAIWNLYACZRXKFKNOHQOFXFIKYWRRDPUFNTSBWQYGGQFNSRBPHBATAWCSVFANTUQIVFSEHGGELSJAUZFRBDEMBFXMFMOTENHPWKEVSIUOEPXPCKMSGDWWORTXBPTAOZPLNCKJUHEPBLCPRRXLGXUHKEKFIYXNJCYTNXMVEXNNAGESQWJGSFBCCQXLSXQJVVJUIZFNIUNAZCVCNUQWFPBCPRSLKIYLDOSOHOPABPMIVLSYIZKJHBCJXBTQHVEFIQHYEGYDMXWSNVWNGSAXBSDBCBDOFVNUFFVWGHHDBIGMNPFLGPGOGSUFYISQESRSSKCEKUTTUTNYYPLKSEYXIZGBPCQVRYGFKYVDYVKKIONENEULDVNMPKFKTAOBDKBCJBIWBKYLYESVCHCSCVVVWXLIMUDNWJQYJQJIGVGJXZQPUEGYTENAMCPDMAVXXOHZCNPWLKGRSQGCNXTPZNTWGFRDJIOSPAFNJHGUHXCDLWSWEHBXHOPAHBQMKECIGDGVGKRYRGLSIVCYQZAZJWGDJWIFUOBIHRENRDKEXQRJCSNMVTFQBJAIAKTPCBINZDYCRLPFSPCNQLDJYSQQWDNZNIEMYZCOIBALBGXXOLLRIVBDQUNXFLMGRIHDFDNCNCFBTKMOOQSLXSONNDFGNWGMAMGIHCDFZZFPAUCOBYJCOCHYVDKNDSOTVGMHSWHOQFCYXYIMFHJCVFCVJGATFWRYPYLEWTNFVTZDATIWNNRYQFTXDGQPPYQYOJJBYSJLADOODZYJIWPIWYQFTGFYESGCCOJFOSQWCQDULHBXAYFDJEJOLOBHTMGXGNFUUFMDIBXDYFVHLQDURYGCSHIYGYJHMJQUFIUBWAKDIFXQEUGYKIFMMSYKOMVNKCMTYXWIBEYNHQHNMYKSPSZTKPTDGMODMAXEHOABRZOSYYLHYWPIQQFMXODEYOAMXDWIFNLAVHTUHSCPJQGRMQNSIZQXNJEEFFVOYAZMQTPNBGKMXYFLYCXQVMXNITCYDMKNTBSNKPGOFRMAGENQZQEPUMRLHFIPOZSJDOBQYSHDETQCBBLXJAMHIPPHQIIBNCAOCVCOHQAPYCYEJBIVWSJVIOFZYAKFYEIXVDVIVAXJZQZKUOCGGBAHHPVOADXHBWEQRMVRBKOONFLPDCKKBFFIZJIKRYMEWWYATRBVIIKBUACMLRTONKOUXMZCGSSYFCYMNTBVIENZQXDTYNZGOKCRENDDTNZOQRXLDVZXLOTFOVYAZEEHKXRDGECGCGXNVMYOKKNIQPCPRWRAHKVPZSKRBMEAAFDAWXXHJUBOUOYQWPLZGTMWWYFBGBNUAQBSRHKNUGGYYJOZNEOWWYZBMREVSOVTWVLUDCJWQGJPFHPTDHFEQVJJIYARMBGCTSKXZQFGOXOXHMWBOHMEFKRWKJPOKUQRQLCHHPNWEPJFIAPSYAHXUPHYOAPABLLDFZOVSJFNNHVDPNWXPXFEYADEXFVRWKVBVCEOVMFIKPMABJUBGOGCDADYIEWZZZCANXEXMMFKHOWOMJRJTKBJPYRPHNKHPSQRJXJNQPORMUKIXNFRIXUGLECEJYZXSUFTROJJRAAHGUDXXSPKOTBUWJPMVUDQGBAPSQOWYDPVVEOISXLDKOPWANASRPSICRGBNHJQGPSFRPFOZYIRYEOFCQRZWCRYAARQBLEAJDQGQVIFGVCPFSEIBAUYXUXFQMNWFNLVYDFFDCVAISNQYGNCXLKXERSQKRJOFLTSOPRPQQONCVGVBLALFFJLSTSGNTHWHHBTNCFRQLWTGKPWIBWSUEVHWFHKAMBOQMZYGAZRAEJCFBEWEFLDGPMAKCQXCLFMBIVDECFIOOXPCTKCCJDZPECXVACPBOQVWNYAZGRIFJETXUABRDPOQOGZLWPLZETFWVYOZHYGSQVMNUMYIAPFCCJNQOVKZCEMMNFRLVTKDRUTDNAQXGPTWYGRCEOTQMLESJDAKGIZNSTADDAIMCUKZQLWYUPHWSQELFHEZOFGRBVUSOYZQMGJFBWWCGYBEFIHCCJKQOAFXAPJEMFJCVZAYESUKQVKHGHGJMTBRECBCLFMCIIBJPIWFRROVXDCPTTEUFOMAFJUHXLAHELLPYCVZDPHKTVGLRVVUXDKISXVAIYEXVWLSQPGKGPYXLXIYQSPYEQZZVHAVHSNASXOWRFMRSLNPUDTWYYPJRFGPJIGTZRTNXDLNAEKRBSZPMZHWPFPGLZVDTSAXANFKOPCNWSRWZMEBVUOCZEMLSYVDURZQUVRZOPKPJMRDQPBGLZCFADBWRWKABRGOMGKIOLZEAJHXIEIPINCETSTKEGEDYJNZBIWISBSDTZREGNOIXNYFQFPUBQLGWKHTJVSCTUHKYWZPSIIBJFKVQPPQCKIKNDEIRXHIBAPDDXYIBMWNUPOISTKFBXDELZFYBRVAMLLPQQXGMBMNBTJRCNCGGZMHIWKJNAFWYYCHEJVYVXPUWZHBWPKHMBJNGWWLXRRKPZHQLTPKGXLWZICJMFIVPRLSXVUOFLWNHFSZAUJTYFRTSPSDOEHFYFHTNZOLRTYIQJQSEEVREMWRKLEVXOGDQMQZQJWTHOYIGOJLJUFBSZJLHGYRRJSZRCNQRCNVBDRCOYENFVWULRBHOGLLRKWMFXEZKBZDMDKYKFJRIHGUZOHBFOPJLMWXECZVXYZPYAIKYDDVWAXCMPKOTEFMIRXDOFFQCNAUBGHGYVFOCONJWNXDMIANMLMJOIAHRPTVNYWLSQBBTNJLBAAQMTJXLXADGYLLMUZPCYFOGJGCJORRTGSRLDXYODWLVGHYBYLHCGPWWEYJPMSAQWNRNHPYLLHUJEZTRQYJVZEJFUQPVTIKFITRVXUODHQDNWOXVHXFWDVRLTKPJVKKEUMYFDOZJOSCHWQQTFKUFMFNQNDCRTVHSVOFPUOMVDEWGUASIKYZPJUGIDUDPTOVAYGMQWLGSUMCWOEKCGYOMZJNRVSUKJGYQBFZMUINTJFOQOVPHHJRNCSUPDAVMSSRCYMJGCGRRIKLAUTKOMWRNKOZETUTSKNRHXRNDOGXBGUGTIXOLEKKOTBAAYFPJHNWKUNMDFZUTRWTLWIBFJGMXMMZLHTJLWVVPAFGJVPKAPPIMTMTOBKXSXWOEWIWIIHPJGKDXCNSYUKAWUCBHJNYHIIDJZRPQPVPYIZZMUFCHOQGNXGAMHEULGHOTRFKFLRPAOYUQYSXLSVVHYXGBLSDOBBZRMXEQCBTNUOATVMYSTKGKQNEUUEWCWBNGWMWIEYDTLBVZHXDUUDXNHJRXOPSLPTTHSOGBGBDSNAJWCBJHZGIABQFONILLESWKMHLIDLBWIDWODZFFKCUHMPMBMYEJUGAIOECPPIYQGFNJCLAHJUQMNTHFJOFOJOTRJDXMGPJYFVDCHLCPRMYRRLMQHQJYQLWMBDYFFZZYWSVVTBFMHXHEAWXYSXTWBNEZKDOUIHUQADPIUKUJXZYHUUUFIGBQIHNLRXUOVMEUSILBUBWEBQRQFQMHOWCEUVUXNNJLNNKGSSEQQZNBDVJYWXLAGGHSBUUFAKMYKRHCATRTMTMNEQHNQWUOPNAWHOCGIEROSOMDJJCQQLSXZVZRVKUALQTFJUOQWMATSZTQBDINTLRDTMHGPIAUONZVDRSFOTAFDNWLUCSYCKAYVCAAYJOZPHPDNIJOGBOGTDLNXHYEJAEECJFZNDMEIDSMGEWTWWSKWSQYEDZFKSRNPQZTGNYRTQVWDBGKJYVAEJZWSQAHWNOHNDRHZAUYXWSAMCNPJBYLNPIPNIFGXQDGRZTQPXETWLZDZVKIQILLEIZDDFLAPQFYFHTUHZIOYZLIGTJMFDATODQNBIHQIOZUTQQGFDCSMSZAFKJFXXYTDGWDVMNLTBZCIDNWXWYXANDDGVPMWGCRHAQOVWPXHVWBQLSCXPPJDYQKLVDBWZBNATRXCPYBOHIGLREODDUVFWLRDSOXYICZPITCQXTJCYGNQPKZXGRHOEKOZTMAYZLUHUYPJKHHFTVSDKELBLVBFNULMMSIERUKEVLCMBRBBHOFGVFBIFFXSYKAMSVXDYUIOGBHLKNNXJTEWNDQJNRGJMKVPFRIJHKFRNTTDSPRECSOIFJUXSIEREFEIMXBMWSBGDJPVIUJUEPAQOOOQZGNZORAKQOVJKDAWSLXSJHQHUIASLQVJDWWXLNPVSWXOGMGUHLKOQUYMGTPKUUEEEHXZVMIBDQJSNRDDFZEOEMMOIJLEYDCDDXGPAYEMXDRXERZYPNHNWOLOTPCDDLLHQPLBHQDKTVJNMFGAWXDHAONUGAWQLTOQSCOMVAHYTYHXQVBKENQKNVOWAGEZVUVWVQKDQPERCLETOCMXIJXDMJRGCVAQUMWHDOUOQQAXOHBXJDRLYGEWUZTIMSTMUCZGOPEBSWIQGPGMTIEGWNGRQAUQQGSLVWKCZTZMOTUOVOCDYLPGZTMNVGHSAGHRGPVTEYZKBVUQNYTHTVMWIEMREKWBVRXLHEGZMHKIWOMOZFPXDPXXPOYFWRLUSBBFXRZWGXAIYYSQFEWQMWRHMYMLFFMBOGAZSDJRENVAQXGDCKMRQYQGWVIDECLOMNZYCCMRCLXWPUIWGNATOQZUYIRDXGCOGZIJRDBYBBNFMOEPYUUJYZJSGICOMXWBAUMEBJVWGTRDRYQGNONJZXSZDJLRAMLJLFTFZUVZZOEOLKFOGFODQBWYBRDMUKEFLKDUADCGKYTZUCVRUULXCXMKAZCBCUQLPAWCHHIFIPIXFZRJHATGQCRWCCMSDXRHASKDKACAVAPMYIYUEXZFJCRPMOTGZJLCFOHJMRRCADBGLMQTBZAMGGLIULVTBOKKZTXRODXTAZXQSXDHPVFFPFLMJKDJNQYGLGUNVIVUWJBCWDYASMCYPTPFZBVUCMUWAOYOUBZZTJEQNIZMPPEHRJPJJKAKHRNGIHUGRGZGRYCOIWXFDDHJKQHSOVNQLYZLABMFFWVQXBPNWNGYMYBLPTLLLFAPTNNBPLCKOIUBNPNCBHJIVUAVRENTTPRWXENQAOUPPEMSOIOLXMQFIAYVPLSCZLYDIOLZIUCBIBYNAWSOUQXDYZPQQHWAQLZCJSRDUUPEKFYWYEFXOHSILHHIJDERCNZEPHGODFOECPZONRLPCFKGUXNFOPVGSQCPWNMAVTPMGSPJRRFIHYXQAGJQWYBBBGTFAAODFFZKDGCEZTHQNZKXKQWFSJKIKTWBZWWRFYIOVWXXZYYMPLUJZETDXGJUASQTPZVBPYKHJLHSCONRZWBUZESWAOXWUMPORTJCQULFBHWIOUOPZIPLZRDCWOCQXHPKNHOYXHTKOFFVIZLGMJMKXQLYEURGMQZRCQGPPLUDLECVBNVBHAWBITJYAVUJKXPAKZDBJGMOFUVOYVAESRHLQVZRDOZPZDWJDWGNXBEQVIKHYIXRIANMIJARWDSAGDKQCYRGZZOFEGXDCMWCNYHDFPOYKSZIGNWIUBSAXPGPDRKERFWILYDILHHXGKKWEWCLLUQDODMHSAHQTOXPLMTTVXRIVIRTJRQFXQHTVREBIXOLZSFNUBXRFSQHSBFHUMMTNVCNRDCAQPSYKEUYHULCSKSYULEQYMQHHKELFXQIPWPEBNBCLVBYEBTQQAZKHWJGIHDVFZHDSHCZPHCWOKRWGSLGCOZEAYLTFJSEBTMOELSJXEGJGCOQPURSZOGOANVZVBTTGLPJYSNUSJUCACWAUTJIAIMIAHLMTVRYONFWCHRYGLSJITEVEFHCQQKLVXMVMAQNEKMKRFJIEUZAPKXDRTHBKEDMSCMNZHOSLFUTXUIDFPKOWRDRADBCWFDZSAJOYSLZMRFLOPUHMXOEECQDNRDPUXFQPOYAKWHIQWIFVNOOAQQHGUYVZRFCLYJYYTROCMSRKXLBHMCBACUNCYLMEWEHTUPFFRJEJAWKHYJUWBUQRKFMHOYSBSMZVIJNRUSEMSMXLPQAKAYVGCFARNHOHWTKINTCYLVNWRGALUZBIQQFMQGBXKAEUFDMVOTJLZGOGMIDGUUSACUMFMGFVDZIRWAWFXDBNJZJAOAMXFVBNMJBEJNMYVOJWLSBFISAKMCOVAKYHBPHHGLYSLZLHPDFCQRPFKUOXKFXZASEPZLMITPDIDENSDCGPFRQKGEZQNBMVWMDGUJMPHMPZAAMSAFRQGYAAGXGUGKMLVMZSSQSREGSOVWUXGQIQXNVIDJDHGSKNCWYOUOEWGVESAKGSMGBGEOZMIUYOPIAJXTBQNXEGCXMVHMOVNHLBFKQFNLOEKISQFNEKNDLGBIBAOEWNBALNSIKGZPWOMLAMTQZPCGLCTPDHFQBNXWFTAPXFRCKHHGLPXKDIXEWPYWOAIAHYJEVXCGFBVROFIVDABRSAHRXGALKMXWARMJZMNBFAMSNXOXOFYMFIXDLEUOBQEHZCXRZYJNEXRDHJZSWZMGAKWIGKYXGQFSEAXTXUWHOKWKINLVBVPTHQULCWKGWKJTWVWODZFFVMTJIATOYRHKRUDKVHJPJJDFJKICWFLEICXOKTGAYYLBWZONTDEEHFZYNPAAJHFOPZJNRWTEECVMRCQIJZPTQNEQDTNKLRPNUWYPFFDVEIWRGQFXUHIGRTZWLLAAGODSELKYMRIYAURIJSMJCCACPVAWMJVJHYNPHPDBSGSXPRNLFOMRPPPTPIMRQAZFEWPFTEDNIBANBUGMSCPJURJZSZBLFYLFDHVIJMLWOQRUOEIQSZYCBVEALSIZMSRNRSBJROLAYNVRHYBDPZQEUBXAJXIDJYRMGULISLPLHLTOONHKYRHRCYNYZFZXIVGMYXNFMKLVQNOYOIQISIUHUTUJIGAFKENBJWMCLGEZNTSMHNUFZLUCJTITIHAZFKXDAZBRUFQXWJEMPTDVLXBIXDPLBPHLZGEYYFVRLZBFOIPHNVVFOJZBGYMRYLMXHJQVDQSFWDNLRKBHHUXWHGRCCDPNVSCSVLXJLHARQZFNRKFHVNKATOKZNTIZSERSKNJMKFSIEMWLUXHRKDFGMOBALHUXOYJRSVAHZUFMZNDHTMYKKPCMIVWBENKTXEBRHJUGMRXHHRWVVCTRTIRQPILWKAMKGJIGMQRZJITFOVHLYGOFANJGQKSTVBCGBVJWRTDABQOUGNXOGBERVOHCPCXCOTREQHMLGLFRLFTDDADUJZZTZCBKATKUAPTRQUHGWFUILCISGGNLCBCAJGKXIXZQCCCJPKKVMNXEDCRANPMFFOKGSPDFAFQQCTEYVAUVUUENWWVQQGHGCHVDGSWPGBPPISWUPEDNODLWQXNSHYQAWJANXNKACXXTNGBJIHHZSBDIBHSGPZGTWXGQVPWEBCREOZPAFHNFANHLHVCYNZQMIOFOVSCHXXCQQSIZMXTBFCULNPCUGZMLWXSDAHRFENSWJVWXFCATCDXZKYQRHCNQDFGRDAGCYDIGPYWSSPTSJZOSCOXEBOWXNQXUGQBTUTSDKHEXNRKAWPLUVGWVPEBMGBQLMKHHNWRDOPCUZZGBNHBODDNLQOWRWFBMXDWYIXIXGGZWIYUKXWRIPBDCLQGKMHBHRSUJOYNBXOMVYQPLBLHEIHQAGKYXTADCVLXKGZXBAXLOXWBSLRMMMTPTXQRYFVFTHNKXDFYOEKCVMHINLNACPQNFHVPYMDSUHGTSWJVZHSMNXONFFYCEZUEGMLIBIUGTRMWQGVXUZCRUYAXCMTXCCGDHSTIREDATCUSTBHGAURHOPAYKCYHOVTVEYWPYGXBSVTQAFGBRNVEDMXDUTWXXFWUOSMBOKJEGSPSFRYBRXYFFCJVEMEYPKSHEXHUBRCHZTIPPTMIYKRDSUJGICXPGATHUNVMVKLEXEROYTRMYOGCQTMJWLSQMAWUUIQBDRNCCEMHWKKIVIEKCVBDEHKRZARARXLTVASSMHGDTTWDVYIJWITWJFILRABYGEOQPCHHFXXRFMOYKCPAQRPBOJJLADKVPDSMPTAXTMZJZQPMQOQBECGZDDKBRLDMBZZEBJAFXGXJNAZDEFBCAXBEFXPSETVGQXRZBGFMBGECCBDBAWRYIVJOQIRNGNYZIRFOPLESXVYVGHKRAZQWCQWIKPBYLFZBRFGFDLYNBYZRYDVUOUXECTBFFAUESCYLBFGYJEZOBVQQABDOOTQCNUNKZLVOHEUSOXZWKYSKZSPQNVPAHTMXLLBOUURUXLFMYWKQGTPHXUZJRUOTGEABCBCNZADCKOEIWZBWFUDMOLHAPQQNNARUOWZLADHNLDUPUADBBZACUPKDBXEFZOQEVWPJMLMYQWSFFHBYKSBMZXLMAAUAWFRWZGYUSDGCEGDFOWYPMWXIHVXKCLWEYXBVQSPMEQNIBBHQRKVLNKNQWEFAWUJSTMZTZYESSYIWLSHGCGRDSESWWIDWTOEXFFCYDLDNDNIEYLXZHIXFZSOQRBYSWLPVOWEEYMVDAGBZMAAAGMZSCMIQFOHJKCCAWJHAZXNIVBHIKKEKGUQIZPRLEXPCNJSTIQJOWUVRDIZTHFQCTHCWWMWYPMPMEIVFAUQOLINCKHXNBADPHNFVZOZWIQCYVUGVOMZTCJIRIPKVVZZPKQAZWCQNLPTAUVXJGKUOCJWUPPPHPAFQOTGJTFRFQVGOXHGBKQIPPAISJIZKBYNNPAXAGCMTXDYRYNQLMAEKYLORYHPJJNCHFSHSUMEOPJNCFYOLONJQAGOAYHQKZXKEQOHTHUTBRISEINMZZZULVLGSNVJUCLQVGPTHPNCKHNRJPPCVMGWZPTIOACQWKUTTUDUAMIJFOZHNGNZHFHYWUFJEJLIWORKAGEBYCQKWGIFOOSVRDRFRQTQUHSZQSCIJUAFZTBWXTIVUFBLDCAJWFBKEPTVVXPZGOHNNNNWYLLIDZHYJGWHCJUBWDLBSXUICEZKEVBCPQGWVIKLTHGVWVAAQXXMGCFTIUGNSJYAMOWAOYGTYVYZPPBEMGGGZZQBUIRELHZXTZSYMNHVXTOIJRYOUOMZNNHGXJJKFMCLTGGRCTEQSXWPZJPDECPUAMGXARWINTDXDDLSNHYQCGPSEDSNJITLKJLZRPAXGJOUMBVFMBRKEZYOEBETWXSZJYSQWFEQUDBPYNYSBRDJOKBFXXLXBNSSFZBJLEIICFMLFXTCOLAODHEAABUKRQHGYSEAZPWIJHZJUJMJIFVUZYBZKSJOFSOVQLYUEGDHVIUMAKLKQJQERNZLLYGEDQGDQCCFOKJWBUNGQNSWMLPFWTXVGAWJMQNBDLYIMXCXNAHUECCILVTXWEMPMXNZQDVYMUWOVPRDOHDHSYKTYEZPMOFKWIXFCGXWHANETZSTTISMGHOMDCTTZIXOOCFRLFLIAXNJWVIMQWEGEZUARCLNBETGINFONHNOEHERRJPRYNBMCSSIXVHCISSUXUXINVIKIMCZNPXBIYWNWQDEZTXDREVXEMAWUASQJISTRTDJMLSQGLQVAURUKZICWNBXQJXSNBZEYKPTPJWSYDCXFZVPBPPSRYUOQQQDNFRQOWVYPIMZPBQAOHTZMCUGJLNILKFTCXQIHQCXBNEKMBPUNULWCNYNMCSFTZZLWPCBUUGVEZYQYQADNHTDFUQWWLDQSBEUOJGLYBPNUMWCDPAAFMGMWFIVLDMXFQWCUGMTMXSGKZKHJGSKSHPHGSIFVQFDTCEBAEQBGCYXIKWJFNUSFOIPHVIVSDCKNPYEVPKWENBFHKYZYTEYULFTGUXCQERPDVDYRTGCOWLIWJMDJFDFHARDANOPOOOPJKPVALZSEYDVSABYLHLCLSQXBVDHVFSRHDKHKJWBGNLMVYKEEECQPPUWOEMPEXGYCQFNCDKMEGPBVUMEOMBEDMCQGSNDLHGMGDMTPSPYOHBZYNBBMPSOMAKEHVCSCEEENUFMTEDDKKCTOXTQVFQOJNSXOHWMMCNTOVFFXHHIBTOTRTBMJUXTAVBUKGCLCKTOJKAZYRHJCOXGGWGZQMJNGGTGFMEYFSYQPFGFOQHTCQBGIUZAJLJJTYLMVZUOJYCSJFOXIZKOJSSGIWSBYYTQOUJDDELVCWQZXHSCGASBZQZSIMTPJHBVGXVPYLDNGIPCUXFAJILVPXTTBCSIEPABVBETVRCXDSDGPETFEFGKYDPABNJIKLMBINGAQJVPDKSRFOWARGITJKRALJENOTDNOFQDRUSKYOUGSJZQFHJAYKFCYNJGWTMYPREHKDXGMBQEKTEMTEBYVXYGGLSBWGAKJBQFEORFLJFYMTJLPPATMOUVESREKJRLOZBOHQLDKLJRHBPBHXVMBTJJOITGXMXGAQDATETWKYIKXENGMAEAMHYXRPPXBIUCEMSKSGPTIWSQDXDLXTPGEZVLENCQKBOMJMQEZFVDSJOFGSFEFVZVUPXSRKWYPNNHUDQSMFFZUIKCWVHGZSWFLXGLXDFSPITBEXVPFOALBIMXCAVIZUNBHDMKVGGXUUXANWXSEGTGKVBWXXGHVFIVLVAGVSVJJLKGXEYXYRMPIKYEFGNQKRXQEBMBADMLSRNIWBCAISXVDZVQHPIPXQLSKXSWUMMMAJOUXWSOEFHXZUEWELFVKKKIJYPRWVYPIJMYBZBDZZMTIJRKUGEGASHZASEJPUEYQJHIRXFQAHEUGWYDPGCJCAGBCLQLPGAPHDNVVWKJHBCKXNVBOJGOESBJTTQWZXGMUHBRLHEQHXOQFJMNSRYWZURFQSBXFCOHRHJNIQQOIBRQUWQHEGWIGSCWQYSEYDVBFFFJXYCORRBRULIJZUQEXQUMLNOMTRWSHCRSVFQSVKKSKVTRRAHLLYKUKGQXZCJHTZAJQKRCYELVNGDPUACTERKRMHOREGYUMGLLIFEXTFYIUERCDVYDBJUMDDUHINQPYWOBHBDDPOTWPLDZPAVVZHPSEDESRDFVGRZETCMTGZFVGVVZCDZEUGYFSZZRPDBJVPARGTOCVPEQOVCMVOOJJUJCXBIBMNRDBAGOJBTHKZUAYPIRNFGNENKLQKJYHSFBPQCURRNZULGKXJTXWYOHUNXPPJWQLALYACFUVYEDAOOJBXRBYGGDQWIWXONWLCMMIGGJNOVIEMZKGBHOELIUDVIDZMXODEZGLVCAKKDKZELECPGUIMAWROODHLMFSSKDMOQCIQBQJWGQBFUCQLJUMRAKYBOEYVXCQTJMYCUZLOXQFPDWSRKKRUUVWUQOPZAUUMWZPSVQMCMLINZOXLFZNRJACEESVDVEBZZJPWNIJAIMKTBXRPSCPYVKTVDGLLRDZOGTRIJSGQLOREUZRQJHJBEVFNXTFQZROKSHJUKXVAVOYGMWAWBYWSBWHYUCDWBNHWHNSKOXSLRTSRFAJHEWVLVQSPDSIHHONIBSPYLZPXTQKLVSSCELGVJCUWIVTFENMPTFMZWXSCXXOIDADDUGDSNFQVAVAYIJZLNYKNNLCEIPKFZPIETWFXXZXSFCUBRTPAEOOEKMCXACVBDBFXPKLBRZNFTQSHEOCECHWESZZFXICIARIASHQQTLEENGCGBHHHXQDBUUBQYGGFGURYPWSMWUXXJHOPCXHSEJQHWNSMJBPYYVMUCSJEKAPFYPDMMSSFTTNYXTFQPYXJEPFEPSBODGVEKBZRXRQNODGBCSVEMWWYGQRTMYIVDFOIBBOCGLSFKIQGUDXNAHMVRDFPAJYDZNCHMDATHJRJXTWHTGBYUKTOPOSASGHTRZTTHPUNEMEFTWDOSBARKQPQDUEUXUZBTLESCECMEIONDSXHTHBKBZEXTHFPQMMNCCUERGPBXQHBKCLAWJMAXNEEHSANEBBVTUBXRAYFSKTSUBORMFOMOJGGCCGDSCNWSEKZFSKEPFNTDFGCDZHGBEFXOUTFTTLSBLEFFPZYMHCKLKKITSTXOUGTIDAUKNXWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRQIAOMZFTFSYWIZUVEWBYRASNEERBQQZRCLIMRCPFZBBEHYFKQQVIVEOZRJGVNGJMWYRXLUIUPNPOQXJPGXJHMLOKWIZYUGULZZOKEWWPGKOXAGBOUXMRMNJBDTOBSOBBNUQNAIOFBMNQPNSKTVKAUNPMXYDCGKNDXBVDFHJJSTTQKQDTTRLNAIFTUKMGHGBMMHHHQLLUKRAUINVQJMFIOGJTZXMGVCKYOUTKAWEPIXSGDZTCWIQSPZLORMQFERHAQDXTYGYDCXCHGCSQGWMCWRSHYNCCCNJCLINIULDINOSIABUZNGXZRYWVPPAUBAPUZUKCKNSXFTIMGPNVQKLGNHVCDAASZOMZVDKKDUMSZWJVKGODPMYYVZKQSQLUMFAIZWZJWTDVDLPDWYPXEMCEHSLGPGOPUPFPAFOKCUVRSPYCVKOUTZAAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTTKLHWESYRSIQHCINUULFSXARVWHNEWPDCXPAZFHVFQGRWZMPHKZQMKVVFKKREAPSFGJMPCPDGEKNNLVEVOWIDDHTJZDIYBMWOBOSWHFITNIUEVEGGXDZYRAIRWTHSECVCCZETCBXGFWSJPHFLCTUNESIKYZKJCTZFOMBMWYHTTXRZKSTVNHJCQJCQLPHFANJTGZXOJRGGMYHXKQVCLBAAKUPWGUWGXEAHQBGJRKABJEUQUKOUABOVZDUKHRRXSBCRCHDFDUXCRZCYCHAZCEGPJFUATVHUHTAFLKSHRYVNYBVXUFUFYXIVGRBRUWPZZRGGNAURWMPKFLCJUGYBJHHTJHCNZQVDVLMENSPFDGHRSQNMFGMUXGPUOIFDXOCFCZMSSDCSILMEYHDIRXQWTOEGSTNXEVSGJGMSTTPKRKAYXHJZCTBTJICBESEBVQXQLRTILEGHXKEIWURTWYLNBFRCNQZUMPVBDVJFNHXKWAKGQGJQMEFFOQDDCQGGMWARKVJROXMKTECKOYWNAXCIVQUUWQCTTZWIBBMTMZGDJAJFNDLVCSALFREYMTHUGQWFYXALWTTDBLDRDZUVWGHBVDAAIQSJGTOUYWTNNFGAGSPGVREBHWDRRNWOFHHQCANZCVDCSHJMBHWRNNJIZWEYFEOKLCVAXDEGHSEUYZHPTFECVAJSFUSFMCGQLMASXUPQYQSNYRSDZVWZUXCDNVVPGAUQRGCQFSQSDEBWTXZDHVDXJMMNIYAQYXEPJVDKPKQBSMWLATYCUWYSYOJZHUDSXTCSHTRACDQOQSNCYLMXJBYBBWKSNHYAYVRLCWFGAZSEVBIUJETIVGHEBDPXLVFWWTCKOUCOAOPMUIRPYZCULRWRCTZLCGMGREFOGJMULHHHQQIAOXVBGVBXZOLNVAPPKFFHXZMBVVEUSQHJOGBNVHUSEDNVMRKVJCOTBCWULBAJBEYUTCVVHYZCXFVDALNLZOARGOCWBFVUQKKSLEMJRKQIHULBCYTZQNRVSLSTQHZAZTZZRTBVXTTHBZJAXCGRVSCRJSEEOJQXFAEAJECDWVEHTBYEIQNMLILIEAAHWBXHQXEDOJKYNBBMTWQDMLFKRQRPACBSRLULLNLMKETFZJAIWHMUOMTZQUXRXYLQWUWZEVJWSVWUZXOHMHMKCHEOIGTJYCLBYPIWOXTHBWDDXMDCMSLPTAGECGNUPHOZBBMUSISZUBTASDXWBZHFNWSWHODJOGCSEUIPWFELWENSKIOZCQRTWINQWOXNSSJVFTGMXIGZDVRGQVODWEVFPRFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHECPGKZWYSJQYVIZZNDYTHHHAZQUQPKQQEJZDJOAPXOSMCBQMLGPUSNTWZOLTGHCBHVFMHHWMOIEWINCVJUCWMGOAPWLNFNOCDJRHJIWCMXOWKPLCATJMBKONEUJXGRSKQWTQWDUPCITOFMCIYVIIEEBCIKARCZHNVYHWQWPFHUPQWKDBHATSGTSDEHORZHLTZZUEMVPJUKSYCIDVSBPFIVDWUOZAARAZQXSQSWQEMKBDZPJLRRQPBRKJUJEICHUZOQUOGYWGUATEKLZAZIAQVWNHYHMXVZDYACNLBIHHETCMNNTCTPRIFYKHNFHGVPFWRYFLKHFGPEDNQORZSVRAXADBTTEVRJSTJJACPHYXIKSXMYFUHKYTDQCXQVBEBVGALWFKWNECWXZPYEUDORKJEYWHVGUGMOTVSZVSSVCRIPERIBYAAKWYLEVWULZHNHUKLVYKJBQXKGZFGRCJRQCATTSQWZCYLDBSZDNAWLHVHWQULGSVAWFGTXNBEHRBBKIXYBQKJGORBFDCDVNPVUJLTGRURLAYCNPPAPNQSIRJPTMAJJSUVLTPVDLKKPWOLEGHKMEZSBYHJSOYMZDJDYUUYDDPJSLVXFDQCTZUWAKYOYLKBBLVPHMWYGUDHPUNOIGSBYSMQUIGXSYHNGQTSUKBWTSYIUUBPGYTCEZLKZSNEXYFNPUKCWAOTVKEIKZEQDHPYMHRTKXEWKXYYYAXUYQIWCSHAGDITDDOQAUPJOJORXTNFKOSCZJRENDFRCXRBZIQPZWDDTYZAYPUINWXLYZXJDOEGHSNPEGVCCHVQXARJCGFWISPUHKFMMRYEEASNKZWXVJUPBZLLUEHNPCLAQWXBGQRBZCDHXBQZTUEPORJBQUPBDTIAWJTASIGTLUBSEOQNXAEMLNNAZIPCBUYSEWCIXLAYJUECBICMZWCNJBZVIMJYZTDTIUGIMCJVDGEGCONXVRQYYIQHUWQGGZBDFPKZYLXGTIOPRGTHCJJKYDPHFIWMZMOTCEGEBDNLWEYWBKYRBRHTEYOLZQTWBIWTHPKZJMPMBGYSBMPJXRPABBVANDBQCTZORWDALOJJNJZYJWUEPHZOVEGRAFHBCRETBBBAKQUTIJNDCIBGNTZOXPGLVBNWSWWMLGOVKOQUXFAXZAQMPPKDSLQBUATEXZRAOSDGOPNVFSPLSNKIECMNKKVYUAAEBGVFOFOATZCFMMDQAFYZTCZFCLWFUTDCPERAASRQVFREZNQXVWKQCAOFLOQMYLYUSMBDXGNHRXRWMUWVAGGHWHLJRGGEAGLXBKZRFXGDVJUFUGBHYRWHKVWOZJFRNZDZCSWZBQTXSDKDLJTSDXBOMUMRAFEBOCKLXOMATMUDBXOZYEVLWWEBBIBOSNBBBHIOPSNDOUDFOUYLOZQWJIOGFLKVZBOUPKIBJFCVNJJYWTUCZEMYJLQSBEPBYKUWFFURQZFKNHWROQLUSHRPNUHGIHQWEZXLYSSKGUTZYRHZCABLEEQXBJOLOJKFSYRCAJFFBCSWODYDVRMMQXRDQIKIEGLAWWVXNAVIUXWJFHBFWDJOICUKHNGPTLLPQYTBSFLOCJQVDHJRPIPBYOIOREUBRURYGLXOCCTZIAOVIXCMLOQLHZJMETCJSLONAGCECYXIXYVMPRWCIIATOULKAMNEKLJZWVZUMHUKJXTFLDSABAYZNGRLGAFGFUBHGXSJNPQVIKSKFASRJPAUFNWZTDIDBXTUSEJHYYRLPFVYLUEOWAWVTJYHXPPDEDUCUIEUROMPFXCAHYLAKPIXHJBINAMIYAFYZNJBWMTVEHDZCTQZQUTDASDXGEALLFLJIRJSGVUOBLVYDHBIMTNYLIARKTDGTLUMIGXQGTCXHHMADSQJAIMXICZQCHRMMJGUNIPMCBAFKOSKMWNGWPKKWKJTVIPTUAVTSFHJTJWTDGCTSBYWJGHGMAGGJHPDMKCMHGAOYJAAQWYCBMPKUEYHOAKTMSLJXCKDAJMHKNAPGCZLDPGZRJYTYYIBDQKKOQHNXDBNTBEVUDFZIQXWSBCNTIKVNKAIXOJWBDAWBHICWTWBIPCTBEEWQCQGZYRVAEEJSLNHPCOTNMBQBMZCMOUUIMJNGCICCSBPUPEUIEUBJMGXTJLAXXFZRFFYWLKBUSUPWYESFIOLVITJEWFFKLTQUJCPDOBPLKBGLRGESJKSYMDRODNIRJMLUWVGEBVFLKJAZMAVSVVVVTFJDARCGVTNNGLUKHQWSMQWVIEGQMYRSBDOCQSUVWWDYBARBOAPQNRNEPGDASZWTHFPEJKXKRMIRDSLASFPLPJYEJYREHMZCBZDNKRJFWHJAEFIELHRNILJBSHRFEEKZXVLVCJNXTDVEHPHHBLBPGFSOOQGWRBXSOIQCBJXRJRBJOLUSUYIMVLVCTHNZVFBRDLFXRSJOTBRZZSOWAFXNXTSEYMTNMQZQQMZKTKWSZZAMWMXBGGDSYREZNERXNBRDYBRHLPNDOWFHRPILOMPUZTZNDZMOUXNNXBHTCTPQUVHDMWUXHXETYDEAJPXKSWMDHQANCXRYDCVBPBQYOZLSLUPHFNKBTYQMQAZRWBJOFBOHCSJFHVMOSHMDJNQSWNAYAYZCEJJWACRBJMMPAFMRTSHIRKKQNMVBRQRNWQGQCTZSFXYQYRDCABSPZARQLKCILMAKGBSMTLDBIXTKWFNTLNCZCHGAQRQKGPZTVSKIBZJWKXYACGPXKEAYBMABWNURPOQBFLTSFLYWJGVPFHATKCBVEZQNLIJUQUARLFCGVRXIXZSHHQHDHGBHQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAOVWHQFXYNUISYONOEKXPDDKUFRMDKHIHTAHPJOWMISGBOQKNDNJQVZUCPYUUIQXJSZAVIXNQNGIVQLSJJREJPHUQQYFXAKJKACWRFQBWBPLQJUYXHKIWJLFGVDGDSBDIVQRCOYZIQXZVYNQYRHEIYTKEBZIPIWHJTCHAAWXOCNFSOIIOFCFIEIDODTDJGFMCYBPZRBXMNSXAIVBQYOWOLUXSDXZGVJTRZIWZXQIOEBAWVPSAWPZNARJQLVFEOLOORFIGFQVEKPLCGIWCZOGSVLNGFLUFXQAHYUAONSXAVPEMPTZWIOHYBZSNGYVBWHMCGADBALGZBKGTSOQGSOSGACPXNNGRXFAZPLMBNNAFOOPMGICEPPFMGBQYNVQHLXBGHODWPHTWRAILPGVMBDOJSHQGGJUWGRVOTAANYDYGPBMDTHWDSTVJUCFXDHSJEKRDQEGYSRTRHYZQPKPDGIGCAMCLSPTEWOSYMRSSLSKJEKIMDSVCGBBSLOMGFYHJTBQWXRJKSPXEBSEZAIZSLIYFFIJHZEXEBYAVQPDRIWVNJFPHGUXTDZBRQDIBEQRDIKSNHLVKMAUYZBKERVDNWWHSDKFCCBQIDZLCMFXPQNMFYTMGKQSMULFQACVBTWXBIDEQSYCVLOFWMRRQJKCFQTHHMMDWYKUVTFZMNVXWNJUZFAAWMSLFDOAYZKXPCTSUYFBSWNKJQTCWJKNRMLHUTFBRPHOWVEMIAKBWFVESZNWPHSHGXQBTSAEGBRXMFBTTUAXCIBPISWQKSLZCPOLQKPSLVHENGNLDMNGYCHIFBPEDOJHAPMSJSIZUEPYUVAYKWFLOVMSKKYZBTLWUGINIQTWIWGWATLDOCEYAPYBHSISMXLMQGNDBOPMKDJAJYXVHLVKWDWINMDBIJYQEHUERVRXKUVPFEQZELXUEPFCKGWNVUIJXDQWMKCWNHDZMRPJJQQIHBUVJCZPBPAKDSEHNNKGPSNLCCUHSVJCJYKOIEFJSVPNWEUFDUUBMIKMZRWRDEIRNAHSRTTQKZGEUTJSUKVTAZLOVIVHQSVSGGQJSSFXEEEMPYRWGTCVBNZQVEEVDYUGFKFXJFOYCJDGPSXDLLGWVNBQFNWGAZJRLKKZHQESOVYLVOPPNIXNSEODDMMVAVZXQZEOMTIITKPFXOGTXZOVVENARVHJJYSUNXIHTJOKYWOTSVFYVGBWEDNFNUCAMSPAVZFFAALISTKEZXRBCTBGXFTBXWANNNTLCTYQQYWTQECOCQNMKIYASENDBVTILDAJNZLSRYSOCKVHFLZJKVBDHXKBVOSZIIAUAUWUNVOYCXWYQGUFSTVBMHLQQZCIVZMUFIALQDINRRXQVFEHQZVRLCBHUKOYYBTMRFXLTELHTKAOPUNZNYAUNCZOUKFVCUTHYKEXEXFYRVPSBSMSREEMBIEYVXULPUMIJQOQIMSWAYZKJYGVZRQMHMHVMIWDEUFPGKQUIRTZXJCSUAPQNAXHQCRUEFVYLUQMGAZMYSBJVNGQMQFYMDSJQZAGHAWYSMOWHGVNYCNCEBRADIJYCCPBFOJDCGEUVNOQTULFQZKWHDSUVHNMTUUQHQUUWLGZYXTBAKDUQXILCJJSASSHQHXUVJVVRLKJUEOUWBZLHDPXGIFQZWUACEKVFHXTQWQJUVJXUKUFSQGIXSMRKGDVJDQYQIBFJXSHGYJIZYHNBWLPUDTGGVSYYOFAKQDJINWKBAYGBKDKRVTXMTVKEYMUFKYOSHAITIDRHTOKNOJQQGZFTLLVYUNEGXNYKXOPZIFAMVYGPILRQVILSKGXMSLTYAUAGGHMSRXEMXDUZCHEVUXDVCDVAYXKEFRYZQCQXUWXHJKTXVYIPGCSXZTSCEHRFOGVEGRCSKLCNSCXHCOVQVKPILKBVRMAYGSEPDMIMNVWPMNUBNKITDKQTXBUMPZWPVYAXGDDNRHYJJTKYETYCTHIZZUZNSPEEHFGSXRRTQIKMYFKUQATOBVEPZRSTBNQWYPYGKSZDGMELRFTYXOGAIESGKUDWQWJTVJELSVCQGGCWKIKDFNHYUQJOVTWIWPQTVASNQMAUVCCRSFBLMKZIZLIOGRDZZYJAMBCMLACWLTWSXDQYTVRVQIVQPLQVHINOSRXUHMMAABWLJBEFTMFQLWDLDCJDXCLLSEMNKXXMXCELVRCHYAIFKTGNOQVJXHPBQRNLMUOGMWYUTUQQCELTWULVIWJMBGHVWSNLFCFSJMXICSZRPFUQMFFDXZEDMEQVJMBPZQNSBYIZUWUQCWPCRAUYUYKAYOBJPNPFYYFKUPYLHYZLCHGNWVFYGGVFZOBBACMNMVPSPIRIEDBKYKAPCRLULAQIOBGRBUOBPYETUBDEJUFZNMRCCQUEHPMRKFKPRKMQZUXDZABPGRJQWPBMDZCTGZAXTLVRBDDLOOQXVYMNWTRVEKHSIOXRRJEJXNCXJFXAQXQOAWEPUSCAYESKFCVSUGYJUMNSVXNYWUDYCCYZWBDUZIUVKCCWHVAMKZEUTYOPRRQHIILOICJJFFNQXLGJFJTKFIAMXBAVPLOWBZVXWWVRMFYFBCBEZTGRVYNJKUHMMCZYITPQIEPSBRPCZENVNEGFRXAHSRSENKGJQDAXRRBUADKZPYEBZCOHSSWGZMDDWIVMWKMJCOEHRFJKDMSSUMQZZLLPHBEFPHRBFFGBRTRXNIRYJVFVASEAUJUJDHNNQNNQMTDHGFWNQNUTNBGUPPMOUROMMAXPUQRJSYRYSGSPYLBVGKWXNDCQZRURGBSZOXEUBFSCFZGOCZJUVJDJFXDMLRQORZDRCCDHHWHBVEKCZLVICXSMKAMSBYWHLNHJYKIPCAVPRKZWTRTRBACHKSTANYJSBUXNSPGCZHRWFYKOYQDJBINSZCQCPYCJJLRLBFKZDKXXROLHCQFYWMCSHOLNVTMKZZHOJOWPFWUIWQNNSQXKUMTLJJRHYCZXCVHHGIVUGTDWPNNBGNPSAHFBHPKJLSBXOSHIBQTKBIWVPJNZQAFWWKXSTPYDQSQGWSPWBNXLZPMMJBRKJCRCXUTUGCKCHHENNEUJYAKZBLZPWWGGNVRQLGAIDBLMIEPHMZDDKNSLIESCVDHXTMSECJNSWZBVGFSLXAPQCJIPWHSWDXKRNNBCLYMVXYASQVQMSWOJYFEVFXPQVBKYLKBQGFQBTZDNJJIKDDGYGUBJADPAZOYFAQYVMNXLUQCBWUOQEEGQUPOBLGNJJZNZOMEFDHWHABNCADZJHJLZLKBBOJCDPSFIQLWAHWAVBFIVEBLJGHYWGAXROBTWEWMTIWTZHRRAAJOAZVJFMOPZVRXDZKZWVKSEYLANBPMKIFELYCMNOBHAAUDZGRUPEHVDPURVRPSIBVCGDVANGLLWNTSDDDKXFEJIBMUKFUPQTQHXOIGJUTFWHLRAIZQCEUZDGRJQQLVDAPSVUCADRSWYAZUYEMPIUIUSHCMNRAKTVYBWNEDIJICJANHXDNKSDUPKUOTKISWGOENVLPUUSKHHIMHXFZRWLNETNEYRXCLGDHYMXCRGBXUIXMDCFSIXDWDYNDXBGZNDHBRYJPXVQWVSRYUFMLNWEITYZFERACAEFCTJSVBLZIGLAEDPPZKWKSDRXNEZMMIHRXUHIENABWZZTJMISHXCZNGBBJEVCQGFNODVDDYQGTPCCCNFTWTQKEYZBXJYCMVUCSCTKWHDVOBQLEPMITFLHCZCJGPAQVKDWBQAJWUCEUCNCATXJDSUGAHYOLKEZMBMDSWHOUXPLFQMCDXONRADVKLCJXJSBUXHTIAMWDRRVKLDEKWPMAGTBNTKQFJNUAGUPCJQJOJICUCGGVDAWWWEBWVCVPWFVPDMKTSEDRYFEKYJKDWILIOINEZINFLEFSVLCCYVNLVCOBVCGZMLMVQDPSWQGWVPYSCEXALUMOOJBESGFIEGNIPUZPICIEYSAUFYVPJZOMXNPSSCNBOMUSRZWQJWIYNSPOERFOVRZILUIGVEAVGDXEGVATXQXZNRLZOFLACOJPFRMVIFCVFXCZVTDBTFCCMIQAQIZQWHEYBYRHGNLLEMQZRZAXGFUWJNOOYSSFYCCKYOYBLMKACMWZOVZKWIIHXADORGTSZGNXDVEIOMYSSWTXLNHFYWBAADLKMRYMFOUNIDRPRRCPKARTNVDRJHUZBGCOFVHATMAWILXJDHGQQXQOWBIZBBECQOPBTHFNGRQBDYMYBGKQXPZVNBSYTQNUWARJKPAVYTCVEIDNFNGXWFSDWEZPLDNOAEALDXYJZZPRYKXQIGVNHLVROALCSUCLQLWKDBDIANPWPIYSEXQDLUZFKHMODVRAPDGDYZIDQUAQMRYLYWTHDEAGGVUGSTOVHSCVVIIVEVVNCDNGPFIWHMDLZKRTAEXEZAUPUWOFRHAGFYYKESPUSESYQGZUWMXOUNTNISBGXPLRDURUNTRHLRDLRDCUOPJNCGBECPGUQVERCWUDSTHAKJPLEXHAKKVSYBSAFHTCJSGBWGSRBRMCBCOHBJXQBPLKRLJOVSGJXCOYHUOPSZZDBWEZINFVGWEONHUGMUDKKJYVJHQOHIBDVJMRTXJDIUEBNZKXYJJCZOGDATCFNUBTUOKOIPDAEPPLGDLKNUPEXYCRQMLNTVMTDQIYTLYZGNVNORDDPGZJYALPTUTVCDLMSVVSARMDMYTPTFVZJNLBJNOYFTGIAQERRWQBTPNWFICROJNCQYDJHTOZQLYDHDNTZZXGUWOUKGSKSBFBTVFHGCQXNEGRICJXTWSYHMLIFXHPKWSIQKXKMDFZBVAUKUOJBVSFVQXATTVLRIDYKLRWASMOFSKLEKYKCSJYZOWXNFHRPXDYJINELNAVTRCXNGEAVPVBSHOODPSLADYLPYHPIIUJTEIVJEQCSCYTIHCMWLBZRQWMSJLPYPAGMBNIGKCQUQZIDPQGNPHGHYDXZEXRLIEBNKKPXANRKZEHWNXDQVREMFJFWYTRHDLGKJONRPSACNLFSAJUSQMWVKPGHBSQJZNPEURDEBZWAODMTEMLFGZFZTRLXXTGCKWZCZFGRSKQHQJVECNHUIJSCXNOVSBIGSLXTXBIKNRMIFHSYAUMETSOBRVVNMOVEHUDDIRUAIKVETTCDOVJXRYHFDAQIAKODLSSUKHRKVGOAPIJMALIEIICODZQNJSWHYHYZPWMQGOCSPSSEAARJWGNIGRDCDJRTYRIHVYSVSMQQADMBDMJLVKOEDPDVRKSEHPOXBKXELETFCQOGGYERRZSVCSLXFJBKJTTXOSMCBVWUAXDSDYLEIZWIAJFIXGMSRLOOOSTJNNSXCQUPNXWKJUJULDKYTVSKPYCKUHLHBKURUKWRYTYNAFAHPNXFZQYPNUEKCNMDXRIZTHFZWYBEBRNLWXHEIHUETXCVODZWNSDRJGYEPXZOCCAVKTNHOOOXVARRMJPEVLCQFFSNXYKCHQOSPEFDWHNJHYSLAZFQTTQJGGGGKOKMKRJANSIRZYDCJNAJQAOTNXUMUCTEHPANJAIQCNCSDWBJUBFUOAKDUDXDRTECSBLMPFATBMLKUMJHWUZXXZGBABOJPBAGYLJFEOEFWLUZEZHMPAOYDBDSZDZHEJBBUTRUJSNHTPKXDJOVJTUYNDYGNIFEAHGTGDFKDJJNWOUGOINVEVYSEQAOCAOVRJQVKPFYAQZSXCPUSVQKGZOQMWASQXHUOIMSYQYFWDRNQEXWBNVFFMDHVFDTLGIZTZRKSFXPZKPUXSYHUZJNFFLSSOMARTZXQWIRRSOOZCKWTQYWRJIMSAYTKZYDPLMHRLESJREGZHZEEHMFERPPRONWZOJRZQGLUGAQKJLZJOLUUQUFNHNLYFZACEUUQMJKZVBQAKNPJTDIXDWCYXBMLHQUXZORTUBLMWFDFOPOXCPWRMMGVLEEMHUBCPQXLGWGJPDLDYIWBMDNGTKPTBNSBDCPVJXFFZZYHMKSCQRPRXABMOZYCJZRQXYRSMMRXXPOGPVNIMHITFGUHAZRYJKRDJFOXRQZQMPQZUNDRBCGNLKDRCNINAJHHAEAFYERFVCQDQXLEMIKVVBTPGGAWZPEGXUMSBVPMOYJZYEZZICYUNYYZSMGQHLNOYACBELDAJFOCISTZAQTWAUKSMBWKIKOTVTDFLDSTRKKEOKFFBJZINVGPHRZJYXDJEIWKFSJLGXYYJEZHKYGPCCHDCSSBETHIKPFIOJXQCFKBDIZZGOEFTBSVRRVBJTPUYVCBCRCKKTWRIPQMIWMMYGARUAGXKSUHZLMFRMMSIIFLYEZHMOYPRGHEHKEVHIKQGQNBAHIOJJGRYFVKONMGGYXSTZUNEOINSDVWIKJBHFNVNOCISHRGRVPWUFTHLRDTSLGYHMEWMXTRNQHRPTAHHWKWSXUBIYTFFXZEFDYTNPHEQLODYJXUJXJFEOXTXUEBULAMCMBGYGDOIUBAHAHVOKKSEGIMYWBVDYWATSXFQTKQYZMEWFWEWCFVVZUSGTNWAQOUKWHKZNBWPAQGXIPBYBGJEMUAOJFNAKTJPLQATBELXZLSFAZROEDQUXBTYRBCVGPXFPMFDAVPUYHFKHSSOIECHBNTASPKZEODIPCLPRXSYUPLACJNFMREFPAKZNXVRGSBDMJZFSBJOMYJQXHPDJAUKOGPDHRNFHJCBJRPMOOLAXOLRHXAKFJSANZRGNXSYJHSHDOWSUZKANMRRHDAINXIHPDENKROYGWVDRJVBRSVJVJWAUJXGPJWVBPBIKTZPMMXREPKOLVCHABTVPINFFGVPDUODKHDOEJUTLZYPEXPZNNGKYNLJIAHGODHFKGNHAKTHBCHXWPCURHGBUQCWBRTISQKNVHPEMMMVSKOKXRDPMMLYDIGUXGFJXLZXNDCSUMHLHLHWCOOYZBPAIUKADKSIQNKTDGPNXYBQPGYWLDXDCEKWFCYCVQIJKPNZAEANTSEVHCPIBWCKAQMUZDMQRMZITMPHKUNDHXXUKFMBHIAUVUFIJGGPAYXJRPCOWLVMVSPZXWNDSSXOQKTCVJYAUEVBBMTHWYLSWDOJTEGABUGTOIQPUKMJMALBZXXIJLVNRVRCJZQLTKCVLULPSYFYJOIBYFANLCOXNLQYJOFQZDFRYIOEQMJGIRLFXTIVXPKQRZUQOSDTUGBTVQSXATNXMAYGNHSOWELEIATWUTKJUAPHFQUMXAYPJKNCXKDEVRTVNDVKHUQEIGIEMWBQANSYWFWZODJQTAQZKWYFSGFGEUESFSAWKELFZKHWBCFWMJSCIYKXSBXYMQEDTGDNAKKFYGZXOTLMHSHMCSHZJPSBZPWFLIJHFUEYOBJGGLXZPIIYPKBZMXFFOUANUWHGTIFKIZPEQPFUFETZYAHVXKSIFBSIHJXUJXYPKLIVXWNLNXDBIJXATRKCJPCEYICDDMVYIUIXGFXGTZZCYCFUUCMVQRKNUMCBVLKODKHXOWXPPGFNPMVBHDEGDFDFFRPKQJXDWUHUUJAIPZVYMADSLEAUSSPVFRVQZLABDREWXJMACDARFYLQGJPBOXNCDPNNJNVAJJMPQHOEYPZMRITBKCUXAKACMADODKWUGHGMZOXEKXKMZBZNQFFVMLKRNMQWLZRKWYIZVYHSACKIEUHSMIPVJZTZDYPAAMBVDGDMPHCBSXZIPDUQXRIRPRBFSZKSLTEXPYUBMKTJHUBEUVSMCPKOBUKXNDLIHXDCRJVBXQVUIDMMOTDXGJVBDRJTJRQXZBRTJDOQHEUJVLGBXPJXIUVLWGCEPCLDIMHIANMUJWJMUVTAIICIDUWMJZLAAQGELUOFRTMBPJUVEBRNLERKQEDAXVAUFSZFLZIZSAWPGQNBRDVUBAVSCKWPRFFMJNVMHRUKXLRXDXQAYBNNBJYBJWYJKZSUDXMENYZREUHQTGFPAFSSCHVPQGEMFEJTAAANSYLAJEMJXAICCUPSRDYAQPACORKDOZLFZTJVJZEEMUTDRDMAWSFQKFYNEAXLEFBFLVLRRURDPHRTYAPYMQSKFIQRQQIPHPYJNCTEPQFVXQMKARRMLFJUWVCXLGCLINCSCNUYMJMSSDPTXWNHJZYMARNWSMBESIXKFFOSAYVUNMJGUQTJLRFVMIJNCCDSGJEXYTKAXICMAIAXAPCYYDHCWBLMSBASJYZSATOOBFUIHAUBGZKDGHUNJJHNOKQSJWSLQJTDMQMPRKCOXZPQBKXSPCGDFOISXDPOHGNLZSIPZZVYOGXMKQHNWIAJNEXRZWEAANWFAJEWXYVWKICBTCWVLKMOWUPNHULNYXILIPHZQVNUYJEHLBGVFDMFNGHCQXATSAPBWZEQKKNSROWFWNYIGMDDRRBADJEZPJYGKONBWWFJVTGXWBNPRWZBKCRMSTTBIRUOILVDKALHNWBDYINQWFHOCFVFBIIUTSPOGRYRBNFFUTSOLFZPITVXCZFVRXDAXNWGQCKQSEVBHXVGTYZAVNZCEPTKIDZXHSFCZQLRUNXXZRAXQNRJOKRPRRUWBKKIQJELOGTNYIVISVVUHFJLSGBKFSOCAKZBHPXLHVSTESSQNISMGBRZFURQSPSHHMMVBAMQXNKMTIOAQDUTICTSZZVJIORVOXYCFAXJWXLLPCDMASYDIUGUJTEXRBHCPWVQVBVDEIWEBJTOTKMOHPOZJJWTOBOMRZKYACGTPMTRPCIHIZZOETYUAGVMMPYZHWTCQSXDDMYCOFUZMMLXYUPNNALAYKXEKBAKTBNZFHDKDPPUSAAHSEZKXUOVWLAUKGDQGSOJBBAYUFWTJHQUCKKQLRSAZQXDCLAJCGELGCJCKHPILUFUHNSZUBBZMXPPXVGKPZMLPREAJKYPLXMJIWDSDSLUUHUHWVWPLKNTOTAGYVFZPFRIETKHPNJFUHRTIWGINJTLTRVZJUOKGNFCEBACMJRLIFGLZERSJHFJKBJJVVXTANNRTWBWHJGPLYQIGIPJSDFVLEAURLKQGWJZATGJHJXLNVHAHUYBDLVLFDMJOLTBPVBLTVVGJLQPVMOCNUMTTADFFABWDGAVLBNBVUSVADDZRMVUMYXLNFLMHWXQUOIKXUNVGXXSJRFICDHGNNRPOADHIVQVSKNPJQGVDYLIBZFELOGFZNHSHPZKWOOBTLJOIWJKGMMDTHFJWCOPGUZTIJVPTECJXTIPMPSFYONVXXUYNBLODBWBKHEXRHUDJRENIPEEEGMWWHEQNQVLYRNFXKMYMDPMEHRKBBLRALSREVVDEIVBEOWIHRNGBFEALKHGCCLUPINRJJNJHRMLLPLFRCXVMLATRKZGKYSSZZTUUHYZJCYOGZMBGRCEEVCUCYNYZUGAXPCQIIUDPYGFAMFXATUYAXKZCTFCSXCOHVWEHHORWFWVURHHBZPZIQHXKLZFWFMSMBOAMEGBXMOHLWYRADETOJMMCDHXIQLWVVMUNEPGRVAUZKEVDONIAUZIXKVHWJMGICGXTYYHFXIWDYJEXTFTELDAQVPPCLXPFFRTKWZSLLGZHUFNWMSIJIEQEMJZUFYUNBJWTFEJMHUVQJESUMNLYKIMSTTUQKDFWTRBHVPCZWTTQQOHPSZXHPQWARAWPSMURVUOIRSCHKHQIFVKLQYLJFUVNZSKVLQSBBCXIGQPDQIHPADAHFFNYNLOUDHYXYKPXEMRYCDZOFQDARJJUXAFWLDVCCRWLECVCPAHEUQRTJLJMIJJMXHQLYTIVFMRTJDPNYNTJPPESLJWJFSVKANKFZXVRAATUYPHTATXIZFSKAQBQSFKMQINHUXDWAXOTKMQBWWIOKOTVGLZYFEOICWPBITPCWQBGTYYTMKWIRRILOQCGOPLSGVPSADTCGFYPENZUJRHJTKPBHGQJJDGQRZGXHAPFTIPZOWWIZJLMDGIMFFYGWNFZGBCMBHPXAVFCZFBZXIJKOPJRLSOKTDKBQSHXSGYPNUMVJFWZUJGFCYJFVPMUZUZPHMVWRGMBWBFTNFCMYGOANRPOOIPJPYHODMDDZTBJKQMNSLFBYPRYYEPAHAFFSRBAOYKNRDIVUNBKHHFFVQFAOTPPETBTCNJXGKQHBQYQBKBFXZDXBDMHJATIIYNEXADIDOJJHCHUFEQVKHSBEAREUBCQBSDXGPVQKKNKJWROBPDEECYIMBZGAIJSERINSYOHWHIEZUOYEDCPAUFNTYYSFOLDYHKNVOGHURZLVZEFCWFLPCZDTBEQYXXDNAJKMTNRGVJZRWVUMGXTVQKZAPKNOLUOAYEUSACDASMCRLFWIZAGTPEJMYLHDEZFCTAARZGYPEMLVOOIZDOTYTNEJEOIMWTIZXGCKOFTWKEMOJCNJDMFAQNYXHJBAVREKDSCMAXVYHOQNGRSRRKXYBMMAFGFLLPCKXUVDKSBJAQOXOGVGVYONMSUIRLOBIPXHXGKICITRONWQEGNCXFWFKMREYWZBXDCEXEXGTXGYFLOOCZKMLLQBVLQVCXOQAEVNLTGNXJGYUDEEPLQJFVTJIRGCYGEPODNJRRCHSMBRHDGJDHQYLHIEDAYBGAHOKKSBFUNZEOSLKPZNSDHLJPSJSBAIICYBADNLZGOCZVAKRKCTAVDQFKRSVIXYMKSGMQGKOCPVPXCQGMXCVOGEWCAIMZNGOIPPRMIAOMEWEIBJBJPTPOREQUNLMOIGOBTOWIEUAMDMEDFDWCAANRQUQGXMZUNJIZPLPUJTPOKECFGQNVSDHWUHJSQWMYFWFGVIFMIPIAYCUTVJVWHDCRAWSNRXPCTAJZQZIIZTAXCVPRWLQWNFBVBNGJBUXGGXLUVWGAVOFOQTCDICONHCWYGFXSDWEGSZCNVJLLXYSQVJWYUGZWRQXACFMLALSNNJGZFIBCAIORHUKYBJPCOQPKCPTOUKMOLMJCGQUJRVLTSUWJSUIILGLSGWLLQGKFJJEVVUZWLDGVLVXSZXMSKTRIJLOTONFARWKIDCQCPXXZLUOYPWOHNUSJMUTAXMFZTELHQBSXKHKPUIXTEMCMKJACOZLPLATYZXIZNMURXMVWNSPQFUCDVDRYEZMIEBZYOABCTTKLGBDSCVWWAQMUJYTXZFFFMHHKEOEORNSDGYIQPLSIEFOMXRQBGEYTCVIQARRCQUSTARLGZEVIQVQDRVMMCIWQEEBCIWKNNXCGBPAEELMPCDQFMKFKAXVAGSKDPRXSZTXXQQQTGPLFLAUBOFMUGDIOZCEVABXEKOHUOYRNBXDOHIIUDDHQHDIHVVBOITYCNFFNULBWGLNZDKHNVAXMGDGDLSQRATNBKTBIOCXBPFTQRDLQGNNWUZFOYRRYJAPMQCQBXUWUBDVLICZJXVPHOHDYQENOMJGIPAYTBDYPMNNLBXGCAOXUNMFFPEVPFKUPGERNNDOZLFVKFCIBCPBUIMHOMCVVDKBVQIOVZQKBPMXABGNJGEPIVFIEDXYFXIDODKJZCXKNHVFQHUSFMJWXFBGRPDIPSMBVEOLMZGWNQLQUQIXKSKOOXTSPFJEDBMAXHDPKEFAMASMLUJBNUKLEYIXPJEKYFTEKNFJRQDYGCHVTKCSEQTRUHPBZPWTEBGWEKXISBPUHEAFAEPLLVVUIFCLZRTUPMIAJVUVLTHOTFPMZZHEMOFWCBPBUVUIWAZOIHJBFZRDXJSACARXYBGNXKHMSKUAMKEALQWTWLMLZTQHGPNYUFKBLFBOZEWEVSSDOBPFAPYNNEXVPZOKKUGSQYFIAEQJTYNLYOBQUDLQKZFVXQAJCCBVJWMPUUARURYPUQDCQOTOPBTTLLOEDPRWEKPPLKUEMCPBGDGJQOBXCSEVPYXUVNDZKVIUZLGJXDHOYQYDDIKSDZSLTWRDKTQMDSOHUWKFJPTEQUAULYGUBLSJRAJNEHSPLGUOORIZOMBTMYJUWBNJYBHNCPDKSKVENEMEAAACQPFLCPZVNOZSASBVDMAKTXATLKVXJCMONWIOSQEVQGXFMHRMGOXBFSUVOJMSXDJBKSWJGWDFWSBQSNLCZYWNWZEIMWXBEMGSIMNAQHVFXLDNQNSWNEARIQXRHGYGNYINFFTEKMTCBOUWZAHYKFYFMNDURMGBHNCPDHUWKFJPUARURYPXYBGNXKHLQUQIXKSQHUSFMJWXGDGDLSQRAATYZXIZNMURKTRIJLOTONFOGEWCAIMZNGOIRLOBIPXHXGKICIPAUFNTYYSFOLDYHFSKAQBQSFKMQINHUXCCRWLECVCPAHEUQRTJLJKBJJVVXTANNRTWBWHJGPLYQQSEVBHXVGTYZAVNZCEPTKIDZXHWFHOCFVFBIIUTSPOGRYRBNFFUTQJTDMQMPRKCOXZPQBKXSPCGDFOIPRFFMJNVMHRUKXLRXDXQAYBNNBJYLGBXPJXIUVLWGCEPCLDIMHIANMUJWOQHEUJVLGBXPJXIUVLWGCEPCLDIMHIASZKSLTEXPYUBMKTJHUBEUVSMCPKOBUKXNDLIHXDFSZKSLTEXPYUBMKTJHUBEUVSMCPKOBUKXNDLIHXDCAYPJKNCXKDEVRTVNDVKHUQEIGIEMWBQANSYWFWZODIJLVNRVRCJZQLTKCVLULPSYFYJOIBYFANLCOXNLQYJOHBNTASPKZEODIPCLPRXSYUPLACJNFMREFPAKZNXVRGSBDMSDVWIKJBHFNVNOCISHRGRVPWUFTHLRDTSLGYHMEWMXTRNQHRNSDVWIKJBHFNVNOCISHRGRVPWUFTHLRDTSLGYHMEWMXTRNQHRNVGPHRZJYXDJEIWKFSJLGXYYJEZHKYGPCCHDCSSBETHIKPFIOPQXLGWGJPDLDYIWBMDNGTKPTBNSBDCPVJXFFZZYHMKSCQRPRXABMMPFATBMLKUMJHWUZXXZGBABOJPBAGYLJFEOEFWLUZEZHMPAOYDBDSJWGNIGRDCDJRTYRIHVYSVSMQQADMBDMJLVKOEDPDVRKSEHPOXBKXEIYTLYZGNVNORDDPGZJYALPTUTVCDLMSVVSARMDMYTPTFVZJNLBJNOYFTCJSGBWGSRBRMCBCOHBJXQBPLKRLJOVSGJXCOYHUOPSZZDBWEZINFVGWNUWARJKPAVYTCVEIDNFNGXWFSDWEZPLDNOAEALDXYJZZPRYKXQIGVNHLGRQBDYMYBGKQXPZVNBSYTQNUWARJKPAVYTCVEIDNFNGXWFSDWEZPLDNOAERXNEZMMIHRXUHIENABWZZTJMISHXCZNGBBJEVCQGFNODVDDYQGTPCCCNFTDRXNEZMMIHRXUHIENABWZZTJMISHXCZNGBBJEVCQGFNODVDDYQGTPCCCNFTUKFUPQTQHXOIGJUTFWHLRAIZQCEUZDGRJQQLVDAPSVUCADRSWYAZUYEMPIUIIWJMBGHVWSNLFCFSJMXICSZRPFUQMFFDXZEDMEQVJMBPZQNSBYIZUWUQCWPCRAUYVIWJMBGHVWSNLFCFSJMXICSZRPFUQMFFDXZEDMEQVJMBPZQNSBYIZUWUQCWPCRAURCHYAIFKTGNOQVJXHPBQRNLMUOGMWYUTUQQCELTWULVIWJMBGHVWSNLFCFSJMXICSZRPFUQMFFBWLPUDTGGVSYYOFAKQDJINWKBAYGBKDKRVTXMTVKEYMUFKYOSHAITIDRHTOKNOJQQGZFTLLVYUNPHOWVEMIAKBWFVESZNWPHSHGXQBTSAEGBRXMFBTTUAXCIBPISWQKSLZCPOLQKPSLVHENGNLDMNGYZKXPCTSUYFBSWNKJQTCWJKNRMLHUTFBRPHOWVEMIAKBWFVESZNWPHSHGXQBTSAEGBRXMFBTTUAXCIBPSNGYVBWHMCGADBALGZBKGTSOQGSOSGACPXNNGRXFAZPLMBNNAFOOPMGICEPPFMGBQYNVQHLXBGHODWPHTWAWXOCNFSOIIOFCFIEIDODTDJGFMCYBPZRBXMNSXAIVBQYOWOLUXSDXZGVJTRZIWZXQIOEBAWVPSAWPZNARJQLQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAOVWHQFXYNUISYONOEKXPDDKUFRMDKHIHTAHPJOWMIHQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAOVWHQFXYNUISYONOEKXPDDKUFRMDKHIHTAHPJOWMIBHQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAOVWHQFXYNUISYONOEKXPDDKUFRMDKHIHTAHPJOWMISGBHQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAOVWHQFXYNUISYONOEKXPDDKUFRMDKHIHTAHPJOWMISHGBHQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAOVWHQFXYNUISYONOEKXPDDKUFRMDKHIHTAHPJOWMISGDHGBHQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAOVWHQFXYNUISYONOEKXPDDKUFRMDKHIHTAHPJOWMISGBGVPFHATKCBVEZQNLIJUQUARLFCGVRXIXZSHHQHDHGBHQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAOVWHQFXBFLTSFLYWJGVPFHATKCBVEZQNLIJUQUARLFCGVRXIXZSHHQHDHGBHQYQPLTNOKEZYGASUNTPKYXOTUNZMAGBUDKXIIAVLKJJLAVTNNGLUKHQWSMQWVIEGQMYRSBDOCQSUVWWDYBARBOAPQNRNEPGDASZWTHFPEJKXKRMIRDSLASFPLPJYEJYREHMZCBZDNKRJFWHJAEFAXXFZRFFYWLKBUSUPWYESFIOLVITJEWFFKLTQUJCPDOBPLKBGLRGESJKSYMDRODNIRJMLUWVGEBVFLKJAZMAVSVVVVTFJDARCGVTNNGUBJMGXTJLAXXFZRFFYWLKBUSUPWYESFIOLVITJEWFFKLTQUJCPDOBPLKBGLRGESJKSYMDRODNIRJMLUWVGEBVFLKJAZMAVSVVVVTFJDARCGVNPQVIKSKFASRJPAUFNWZTDIDBXTUSEJHYYRLPFVYLUEOWAWVTJYHXPPDEDUCUIEUROMPFXCAHYLAKPIXHJBINAMIYAFYZNJBWMTVEHDZCTQZBHGXSJNPQVIKSKFASRJPAUFNWZTDIDBXTUSEJHYYRLPFVYLUEOWAWVTJYHXPPDEDUCUIEUROMPFXCAHYLAKPIXHJBINAMIYAFYZNJBWMTVEHDZCUBHGXSJNPQVIKSKFASRJPAUFNWZTDIDBXTUSEJHYYRLPFVYLUEOWAWVTJYHXPPDEDUCUIEUROMPFXCAHYLAKPIXHJBINAMIYAFYZNJBWMTVEHDZCTMHUKJXTFLDSABAYZNGRLGAFGFUBHGXSJNPQVIKSKFASRJPAUFNWZTDIDBXTUSEJHYYRLPFVYLUEOWAWVTJYHXPPDEDUCUIEUROMPFXCAHYLAKPIXHJBICTZORWDALOJJNJZYJWUEPHZOVEGRAFHBCRETBBBAKQUTIJNDCIBGNTZOXPGLVBNWSWWMLGOVKOQUXFAXZAQMPPKDSLQBUATEXZRAOSDGOPNVFSPLSNKIWUOZAARAZQXSQSWQEMKBDZPJLRRQPBRKJUJEICHUZOQUOGYWGUATEKLZAZIAQVWNHYHMXVZDYACNLBIHHETCMNNTCTPRIFYKHNFHGVPFWRYFLKHFGPEDNZZNDYTHHHAZQUQPKQQEJZDJOAPXOSMCBQMLGPUSNTWZOLTGHCBHVFMHHWMOIEWINCVJUCWMGOAPWLNFNOCDJRHJIWCMXOWKPLCATJMBKONEUJXGRSKQWTQWDUMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLITMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHEYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHEFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHERFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHECPGKZPRFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHECPGKZFPRFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHECPGKVFPRFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHECPGKVODWEVFPRFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHEQVODWEVFPRFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHECPGQVODWEVFPRFYQIRTMOYRDCMLVOGPGMYJERFQBGYNZTLAYSFNQSOQKSDHDUAYBIOGVLRNCYUFQOBUXGIZNKJQSMTUHMUOCOOASMHJXDSCYCBXUZGRTPKJJCSCCKEYKDOYORJMDOSNWTJVWUJKSYBQWLIMNVUIYDHHECPGCVVHYZCXFVDALNLZOARGOCWBFVUQKKSLEMJRKQIHULBCYTZQNRVSLSTQHZAZTZZRTBVXTTHBZJAXCGRVSCRJSEEOJQXFAEAJECDWVEHTBYEIQNMLILIEAAHWBXHQXEDOJKYNBBMTWQDMLFKRQRPACBSRLULLNLMKETFZJEBWTXZDHVDXJMMNIYAQYXEPJVDKPKQBSMWLATYCUWYSYOJZHUDSXTCSHTRACDQOQSNCYLMXJBYBBWKSNHYAYVRLCWFGAZSEVBIUJETIVGHEBDPXLVFWWTCKOUCOAOPMUIRPYZCULRWRCTZLCGMGREFOGJMULHHHQQIAOXVOKLCVAXDEGHSEUYZHPTFECVAJSFUSFMCGQLMASXUPQYQSNYRSDZVWZUXCDNVVPGAUQRGCQFSQSDEBWTXZDHVDXJMMNIYAQYXEPJVDKPKQBSMWLATYCUWYSYOJZHUDSXTCSHTRACDQOQSNCYLMXJBYBBWKSNHYAYVRLCWFGCQJCQLPHFANJTGZXOJRGGMYHXKQVCLBAAKUPWGUWGXEAHQBGJRKABJEUQUKOUABOVZDUKHRRXSBCRCHDFDUXCRZCYCHAZCEGPJFUATVHUHTAFLKSHRYVNYBVXUFUFYXIVGRBRUWPZZRGGNAURWMPKFLCJUGYBJHHTJHCNZQVDVLMJCQJCQLPHFANJTGZXOJRGGMYHXKQVCLBAAKUPWGUWGXEAHQBGJRKABJEUQUKOUABOVZDUKHRRXSBCRCHDFDUXCRZCYCHAZCEGPJFUATVHUHTAFLKSHRYVNYBVXUFUFYXIVGRBRUWPZZRGGNAURWMPKFLCJUGYBJHHTJHCNZQVDVLMENSPFDIYBMWOBOSWHFITNIUEVEGGXDZYRAIRWTHSECVCCZETCBXGFWSJPHFLCTUNESIKYZKJCTZFOMBMWYHTTXRZKSTVNHJCQJCQLPHFANJTGZXOJRGGMYHXKQVCLBAAKUPWGUWGXEAHQBGJRKABJEUQUKOUABOVZDUKHRRXSBCRCHDFDUXCRZCLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBRCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTTHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTAAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQZAAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTTTZAAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTUTZAAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTOUTZAAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTTKOUTZAAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTTKLHVKOUTZAAXHUGBMWURCDKHFEEBLRVDUFOARAOFKXFESYNYRKSMLBUQYTCJSLHIHGMPTXAPLTINHRQXRLOSXQDEFLZEVHHSAGQBRNBPJEQVCKVOTUBGGOIRCWEEYQGCIPXJDFRZUPUTVXGMPSCOVBPUFYVPTEYXTRUHXARDSYTZTGDIHALCQZAIWRPDAYGNZDKMTIFEJHQTEMIYVARZJRWUDDXKMGUUQBWHZNWCJFCQTTKLHFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRQWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRQXWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRNXWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRKNXWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRQUKNXWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRQIAUKNXWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRQIADAUKNXWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRQIIDAUKNXWFYRPHKDPWHACQGQFLCDTXXZKYDGDDPOBSWEMPAAVFCEXQJDCBOZIRSOWELVYEKWNGRMNGMOPFVVLVIOYDJJMWJGMZCMNGRPMLMNJLPZKFRVYSTRPQOPBKREYFDCIQJLQANHNOIUMHAJAEHAVGSMDSJRNGVPTRTFHWNXPZDOOLHYYMGALWNVZYKHPGFEZNGDGFUIEUNYQKEAICMFOYYLDRJQXCKQUILBITRHCUSQMCNSDDCLMYRQIAOM diff --git a/test/CVE-2018-25032/test.txt b/test/CVE-2018-25032/fixed.txt similarity index 100% rename from test/CVE-2018-25032/test.txt rename to test/CVE-2018-25032/fixed.txt From d6c1c88992ad23e98c79dc367049081a07636e6c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 31 Mar 2022 10:04:49 -0700 Subject: [PATCH 359/798] Test CVE-2018-25032 against the default level and levels 1 and 2. --- CMakeLists.txt | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a08a8f5f47..13850528d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1353,23 +1353,26 @@ if(ZLIB_ENABLE_TESTS) -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake) endforeach() - add_test(NAME CVE-2018-25032-fixed - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIDEFLATE_COMMAND}" - "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-F" - "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15" - -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/fixed.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) - - add_test(NAME CVE-2018-25032-default - COMMAND ${CMAKE_COMMAND} - "-DTARGET=${MINIDEFLATE_COMMAND}" - "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;" - "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15" - -DGZIP_VERIFY=OFF - -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/default.txt - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) + set(TEST_LEVELS 6 1 2) + foreach(TEST_LEVEL ${TEST_LEVELS}) + add_test(NAME CVE-2018-25032-fixed-level-${TEST_LEVEL} + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIDEFLATE_COMMAND}" + "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-F;-${TEST_LEVEL}" + "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15;-${TEST_LEVEL}" + -DGZIP_VERIFY=OFF + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/fixed.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) + + add_test(NAME CVE-2018-25032-default-level-${TEST_LEVEL} + COMMAND ${CMAKE_COMMAND} + "-DTARGET=${MINIDEFLATE_COMMAND}" + "-DCOMPRESS_ARGS=-c;-k;-m;1;-w;-15;-s;4;-${TEST_LEVEL}" + "-DDECOMPRESS_ARGS=-c;-k;-d;-m;1;-w;-15;-${TEST_LEVEL}" + -DGZIP_VERIFY=OFF + -DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/CVE-2018-25032/default.txt + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/test-compress.cmake) + endforeach() # Run tests targeting tools include(cmake/test-tools.cmake) From 42843861036c048a3c6f1475972a51c5a662b950 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 31 Mar 2022 09:50:52 -0700 Subject: [PATCH 360/798] Remove support for building fuzzers from configure. --- Makefile.in | 57 ++---------------------------------------------- README.md | 2 +- configure | 5 ----- test/Makefile.in | 21 +----------------- 4 files changed, 4 insertions(+), 81 deletions(-) diff --git a/Makefile.in b/Makefile.in index 2b8269099b..96bb93828f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -154,7 +154,7 @@ PIC_OBJS = $(PIC_OBJC) all: static shared -static: example$(EXE) minigzip$(EXE) fuzzers makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) +static: example$(EXE) minigzip$(EXE) makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) shared: examplesh$(EXE) minigzipsh$(EXE) @@ -177,59 +177,6 @@ $(ARCHDIR)/%.lo: $(SRCDIR)/$(ARCHDIR)/%.c test: all $(MAKE) -C test -# This variable is set by configure. -WITH_FUZZERS= - -# By default, use our own standalone_fuzz_target_runner. -# This runner does no fuzzing, but simply executes the inputs -# provided via parameters. -# Run e.g. "make all LIB_FUZZING_ENGINE=/path/to/libFuzzer.a" -# to link the fuzzer(s) against a real fuzzing engine. -ifeq (,$(LIB_FUZZING_ENGINE)) - LIB_FUZZING_ENGINE = standalone_fuzz_target_runner.o -else - # OSS-Fuzz will define its own value for LIB_FUZZING_ENGINE. - WITH_FUZZERS=1 -endif - -ifeq (1,$(WITH_FUZZERS)) -fuzzers: fuzzer_checksum$(EXE) fuzzer_compress$(EXE) fuzzer_example_small$(EXE) fuzzer_example_large$(EXE) fuzzer_example_flush$(EXE) fuzzer_example_dict$(EXE) fuzzer_minigzip$(EXE) -else -fuzzers: -endif - -# The standalone fuzz target runner. -standalone_fuzz_target_runner.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -fuzzer_checksum.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -fuzzer_compress.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -fuzzer_example_small.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -fuzzer_example_large.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -fuzzer_example_flush.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -fuzzer_example_dict.o: - $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< -fuzzer_minigzip.o: - $(CC) $(CFLAGS) -DWITH_GZFILEOP $(INCLUDES) -c -o $@ $< -fuzzer_checksum$(EXE): fuzzer_checksum.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_checksum.o $(STATICLIB) -lpthread -fuzzer_compress$(EXE): fuzzer_compress.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_compress.o $(STATICLIB) -lpthread -fuzzer_example_small$(EXE): fuzzer_example_small.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_example_small.o $(STATICLIB) -lpthread -fuzzer_example_large$(EXE): fuzzer_example_large.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_example_large.o $(STATICLIB) -lpthread -fuzzer_example_flush$(EXE): fuzzer_example_flush.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_example_flush.o $(STATICLIB) -lpthread -fuzzer_example_dict$(EXE): fuzzer_example_dict.o standalone_fuzz_target_runner.o $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_example_dict.o $(STATICLIB) -lpthread -fuzzer_minigzip$(EXE): fuzzer_minigzip.o standalone_fuzz_target_runner.o $(OBJG) $(STATICLIB) - $(CC) $(LDFLAGS) -o $@ $(LIB_FUZZING_ENGINE) fuzzer_minigzip.o $(OBJG) $(STATICLIB) -lpthread - infcover.o: $(SRCDIR)/test/infcover.c zlib$(SUFFIX).h zconf$(SUFFIX).h zlib_name_mangling$(SUFFIX).h $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $(SRCDIR)/test/infcover.c @@ -410,7 +357,7 @@ clean: @if [ -f $(ARCHDIR)/Makefile ]; then $(MAKE) -C $(ARCHDIR) clean; fi @if [ -f test/Makefile ]; then $(MAKE) -C test clean; fi rm -f *.o *.lo *~ \ - example$(EXE) minigzip$(EXE) minigzipsh$(EXE) fuzzer_*$(EXE) \ + example$(EXE) minigzip$(EXE) minigzipsh$(EXE) \ infcover makefixed$(EXE) maketrees$(EXE) makecrct$(EXE) \ $(STATICLIB) $(IMPORTLIB) $(SHAREDLIB) $(SHAREDLIBV) $(SHAREDLIBM) \ foo.gz so_locations \ diff --git a/README.md b/README.md index b0842bc442..f178ed5404 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ Build Options | WITH_NEW_STRATEGIES | --without-new-strategies | Use new strategies | ON | | WITH_NATIVE_INSTRUCTIONS | --native | Compiles with full instruction set supported on this host (gcc/clang -march=native) | OFF | | WITH_SANITIZER | --with-sanitizer | Build with sanitizer (memory, address, undefined) | OFF | -| WITH_FUZZERS | --with-fuzzers | Build test/fuzz | OFF | +| WITH_FUZZERS | | Build test/fuzz | OFF | | WITH_BENCHMARKS | | Build test/benchmarks | OFF | | WITH_MAINTAINER_WARNINGS | | Build with project maintainer warnings | OFF | | WITH_CODE_COVERAGE | | Enable code coverage reporting | OFF | diff --git a/configure b/configure index b8216abf97..bf64ae35d1 100755 --- a/configure +++ b/configure @@ -100,7 +100,6 @@ builddfltccdeflate=0 builddfltccinflate=0 buildcrc32vx=1 with_sanitizer="" -with_fuzzers=0 floatabi= native=0 forcesse2=0 @@ -178,7 +177,6 @@ case "$1" in echo ' [--force-sse2] Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log echo ' [--force-tzcnt] Assume TZCNT instructions are always available (disabled by default)' | tee -a configure.log echo ' [--with-sanitizer] Build with sanitizer (memory, address, undefined)' | tee -a configure.log - echo ' [--with-fuzzers] Build test/fuzz (disabled by default)' | tee -a configure.log echo ' [--native] Compiles with full instruction set supported on this host' | tee -a configure.log exit 0 ;; -p*=* | --prefix=*) prefix=$(echo $1 | sed 's/.*=//'); shift ;; @@ -221,7 +219,6 @@ case "$1" in -w* | --warn) warn=1; shift ;; -d* | --debug) debug=1; shift ;; --with-sanitizer=*) with_sanitizer=$(echo $1 | sed 's/.*=//'); shift ;; - --with-fuzzers) with_fuzzers=1; shift ;; *) echo "unknown option: $1" | tee -a configure.log @@ -2043,7 +2040,6 @@ if [ "$SRCDIR" != "$BUILDDIR" ]; then INCLUDES="-I$BUILDDIR ${INCLUDES}"; fi sed < $SRCDIR/Makefile.in " /^CC *=/s#=.*#=$CC# /^CFLAGS *=/s#=.*#=$CFLAGS# -/^WITH_FUZZERS *=/s#=.*#=$with_fuzzers# /^SFLAGS *=/s#=.*#=$SFLAGS# /^LDFLAGS *=/s#=.*#=$LDFLAGS# /^LDSHARED *=/s#=.*#=$LDSHARED# @@ -2211,7 +2207,6 @@ sed < $SRCDIR/test/Makefile.in " /^SRCDIR *=/s#=.*#=$SRCDIR/test# /^SRCTOP *=/s#=.*#=$SRCDIR# /^QEMU_RUN *=/s#=.*#=$QEMU_RUN# -/^WITH_FUZZERS *=/s#=.*#=$with_fuzzers# /^LIBNAME *=/s#=.*#=$LIBNAME# " > test/Makefile diff --git a/test/Makefile.in b/test/Makefile.in index 00050798b4..4078d60d45 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -9,12 +9,11 @@ SRCDIR= SRCTOP= LIBNAME= TEST_LDFLAGS=-L.. ../$(LIBNAME).a -WITH_FUZZERS= QEMU_RUN= QEMU_VER:=$(shell command -v $(QEMU_RUN) --version 2> /dev/null) -all: oldtests cvetests fuzzer ghtests +all: oldtests cvetests ghtests oldtests: #set by ../configure check_cross_dep: @@ -26,24 +25,6 @@ endif ALL_SRC_FILES := $(wildcard ../*) -# Only check the fuzzer when it is a stand-alone executable. -ifneq (,$(LIB_FUZZING_ENGINE)) -fuzzer: -else - ifeq (0,$(WITH_FUZZERS)) -fuzzer: - else -fuzzer: - @${QEMU_RUN} ../fuzzer_checksumr$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../fuzzer_compress$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../fuzzer_example_small$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../fuzzer_example_large$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../fuzzer_example_flush$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../fuzzer_example_dict$(EXE) $(ALL_SRC_FILES) && \ - ${QEMU_RUN} ../fuzzer_minigzip$(EXE) $(ALL_SRC_FILES) - endif -endif - teststatic: check_cross_dep @TMPST=tmpst_$$$$; \ HELLOST=tmphellost_$$$$; \ From f98729de07e19c966ad3ba11d25a7f4ec75fdcc8 Mon Sep 17 00:00:00 2001 From: Shlomi Fish Date: Sat, 2 Apr 2022 13:16:47 +0300 Subject: [PATCH 361/798] Grammar fixes --- PORTING.md | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/PORTING.md b/PORTING.md index 1f2c7d62d5..3875ccc965 100644 --- a/PORTING.md +++ b/PORTING.md @@ -33,8 +33,8 @@ certain value will need to be updated. - If your application is pre-allocating a memory buffer and you are providing deflate/inflate init with your own allocator that allocates from that buffer (looking at you nginx), you should be aware that zlib-ng needs to allocate - more memory than stock zlib needs. The same problem exists with Intels and - Cloudflares zlib forks. Doing this is not recommended since it makes it + more memory than stock zlib needs. The same problem exists with Intel’s and + Cloudflare’s zlib forks. Doing this is not recommended since it makes it very hard to maintain compatibility over time. **Build Considerations:** diff --git a/README.md b/README.md index f178ed5404..5df00579f3 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Features * Zlib compatible API with support for dual-linking * Modernized native API based on zlib API for ease of porting * Modern C11 syntax and a clean code layout -* Deflate medium and quick algorithms based on Intels zlib fork +* Deflate medium and quick algorithms based on Intel’s zlib fork * Support for CPU intrinsics when available * Adler32 implementation using SSSE3, AVX2, AVX512, AVX512-VNNI, Neon, VMX & VSX * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, ACLE, & IBM Z From 8117b0e7147922e5530fa70977ece0fb913054c2 Mon Sep 17 00:00:00 2001 From: Dan Kegel Date: Fri, 1 Apr 2022 19:38:36 +0000 Subject: [PATCH 362/798] abicheck.sh: implement --refresh-if option as documented. Also change exit status to nonzero if there is no abifile and --refresh or --refresh-if were not specified. --- .github/workflows/pkgcheck.yml | 4 ++-- test/abicheck.md | 2 +- test/abicheck.sh | 10 ++++------ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pkgcheck.yml b/.github/workflows/pkgcheck.yml index 41daf5f309..1c4b1dcbba 100644 --- a/.github/workflows/pkgcheck.yml +++ b/.github/workflows/pkgcheck.yml @@ -128,7 +128,7 @@ jobs: # macOS runner does not contain abigail if: runner.os != 'macOS' run: | - sh test/abicheck.sh --refresh_if + sh test/abicheck.sh --refresh-if env: CC: ${{ matrix.compiler }} CXX: ${{ matrix.cxx-compiler }} @@ -143,7 +143,7 @@ jobs: # macOS runner does not contain abigail if: runner.os != 'macOS' run: | - sh test/abicheck.sh --zlib-compat --refresh_if + sh test/abicheck.sh --zlib-compat --refresh-if env: CC: ${{ matrix.compiler }} CXX: ${{ matrix.cxx-compiler }} diff --git a/test/abicheck.md b/test/abicheck.md index 3e291264ad..57337f5882 100644 --- a/test/abicheck.md +++ b/test/abicheck.md @@ -29,7 +29,7 @@ means someone has to check out and build the previous source tree and extract its .abi using abidw. This can be slow. -If you don't mind the slowness, run abicheck.sh --refresh_if, +If you don't mind the slowness, run abicheck.sh --refresh-if, and it will download and build the reference version and extract the .abi on the spot if needed. (FIXME: should this be the default?) diff --git a/test/abicheck.sh b/test/abicheck.sh index 89199a59ab..5c142556b3 100755 --- a/test/abicheck.sh +++ b/test/abicheck.sh @@ -49,7 +49,7 @@ do --refresh) refresh=true ;; - --refresh_if) + --refresh-if) refresh_if=true ;; --help) @@ -134,12 +134,10 @@ then # caching abi files in git (but that would slow builds down). fi -if test -f "$ABIFILE" +if ! test -f "$ABIFILE" then - ABIFILE="$ABIFILE" -else - echo "abicheck: SKIP: $ABIFILE not found; rerun with --refresh or --refresh_if" - exit 0 + echo "abicheck: SKIP: $ABIFILE not found; rerun with --refresh or --refresh-if" + exit 1 fi # Build unstripped, uninstalled, very debug shared library From 11f54459f30d71ebd4b36798ec1ea83f26ff72c3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 2 Apr 2022 15:13:16 -0700 Subject: [PATCH 363/798] Use latest stable version of google test instead of unstable main branch. --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 35655a3d0d..64b51c302a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -34,7 +34,7 @@ if(NOT DEFINED GTEST_TAG) if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 5.3) set(GTEST_TAG release-1.10.0) else() - set(GTEST_TAG main) + set(GTEST_TAG release-1.11.0) endif() endif() From 12eb5aba08c5fa0ddf96ea94fff370f9531b5219 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 2 Apr 2022 15:31:22 -0700 Subject: [PATCH 364/798] Move fuzzer cmake into fuzz directory. --- CMakeLists.txt | 28 +------------------------ test/fuzz/CMakeLists.txt | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 27 deletions(-) create mode 100644 test/fuzz/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 13850528d6..6c8d867946 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1252,33 +1252,7 @@ if(ZLIB_ENABLE_TESTS) -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) if(WITH_FUZZERS) - if(CMAKE_C_COMPILER_ID MATCHES "Clang") - enable_language(CXX) - - if(DEFINED ENV{LIB_FUZZING_ENGINE}) - set(FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE}) - set(FUZZING_ENGINE_FOUND ON) - else() - find_library(FUZZING_ENGINE "FuzzingEngine") - endif() - endif() - - set(FUZZERS checksum compress example_small example_large example_flush example_dict minigzip) - file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*") - foreach(FUZZER ${FUZZERS}) - set(FUZZER_SRCS test/fuzz/fuzzer_${FUZZER}.c) - if(NOT FUZZING_ENGINE_FOUND) - list(APPEND FUZZER_SRCS test/fuzz/standalone_fuzz_target_runner.c) - endif() - add_executable(fuzzer_${FUZZER} ${FUZZER_SRCS}) - configure_test_executable(fuzzer_${FUZZER}) - target_link_libraries(fuzzer_${FUZZER} zlib) - if(FUZZING_ENGINE_FOUND) - target_link_libraries(fuzzer_${FUZZER} ${FUZZING_ENGINE}) - endif() - set(FUZZER_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ ${ALL_SRC_FILES}) - add_test(NAME fuzzer_${FUZZER} COMMAND ${FUZZER_COMMAND}) - endforeach() + add_subdirectory(test/fuzz) endif() macro(test_minigzip name path) diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt new file mode 100644 index 0000000000..c21f9c1ca4 --- /dev/null +++ b/test/fuzz/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 3.5.1) + +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + enable_language(CXX) + + if(DEFINED ENV{LIB_FUZZING_ENGINE}) + set(FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE}) + set(FUZZING_ENGINE_FOUND ON) + else() + find_library(FUZZING_ENGINE "FuzzingEngine") + endif() +endif() + +set(FUZZERS + fuzzer_checksum + fuzzer_compress + fuzzer_example_small + fuzzer_example_large + fuzzer_example_flush + fuzzer_example_dict + ) + +if(WITH_GZFILEOP) + list(APPEND FUZZERS fuzzer_minigzip) +endif() + +foreach(FUZZER ${FUZZERS}) + add_executable(${FUZZER} ${FUZZER}.c) + + if(NOT FUZZING_ENGINE_FOUND) + target_sources(${FUZZER} PRIVATE standalone_fuzz_target_runner.c) + endif() + + target_link_libraries(${FUZZER} zlibstatic) + if(FUZZING_ENGINE_FOUND) + target_link_libraries(${FUZZER} ${FUZZING_ENGINE}) + endif() + + if(ZLIB_ENABLE_TESTS) + file(GLOB FUZZER_TEST_FILES ${CMAKE_SOURCE_DIR}/*) + set(FUZZER_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ ${FUZZER_TEST_FILES}) + add_test(NAME ${FUZZER} COMMAND ${FUZZER_COMMAND}) + endif() +endforeach() From a848a1ffe2963662d51c59ecc2953d21ab67d6f7 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 2 Apr 2022 15:41:21 -0700 Subject: [PATCH 365/798] Fixed building tests when -DWITH_GZFILEOP=OFF --- test/CMakeLists.txt | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 64b51c302a..6ebaf7c966 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,12 +49,37 @@ if(NOT googletest_POPULATED) add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR} EXCLUDE_FROM_ALL) endif() -file(GLOB TEST_SRCS - LIST_DIRECTORIES false - RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/test_*.cc) +set(TEST_SRCS + test_adler32.cc + test_aligned_alloc.cc + test_compare256.cc + test_compress.cc + test_crc32.cc + test_cve-2003-0107.cc + test_deflate_bound.cc + test_deflate_copy.cc + test_deflate_dict.cc + test_deflate_hash_head_0.cc + test_deflate_header.cc + test_deflate_params.cc + test_deflate_pending.cc + test_deflate_prime.cc + test_deflate_quick_bi_valid.cc + test_deflate_quick_block_open.cc + test_deflate_tune.cc + test_dict.cc + test_inflate_adler32.cc + test_inflate_sync.cc + test_large_buffers.cc + test_small_buffers.cc + test_version.cc + ) -add_executable(gtest_zlib ${TEST_SRCS}) +if(WITH_GZFILEOP) + list(APPEND TEST_SRCS test_gzio.cc) +endif() + +add_executable(gtest_zlib test_main.cc ${TEST_SRCS}) target_include_directories(gtest_zlib PRIVATE ${CMAKE_SOURCE_DIR} From 03a44f98fe87e8f74aafbebcb86748deccb2e593 Mon Sep 17 00:00:00 2001 From: Dan Kegel Date: Fri, 1 Apr 2022 19:42:28 +0000 Subject: [PATCH 366/798] abicheck.sh: zlib-ng is a bash script, not a sh script, don't hardcode shell when running configure --- test/abicheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/abicheck.sh b/test/abicheck.sh index 5c142556b3..5b720acfe7 100755 --- a/test/abicheck.sh +++ b/test/abicheck.sh @@ -121,7 +121,7 @@ then git reset --hard FETCH_HEAD cd .. # Build unstripped, uninstalled, very debug shared library - CFLAGS="$CFLAGS -ggdb" sh src.d/configure $CONFIGURE_ARGS + CFLAGS="$CFLAGS -ggdb" src.d/configure $CONFIGURE_ARGS make -j2 cd .. # Find shared library, extract its abi From 445284c5707665e36234f2dc16a22c8dcbb80fd8 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 2 Apr 2022 17:31:45 -0700 Subject: [PATCH 367/798] Fixed missing crc32_combine exports for zlib 1.2.12. --- win32/zlib.def.in | 3 +++ win32/zlibcompat.def.in | 3 +++ zlib_name_mangling-ng.h.in | 3 +++ zlib_name_mangling.h.in | 3 +++ 4 files changed, 12 insertions(+) diff --git a/win32/zlib.def.in b/win32/zlib.def.in index 66a6f66fb4..561a42f7f8 100644 --- a/win32/zlib.def.in +++ b/win32/zlib.def.in @@ -38,6 +38,7 @@ EXPORTS ; large file functions @ZLIB_SYMBOL_PREFIX@adler32_combine64 @ZLIB_SYMBOL_PREFIX@crc32_combine64 + @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64 ; checksum functions @ZLIB_SYMBOL_PREFIX@adler32 @ZLIB_SYMBOL_PREFIX@adler32_z @@ -45,6 +46,8 @@ EXPORTS @ZLIB_SYMBOL_PREFIX@crc32_z @ZLIB_SYMBOL_PREFIX@adler32_combine @ZLIB_SYMBOL_PREFIX@crc32_combine + @ZLIB_SYMBOL_PREFIX@crc32_combine_gen + @ZLIB_SYMBOL_PREFIX@crc32_combine_op ; various hacks, don't look :) @ZLIB_SYMBOL_PREFIX@deflateInit_ @ZLIB_SYMBOL_PREFIX@deflateInit2_ diff --git a/win32/zlibcompat.def.in b/win32/zlibcompat.def.in index dbb3c3f712..52a713cf03 100644 --- a/win32/zlibcompat.def.in +++ b/win32/zlibcompat.def.in @@ -69,6 +69,7 @@ EXPORTS @ZLIB_SYMBOL_PREFIX@gzoffset64 @ZLIB_SYMBOL_PREFIX@adler32_combine64 @ZLIB_SYMBOL_PREFIX@crc32_combine64 + @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64 ; checksum functions @ZLIB_SYMBOL_PREFIX@adler32 @ZLIB_SYMBOL_PREFIX@adler32_z @@ -76,6 +77,8 @@ EXPORTS @ZLIB_SYMBOL_PREFIX@crc32_z @ZLIB_SYMBOL_PREFIX@adler32_combine @ZLIB_SYMBOL_PREFIX@crc32_combine + @ZLIB_SYMBOL_PREFIX@crc32_combine_gen + @ZLIB_SYMBOL_PREFIX@crc32_combine_op ; various hacks, don't look :) @ZLIB_SYMBOL_PREFIX@deflateInit_ @ZLIB_SYMBOL_PREFIX@deflateInit2_ diff --git a/zlib_name_mangling-ng.h.in b/zlib_name_mangling-ng.h.in index 627ed46510..78ab9e3ef1 100644 --- a/zlib_name_mangling-ng.h.in +++ b/zlib_name_mangling-ng.h.in @@ -26,6 +26,9 @@ #define zng_crc32 @ZLIB_SYMBOL_PREFIX@zng_crc32 #define zng_crc32_combine @ZLIB_SYMBOL_PREFIX@zng_crc32_combine #define zng_crc32_combine64 @ZLIB_SYMBOL_PREFIX@zng_crc32_combine64 +#define zng_crc32_combine_gen @ZLIB_SYMBOL_PREFIX@zng_crc32_combine_gen +#define zng_crc32_combine_gen64 @ZLIB_SYMBOL_PREFIX@zng_crc32_combine_gen64 +#define zng_crc32_combine_op @ZLIB_SYMBOL_PREFIX@zng_crc32_combine_op #define zng_crc32_z @ZLIB_SYMBOL_PREFIX@zng_crc32_z #define zng_deflate @ZLIB_SYMBOL_PREFIX@zng_deflate #define zng_deflateBound @ZLIB_SYMBOL_PREFIX@zng_deflateBound diff --git a/zlib_name_mangling.h.in b/zlib_name_mangling.h.in index 22d458b1c9..5a1b2cea7e 100644 --- a/zlib_name_mangling.h.in +++ b/zlib_name_mangling.h.in @@ -26,6 +26,9 @@ #define crc32 @ZLIB_SYMBOL_PREFIX@crc32 #define crc32_combine @ZLIB_SYMBOL_PREFIX@crc32_combine #define crc32_combine64 @ZLIB_SYMBOL_PREFIX@crc32_combine64 +#define crc32_combine_gen @ZLIB_SYMBOL_PREFIX@crc32_combine_gen +#define crc32_combine_gen64 @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64 +#define crc32_combine_op @ZLIB_SYMBOL_PREFIX@crc32_combine_op #define crc32_z @ZLIB_SYMBOL_PREFIX@crc32_z #define deflate @ZLIB_SYMBOL_PREFIX@deflate #define deflateBound @ZLIB_SYMBOL_PREFIX@deflateBound From 6655c39fd0e2a1b558786cace02d6d77a8a95cf1 Mon Sep 17 00:00:00 2001 From: Dan Kegel Date: Sun, 3 Apr 2022 11:27:39 -0700 Subject: [PATCH 368/798] abicheck.sh: don't export CHOST if it wasn't already exported. This fixes https://github.com/zlib-ng/zlib-ng/issues/1219, a regression when running abicheck.sh with default compiler. --- test/abicheck.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/abicheck.sh b/test/abicheck.sh index 5b720acfe7..4267aff97d 100755 --- a/test/abicheck.sh +++ b/test/abicheck.sh @@ -94,7 +94,11 @@ then fi # Canonicalize CHOST to work around bug in original zlib's configure -export CHOST=$(sh $TESTDIR/../tools/config.sub $CHOST) +# (Don't export it if it wasn't already exported, else may cause +# default compiler detection failure and shared library link error +# when building both zlib and zlib-ng. +# See https://github.com/zlib-ng/zlib-ng/issues/1219) +CHOST=$(sh $TESTDIR/../tools/config.sub $CHOST) if test "$CHOST" = "" then From 81d91d6f674ca97b97f7d94dacd728e9ed121ec4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 2 Apr 2022 14:49:28 -0700 Subject: [PATCH 369/798] Remove sanitizer support from configure since it is better supported in cmake. Anybody who still needs it can use cmake or manually set CFLAGS and LDFLAGS. --- .github/workflows/configure.yml | 15 ------- README.md | 2 +- configure | 77 --------------------------------- 3 files changed, 1 insertion(+), 93 deletions(-) diff --git a/.github/workflows/configure.yml b/.github/workflows/configure.yml index ce367493ee..25d9b875c6 100644 --- a/.github/workflows/configure.yml +++ b/.github/workflows/configure.yml @@ -30,21 +30,6 @@ jobs: compiler: gcc configure-args: --warn --zlib-compat --without-optimizations --without-new-strategies - - name: Ubuntu GCC ASAN - os: ubuntu-latest - compiler: gcc - configure-args: --warn --with-sanitizer=address - - - name: Ubuntu GCC MSAN - os: ubuntu-latest - compiler: gcc - configure-args: --warn --with-sanitizer=memory - - - name: Ubuntu GCC No Unaligned UBSAN - os: ubuntu-latest - compiler: gcc - configure-args: --warn --without-unaligned --with-sanitizer=undefined - - name: Ubuntu GCC ARM SF os: ubuntu-latest compiler: arm-linux-gnueabi-gcc diff --git a/README.md b/README.md index 5df00579f3..e02e04b316 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ Build Options | WITH_OPTIM | --without-optimizations | Build with optimisations | ON | | WITH_NEW_STRATEGIES | --without-new-strategies | Use new strategies | ON | | WITH_NATIVE_INSTRUCTIONS | --native | Compiles with full instruction set supported on this host (gcc/clang -march=native) | OFF | -| WITH_SANITIZER | --with-sanitizer | Build with sanitizer (memory, address, undefined) | OFF | +| WITH_SANITIZER | | Build with sanitizer (memory, address, undefined) | OFF | | WITH_FUZZERS | | Build test/fuzz | OFF | | WITH_BENCHMARKS | | Build test/benchmarks | OFF | | WITH_MAINTAINER_WARNINGS | | Build with project maintainer warnings | OFF | diff --git a/configure b/configure index bf64ae35d1..aed1909ccb 100755 --- a/configure +++ b/configure @@ -99,7 +99,6 @@ buildneon=1 builddfltccdeflate=0 builddfltccinflate=0 buildcrc32vx=1 -with_sanitizer="" floatabi= native=0 forcesse2=0 @@ -176,7 +175,6 @@ case "$1" in echo ' [--with-reduced-mem] Reduced memory usage for special cases (reduces performance)' | tee -a configure.log echo ' [--force-sse2] Assume SSE2 instructions are always available (disabled by default on x86, enabled on x86_64)' | tee -a configure.log echo ' [--force-tzcnt] Assume TZCNT instructions are always available (disabled by default)' | tee -a configure.log - echo ' [--with-sanitizer] Build with sanitizer (memory, address, undefined)' | tee -a configure.log echo ' [--native] Compiles with full instruction set supported on this host' | tee -a configure.log exit 0 ;; -p*=* | --prefix=*) prefix=$(echo $1 | sed 's/.*=//'); shift ;; @@ -218,7 +216,6 @@ case "$1" in -oldstrat | --without-new-strategies) without_new_strategies=1; shift;; -w* | --warn) warn=1; shift ;; -d* | --debug) debug=1; shift ;; - --with-sanitizer=*) with_sanitizer=$(echo $1 | sed 's/.*=//'); shift ;; *) echo "unknown option: $1" | tee -a configure.log @@ -622,80 +619,6 @@ fi echo >> configure.log -if test "$with_sanitizer" = "address"; then - echo -n "Checking for address sanitizer... " | tee -a configure.log - sanitizers="" - for san in address pointer-compare pointer-subtract; do - if try $CC -c $CFLAGS $test.c -fsanitize=$san ; then - if test -n "$sanitizers"; then - sanitizers="$sanitizers,$san" - else - sanitizers="$san" - fi - fi - done - - if test -n "$sanitizers"; then - echo "-fsanitize=$sanitizers" | tee -a configure.log - CFLAGS="$CFLAGS -fsanitize=$sanitizers" - SFLAGS="$SFLAGS -fsanitize=$sanitizers" - LDFLAGS="$LDFLAGS -fsanitize=$sanitizers" - else - echo No | tee -a configure.log - fi - - echo -n "Checking for leak sanitizer... " | tee -a configure.log - if try $CC -c $CFLAGS $test.c -fsanitize=leak; then - echo "-fsanitize=leak" | tee -a configure.log - CFLAGS="$CFLAGS -fsanitize=leak" - SFLAGS="$SFLAGS -fsanitize=leak" - LDFLAGS="$LDFLAGS -fsanitize=leak" - else - echo No | tee -a configure.log - fi - - echo >> configure.log -fi - -if test "$with_sanitizer" = "memory"; then - echo -n "Checking for memory sanitizer... " | tee -a configure.log - if try $CC -c $CFLAGS $test.c -fsanitize=memory ; then - echo "-fsanitize=memory" | tee -a configure.log - CFLAGS="$CFLAGS -fsanitize=memory" - SFLAGS="$SFLAGS -fsanitize=memory" - LDFLAGS="$LDFLAGS -fsanitize=memory" - else - echo No | tee -a configure.log - fi - - echo >> configure.log -fi - -if test "$with_sanitizer" = "undefined"; then - echo -n "Checking for undefined behavior sanitizer... " | tee -a configure.log - sanitizers="" - for san in array-bounds bool bounds builtin enum float-cast-overflow float-divide-by-zero function integer-divide-by-zero local-bounds null nonnull-attribute object-size pointer-overflow return returns-nonnull-attribute shift shift-base shift-exponent signed-integer-overflow undefined unsigned-integer-overflow unsigned-shift-base vla-bound vptr; do - if try $CC -c $CFLAGS $test.c -fsanitize=$san; then - if test -n "$sanitizers"; then - sanitizers="$sanitizers,$san" - else - sanitizers="$san" - fi - fi - done - - if test -n "$sanitizers"; then - echo "-fsanitize=$sanitizers" | tee -a configure.log - CFLAGS="$CFLAGS -fsanitize=$sanitizers" - SFLAGS="$SFLAGS -fsanitize=$sanitizers" - LDFLAGS="$LDFLAGS -fsanitize=$sanitizers" - else - echo No | tee -a configure.log - fi - - echo >> configure.log -fi - # see if shared library build supported cat > $test.c < Date: Wed, 6 Apr 2022 18:15:57 -0400 Subject: [PATCH 370/798] Fix the custom PNG image based benchmark The height parameter was using a fixed macro, written at a time when the test imagery was fully synthetic. Because of this, images smaller than than our in-memory generated imagery will artificially throw a CRC error. --- test/benchmarks/benchmark_png_shared.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/benchmarks/benchmark_png_shared.h b/test/benchmarks/benchmark_png_shared.h index 1b29d3be9c..926b4d964f 100644 --- a/test/benchmarks/benchmark_png_shared.h +++ b/test/benchmarks/benchmark_png_shared.h @@ -124,7 +124,7 @@ static inline int decode_png(png_parse_dat *dat, png_bytepp out_bytes, size_t in int bit_depth = 0, color_type = -1; png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); - size_t im_size = width * height * bit_depth/8; + size_t im_size = width * height * bit_depth/8 * 3; if (color_type != PNG_COLOR_TYPE_RGB) { fprintf(stderr, "expected an 8 bpp RGB image\n"); abort(); @@ -136,9 +136,9 @@ static inline int decode_png(png_parse_dat *dat, png_bytepp out_bytes, size_t in png_bytep *out_rows = new png_bytep[height]; for (size_t i = 0; i < height; ++i) - out_rows[i] = *out_bytes + (width*i); + out_rows[i] = *out_bytes + (width*i*3); - png_read_rows(png, out_rows, NULL, IMHEIGHT); + png_read_rows(png, out_rows, NULL, height); png_destroy_read_struct(&png, &info, NULL); delete[] out_rows; From cd65646854504e02e68dcf3cffc2f5a5e9439a4e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Thu, 7 Apr 2022 20:39:21 -0700 Subject: [PATCH 371/798] Mimic minigzip behavior and only unlink files if not using -c copy out argument. --- test/minideflate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/minideflate.c b/test/minideflate.c index 8ef5ed917b..148a277692 100644 --- a/test/minideflate.c +++ b/test/minideflate.c @@ -346,7 +346,7 @@ int main(int argc, char **argv) { if (fin != stdin) { fclose(fin); - if (!keep) { + if (!copyout && !keep) { unlink(argv[i]); } } From 1dce534adb2ba7f136ebe89ad405fa4fd465702e Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 9 Apr 2022 07:22:01 -0700 Subject: [PATCH 372/798] Fixed off-by-one error when benchmarking compare256 resulting in heap-buffer-overflow. --- test/benchmarks/benchmark_compare256.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index e690e8effe..cc1ee5c19a 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -32,7 +32,7 @@ class compare256: public benchmark::Fixture { } void Bench(benchmark::State& state, compare256_func compare256) { - int32_t match_len = (int32_t)state.range(0); + int32_t match_len = (int32_t)state.range(0) - 1; uint32_t len; str2[match_len] = 0; From 24d1d8497ea8adca3e54d7b157db3ff31c37251c Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 10 Apr 2022 19:20:23 -0700 Subject: [PATCH 373/798] Rename memory alignment functions because they handle custom allocator which is the first parameter so having calloc and cfree (c = custom) is confusing in the name. --- test/test_aligned_alloc.cc | 6 +++--- zutil.c | 4 ++-- zutil.h | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/test_aligned_alloc.cc b/test/test_aligned_alloc.cc index 5d8517163f..259d474b87 100644 --- a/test/test_aligned_alloc.cc +++ b/test/test_aligned_alloc.cc @@ -1,4 +1,4 @@ -/* test_aligned_alloc.cc - Test zng_calloc_aligned and zng_cfree_aligned */ +/* test_aligned_alloc.cc - Test zng_alloc_aligned and zng_free_aligned */ #include #include @@ -39,8 +39,8 @@ void zng_cfree_unaligned(void *opaque, void *ptr) { } TEST(zalloc, aligned_64) { - void *return_ptr = zng_calloc_aligned(zng_calloc_unaligned, 0, 1, 100, 64); + void *return_ptr = zng_alloc_aligned(zng_calloc_unaligned, 0, 1, 100, 64); ASSERT_TRUE(return_ptr != NULL); EXPECT_EQ((intptr_t)return_ptr % 64, 0); - zng_cfree_aligned(zng_cfree_unaligned, 0, return_ptr); + zng_free_aligned(zng_cfree_unaligned, 0, return_ptr); } diff --git a/zutil.c b/zutil.c index 2ca6aae4b2..5583578615 100644 --- a/zutil.c +++ b/zutil.c @@ -112,7 +112,7 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr) { /* Since we support custom memory allocators, some which might not align memory as we expect, * we have to ask for extra memory and return an aligned pointer. */ -void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align) { +void Z_INTERNAL *zng_alloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align) { uintptr_t return_ptr, original_ptr; uint32_t alloc_size, align_diff; void *ptr; @@ -141,7 +141,7 @@ void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsign return (void *)return_ptr; } -void Z_INTERNAL zng_cfree_aligned(zng_cfree_func zfree, void *opaque, void *ptr) { +void Z_INTERNAL zng_free_aligned(zng_cfree_func zfree, void *opaque, void *ptr) { /* If no custom cfree function used then call zlib-ng's aligned cfree */ if (zfree == zng_cfree) { zng_cfree(opaque, ptr); diff --git a/zutil.h b/zutil.h index 5022b36f54..f70eb4bdbb 100644 --- a/zutil.h +++ b/zutil.h @@ -120,7 +120,7 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */ # define OS_CODE 3 /* assume Unix */ #endif - /* functions */ + /* memory allocation functions */ void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size); void Z_INTERNAL zng_cfree(void *opaque, void *ptr); @@ -128,11 +128,11 @@ void Z_INTERNAL zng_cfree(void *opaque, void *ptr); typedef void *zng_calloc_func(void *opaque, unsigned items, unsigned size); typedef void zng_cfree_func(void *opaque, void *ptr); -void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align); -void Z_INTERNAL zng_cfree_aligned(zng_cfree_func zfree, void *opaque, void *ptr); +void Z_INTERNAL *zng_alloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align); +void Z_INTERNAL zng_free_aligned(zng_cfree_func zfree, void *opaque, void *ptr); -#define ZALLOC(strm, items, size) zng_calloc_aligned((strm)->zalloc, (strm)->opaque, (items), (size), 64) -#define ZFREE(strm, addr) zng_cfree_aligned((strm)->zfree, (strm)->opaque, (void *)(addr)) +#define ZALLOC(strm, items, size) zng_alloc_aligned((strm)->zalloc, (strm)->opaque, (items), (size), 64) +#define ZFREE(strm, addr) zng_free_aligned((strm)->zfree, (strm)->opaque, (void *)(addr)) #define TRY_FREE(s, p) {if (p) ZFREE(s, p);} From c882034d48afc0b32a38e8f7ca63a2e4e91ab42d Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 10 Apr 2022 19:35:12 -0700 Subject: [PATCH 374/798] Use _msan_unposion to unposion end of window for when it needs to read the past < chunksize bytes in the window. See #1245. Co-authored-by: Adam Stylinski --- inflate.c | 7 ++++++- zbuild.h | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/inflate.c b/inflate.c index 1a0914859b..291582d057 100644 --- a/inflate.c +++ b/inflate.c @@ -205,7 +205,12 @@ int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) { state->window = (unsigned char *)ZALLOC_WINDOW(state->strm, wsize + state->chunksize, sizeof(unsigned char)); if (state->window == NULL) return Z_MEM_ERROR; - memset(state->window + wsize, 0, state->chunksize); +#ifdef Z_MEMORY_SANITIZER + /* This is _not_ to subvert the memory sanitizer but to instead unposion some + data we willingly and purposefully load uninitialized into vector registers + in order to safely read the last < chunksize bytes of the window. */ + __msan_unpoison(state->window + wsize, state->chunksize); +#endif } /* if window not in use yet, initialize */ diff --git a/zbuild.h b/zbuild.h index f692385344..9274cbc1ce 100644 --- a/zbuild.h +++ b/zbuild.h @@ -246,4 +246,11 @@ # define zmemcmp_8(str1, str2) memcmp(str1, str2, 8) #endif +#if defined(__has_feature) +# if __has_feature(memory_sanitizer) +# define Z_MEMORY_SANITIZER 1 +# include +# endif +#endif + #endif From c467068a3055669db53c0c8a205e573d61286d3f Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Mon, 4 Apr 2022 13:37:12 +0500 Subject: [PATCH 375/798] Disable LTO in CMake --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c8d867946..f049a0c823 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,6 +249,14 @@ else() endif() endif() +# Disable LTO +if(NOT WITH_NATIVE_INSTRUCTIONS) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) + foreach(_cfg_name IN LISTS CMAKE_CONFIGURATION_TYPES) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_${_cfg_name} OFF) + endforeach() +endif() + # Set architecture alignment requirements if(NOT WITH_UNALIGNED) add_definitions(-DNO_UNALIGNED) From 4fadf3c49e3dc98c5e1c0b86401324061d951d9f Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 6 Apr 2022 00:04:45 +0300 Subject: [PATCH 376/798] Add one extra byte to return value of compressBound and deflateBound for small lengths due to shift returning 0. * Treat 0 byte input as 1 byte input when calculating compressBound and deflateBound --- compress.c | 2 ++ deflate.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/compress.c b/compress.c index db13f6ca22..44f8dd9eb3 100644 --- a/compress.c +++ b/compress.c @@ -87,6 +87,8 @@ z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) { #ifndef NO_QUICK_STRATEGY return sourceLen /* The source size itself */ + + (sourceLen == 0 ? 1 : 0) /* Always at least one byte for any input */ + + (sourceLen < 9 ? 1 : 0) /* One extra byte for lengths less than 9 */ + DEFLATE_QUICK_OVERHEAD(sourceLen) /* Source encoding overhead, padded to next full byte */ + DEFLATE_BLOCK_OVERHEAD /* Deflate block overhead bytes */ + ZLIB_WRAPLEN; /* zlib wrapper */ diff --git a/deflate.c b/deflate.c index 50c5531f1b..233a629c42 100644 --- a/deflate.c +++ b/deflate.c @@ -646,6 +646,8 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long #ifndef NO_QUICK_STRATEGY return sourceLen /* The source size itself */ + + (sourceLen == 0 ? 1 : 0) /* Always at least one byte for any input */ + + (sourceLen < 9 ? 1 : 0) /* One extra byte for lengths less than 9 */ + DEFLATE_QUICK_OVERHEAD(sourceLen) /* Source encoding overhead, padded to next full byte */ + DEFLATE_BLOCK_OVERHEAD /* Deflate block overhead bytes */ + wraplen; /* none, zlib or gzip wrapper */ From 7690c7311bba604c74715cf4150fa6394464cdb8 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 6 Apr 2022 23:49:24 +0300 Subject: [PATCH 377/798] Add test for issue #1235. * Test both compressBound() and deflateBound() as those share same code fragment. --- test/Makefile.in | 11 +++++++++-- test/gh1235.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 test/gh1235.c diff --git a/test/Makefile.in b/test/Makefile.in index 4078d60d45..119eb6802e 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -55,7 +55,7 @@ testCVEinputs: check_cross_dep @EXE=$(EXE) QEMU_RUN="${QEMU_RUN}" $(SRCDIR)/testCVEinputs.sh .PHONY: ghtests -ghtests: testGH-361 testGH-364 testGH-751 +ghtests: testGH-361 testGH-364 testGH-751 testGH-1235 .PHONY: testGH-361 testGH-361: @@ -72,9 +72,16 @@ testGH-364: switchlevels$(EXE) testGH-751: $(QEMU_RUN) ../minigzip$(EXE) <$(SRCDIR)/GH-751/test.txt | $(QEMU_RUN) ../minigzip$(EXE) -d >/dev/null +gh1235$(EXE): $(SRCDIR)/gh1235.c + $(CC) $(CFLAGS) -I.. -I$(SRCTOP) -o $@ $< $(TEST_LDFLAGS) + +.PHONY: testGH-1235 +testGH-1235: gh1235$(EXE) + $(QEMU_RUN) ./gh1235$(EXE) + clean: rm -f *.o *.gcda *.gcno *.gcov - rm -f switchlevels$(EXE) + rm -f switchlevels$(EXE) gh1235$(EXE) distclean: rm -f Makefile diff --git a/test/gh1235.c b/test/gh1235.c new file mode 100644 index 0000000000..472282d1ee --- /dev/null +++ b/test/gh1235.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include "zutil.h" + +int main(void) { + unsigned char plain[32]; + unsigned char compressed[130]; + PREFIX3(stream) strm; + int bound; + z_size_t bytes; + + for (int i = 0; i <= 32; i++) { + memset(plain, 6, i); + memset(&strm, 0, sizeof(strm)); + PREFIX(deflateInit2)(&strm, 0, 8, 31, 1, Z_DEFAULT_STRATEGY); + bound = PREFIX(deflateBound)(&strm, i); + strm.next_in = plain; + strm.next_out = compressed; + strm.avail_in = i; + strm.avail_out = sizeof(compressed); + if (PREFIX(deflate)(&strm, Z_FINISH) != Z_STREAM_END) return -1; + if (strm.avail_in != 0) return -1; + printf("bytes = %2i, deflateBound = %2i, total_out = %2zi\n", i, bound, strm.total_out); + if (bound < strm.total_out) return -1; + if (PREFIX(deflateEnd)(&strm) != Z_OK) return -1; + } + for (int i = 0; i <= 32; i++) { + bytes = sizeof(compressed); + for (int j = 0; j < i; j++) { + plain[j] = j; + } + bound = PREFIX(compressBound)(i); + if (PREFIX(compress2)(compressed, &bytes, plain, i, 1) != Z_OK) return -1; + printf("bytes = %2i, compressBound = %2i, total_out = %2zi\n", i, bound, (size_t)bytes); + if (bytes > bound) return -1; + } + return 0; +} From dd5100d857bfafe890a524b5763785c71f2d7730 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 8 Apr 2022 21:43:54 -0700 Subject: [PATCH 378/798] Fixed failed tools tests when source directory is read-only. --- CMakeLists.txt | 8 ++++---- cmake/run-and-compare.cmake | 14 ++++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f049a0c823..0dd196130c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1217,7 +1217,7 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME makefixed COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKEFIXED_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/inffixed_tbl._h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/inffixed_tbl._h -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/inffixed_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -1231,7 +1231,7 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME maketrees COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKETREES_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/trees_tbl._h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/trees_tbl._h -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/trees_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -1245,7 +1245,7 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME makecrct-crc32 COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/crc32_tbl._h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/crc32_tbl._h -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) @@ -1254,7 +1254,7 @@ if(ZLIB_ENABLE_TESTS) add_test(NAME makecrct-crc32-combine COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/crc32_comb_tbl._h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/crc32_comb_tbl._h -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_comb_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) diff --git a/cmake/run-and-compare.cmake b/cmake/run-and-compare.cmake index 209d31e9e6..16f4821e55 100644 --- a/cmake/run-and-compare.cmake +++ b/cmake/run-and-compare.cmake @@ -41,10 +41,16 @@ endif() # Use configure_file to normalize line-endings if(IGNORE_LINE_ENDINGS) - configure_file(${COMPARE} ${COMPARE}.cmp NEWLINE_STYLE LF) - set(COMPARE ${COMPARE}.cmp) - configure_file(${OUTPUT} ${OUTPUT}.cmp NEWLINE_STYLE LF) - set(OUTPUT ${OUTPUT}.cmp) + # Rewrite files with normalized line endings to temporary directory + get_filename_component(COMPARE_NAME ${COMPARE} NAME) + set(COMPARE_TEMP ${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/${COMPARE_NAME}.cmp) + configure_file(${COMPARE} ${COMPARE_TEMP} NEWLINE_STYLE LF) + set(COMPARE ${COMPARE_TEMP}) + + get_filename_component(OUTPUT_NAME ${OUTPUT} NAME) + set(OUTPUT_TEMP ${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/${OUTPUT_NAME}.cmp) + configure_file(${OUTPUT} ${OUTPUT_TEMP} NEWLINE_STYLE LF) + set(OUTPUT ${OUTPUT_TEMP}) endif() # Compare that output is equal to specified file From e1baa6b439c06f3d0e6be3e381cc746ffb55aee1 Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 13 Apr 2022 01:22:29 +0300 Subject: [PATCH 379/798] Check that sys/auxv.h exists at configure time and add preprocessor define for it. * Protect including sys/auxv.h in all relevant files with the new preprocessor define * Test for both existence of both sys/auxv.h and getauxval() with both cmake and configure --- CMakeLists.txt | 7 ++++++- arch/arm/arm_features.c | 2 +- arch/power/power_features.c | 6 ++++-- arch/s390/s390_features.c | 8 ++++++-- cmake/detect-intrinsics.cmake | 10 ++++++++++ configure | 13 +++++++++++++ 6 files changed, 40 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dd196130c..e4e4b73327 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -290,6 +290,10 @@ endif() # # Check for standard/system includes # +check_include_file(sys/auxv.h HAVE_SYS_AUXV_H) +if(HAVE_SYS_AUXV_H) + add_definitions(-DHAVE_SYS_AUXV_H) +endif() check_include_file(sys/sdt.h HAVE_SYS_SDT_H) if(HAVE_SYS_SDT_H) add_definitions(-DHAVE_SYS_SDT_H) @@ -660,7 +664,8 @@ if(WITH_OPTIM) endif() endif() elseif(BASEARCH_S360_FOUND) - if(WITH_CRC32_VX) + check_s390_intrinsics() + if(HAVE_S390_INTRIN) add_definitions(-DS390_FEATURES) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/s390_features.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/s390_features.c) diff --git a/arch/arm/arm_features.c b/arch/arm/arm_features.c index 195c94992d..f6b67687f3 100644 --- a/arch/arm/arm_features.c +++ b/arch/arm/arm_features.c @@ -1,6 +1,6 @@ #include "../../zbuild.h" -#if defined(__linux__) +#if defined(__linux__) && defined(HAVE_SYS_AUXV_H) # include # ifdef ARM_ASM_HWCAP # include diff --git a/arch/power/power_features.c b/arch/power/power_features.c index 9186b40d83..65599d9a79 100644 --- a/arch/power/power_features.c +++ b/arch/power/power_features.c @@ -1,10 +1,12 @@ /* power_features.c - POWER feature check * Copyright (C) 2020 Matheus Castanho , IBM - * Copyright (C) 2021 Mika T. Lindqvist + * Copyright (C) 2021-2022 Mika T. Lindqvist * For conditions of distribution and use, see copyright notice in zlib.h */ -#include +#ifdef HAVE_SYS_AUXV_H +# include +#endif #include "../../zbuild.h" #include "power_features.h" diff --git a/arch/s390/s390_features.c b/arch/s390/s390_features.c index 465fe0f376..30bdde91e3 100644 --- a/arch/s390/s390_features.c +++ b/arch/s390/s390_features.c @@ -1,10 +1,14 @@ #include "../../zbuild.h" #include "s390_features.h" -#include +#ifdef HAVE_SYS_AUXV_H +# include +#endif -Z_INTERNAL int s390_cpu_has_vx; +Z_INTERNAL int s390_cpu_has_vx = 0; void Z_INTERNAL s390_check_features(void) { +#ifdef S390_FEATURES s390_cpu_has_vx = getauxval(AT_HWCAP) & HWCAP_S390_VX; +#endif } diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 9a4e54c3dc..80fecf2b1d 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -306,6 +306,16 @@ macro(check_power8_intrinsics) set(CMAKE_REQUIRED_FLAGS) endmacro() +macro(check_s390_intrinsics) + check_c_source_compiles( + "#include + int main() { + return (getauxval(AT_HWCAP) & HWCAP_S390_VX); + }" + HAVE_S390_INTRIN + ) +endmacro() + macro(check_sse2_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "Intel") if(CMAKE_HOST_UNIX OR APPLE) diff --git a/configure b/configure index aed1909ccb..a357e1c8aa 100755 --- a/configure +++ b/configure @@ -733,6 +733,19 @@ else echo "Checking for strerror... No." | tee -a configure.log fi +# check for getauxval() for architecture feature detection at run-time +cat > $test.c < +int main() { return getauxval(0); } +EOF +if try $CC $CFLAGS -o $test $test.c $LDSHAREDLIBC; then + echo "Checking for getauxval() in sys/auxv.h... Yes." | tee -a configure.log + CFLAGS="${CFLAGS} -DHAVE_SYS_AUXV_H" + SFLAGS="${SFLAGS} -DHAVE_SYS_AUXV_H" +else + echo "Checking for getauxval() in sys/auxv.h... No." | tee -a configure.log +fi + # We need to remove consigured files (zconf.h etc) from source directory if building outside of it if [ "$SRCDIR" != "$BUILDDIR" ]; then rm -f $SRCDIR/zconf${SUFFIX}.h From bb89b77f78bfba795c7846f5ce68430bd332685f Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Wed, 13 Apr 2022 04:24:12 +0300 Subject: [PATCH 380/798] Don't try to build tests or benchmarks if cmake is too old for them. --- CMakeLists.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e4e4b73327..447d92aca7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1147,9 +1147,13 @@ option(ZLIB_ENABLE_TESTS "Build test binaries" ON) if(ZLIB_ENABLE_TESTS) enable_testing() - add_subdirectory(test) - if(WITH_BENCHMARKS) - add_subdirectory(test/benchmarks) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12) + add_subdirectory(test) + if(WITH_BENCHMARKS) + add_subdirectory(test/benchmarks) + endif() + else() + message(WARNING "Minimum cmake version of 3.12 not met for GoogleTest or benchmarks!") endif() macro(configure_test_executable target) From 9be98893aaf69892811d617122e28ea2dd8e17ba Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 12 Apr 2022 15:16:20 +0200 Subject: [PATCH 381/798] Use PREFIX() for some of the Z_INTERNAL symbols https://github.com/powturbo/TurboBench links zlib and zlib-ng into the same binary, causing non-static symbol conflicts. Fix by using PREFIX() for flush_pending(), bi_reverse(), inflate_ensure_window() and all of the IBM Z symbols. Note: do not use an explicit zng_, since one of the long-term goals is to be able to link two versions of zlib-ng into the same binary for benchmarking [1]. [1] https://github.com/zlib-ng/zlib-ng/pull/1248#issuecomment-1096648932 --- arch/s390/crc32-vx.c | 2 +- arch/s390/dfltcc_common.c | 10 ++++---- arch/s390/dfltcc_common.h | 20 ++++++++-------- arch/s390/dfltcc_deflate.c | 24 +++++++++---------- arch/s390/dfltcc_deflate.h | 38 +++++++++++++++--------------- arch/s390/dfltcc_inflate.c | 16 ++++++------- arch/s390/dfltcc_inflate.h | 24 +++++++++---------- arch/s390/s390_features.c | 6 ++--- arch/s390/s390_features.h | 4 ++-- cpu_features.c | 2 +- cpu_features.h | 2 +- deflate.c | 22 ++++++++--------- deflate.h | 4 ++-- deflate_p.h | 4 ++-- deflate_quick.c | 4 ++-- deflate_stored.c | 4 ++-- functable.c | 4 ++-- inflate.c | 4 ++-- inflate.h | 2 +- test/benchmarks/benchmark_crc32.cc | 2 +- test/test_crc32.cc | 2 +- tools/maketrees.c | 2 +- trees.c | 4 ++-- 23 files changed, 103 insertions(+), 103 deletions(-) diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index e7a6109502..3477743ddb 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -198,7 +198,7 @@ static uint32_t crc32_le_vgfm_16(uint32_t crc, const unsigned char *buf, size_t #define VX_ALIGNMENT 16L #define VX_ALIGN_MASK (VX_ALIGNMENT - 1) -uint32_t Z_INTERNAL s390_crc32_vx(uint32_t crc, const unsigned char *buf, uint64_t len) { +uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf, uint64_t len) { uint64_t prealign, aligned, remaining; if (len < VX_MIN_LEN + VX_ALIGN_MASK) diff --git a/arch/s390/dfltcc_common.c b/arch/s390/dfltcc_common.c index f1ae904ad5..a5b5e1f3f3 100644 --- a/arch/s390/dfltcc_common.c +++ b/arch/s390/dfltcc_common.c @@ -35,7 +35,7 @@ static inline int is_dfltcc_enabled(void) { return is_bit_set((const char *)facilities, DFLTCC_FACILITY); } -void Z_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size) { +void Z_INTERNAL PREFIX(dfltcc_reset)(PREFIX3(streamp) strm, uInt size) { struct dfltcc_state *dfltcc_state = (struct dfltcc_state *)((char *)strm->state + ALIGN_UP(size, 8)); struct dfltcc_qaf_param *param = (struct dfltcc_qaf_param *)&dfltcc_state->param; @@ -58,17 +58,17 @@ void Z_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size) { dfltcc_state->param.ribm = DFLTCC_RIBM; } -void Z_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size) { +void Z_INTERNAL *PREFIX(dfltcc_alloc_state)(PREFIX3(streamp) strm, uInt items, uInt size) { return ZALLOC(strm, ALIGN_UP(items * size, 8) + sizeof(struct dfltcc_state), sizeof(unsigned char)); } -void Z_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size) { +void Z_INTERNAL PREFIX(dfltcc_copy_state)(void *dst, const void *src, uInt size) { memcpy(dst, src, ALIGN_UP(size, 8) + sizeof(struct dfltcc_state)); } static const int PAGE_ALIGN = 0x1000; -void Z_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size) { +void Z_INTERNAL *PREFIX(dfltcc_alloc_window)(PREFIX3(streamp) strm, uInt items, uInt size) { void *p; void *w; @@ -83,7 +83,7 @@ void Z_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt siz return w; } -void Z_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w) { +void Z_INTERNAL PREFIX(dfltcc_free_window)(PREFIX3(streamp) strm, void *w) { if (w) ZFREE(strm, *(void **)((unsigned char *)w - sizeof(void *))); } diff --git a/arch/s390/dfltcc_common.h b/arch/s390/dfltcc_common.h index df4b8b5784..374e06e271 100644 --- a/arch/s390/dfltcc_common.h +++ b/arch/s390/dfltcc_common.h @@ -3,23 +3,23 @@ #include "zutil.h" -void Z_INTERNAL *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt items, uInt size); -void Z_INTERNAL dfltcc_copy_state(void *dst, const void *src, uInt size); -void Z_INTERNAL dfltcc_reset(PREFIX3(streamp) strm, uInt size); -void Z_INTERNAL *dfltcc_alloc_window(PREFIX3(streamp) strm, uInt items, uInt size); -void Z_INTERNAL dfltcc_free_window(PREFIX3(streamp) strm, void *w); +void Z_INTERNAL *PREFIX(dfltcc_alloc_state)(PREFIX3(streamp) strm, uInt items, uInt size); +void Z_INTERNAL PREFIX(dfltcc_copy_state)(void *dst, const void *src, uInt size); +void Z_INTERNAL PREFIX(dfltcc_reset)(PREFIX3(streamp) strm, uInt size); +void Z_INTERNAL *PREFIX(dfltcc_alloc_window)(PREFIX3(streamp) strm, uInt items, uInt size); +void Z_INTERNAL PREFIX(dfltcc_free_window)(PREFIX3(streamp) strm, void *w); -#define ZALLOC_STATE dfltcc_alloc_state +#define ZALLOC_STATE PREFIX(dfltcc_alloc_state) #define ZFREE_STATE ZFREE -#define ZCOPY_STATE dfltcc_copy_state +#define ZCOPY_STATE PREFIX(dfltcc_copy_state) -#define ZALLOC_WINDOW dfltcc_alloc_window +#define ZALLOC_WINDOW PREFIX(dfltcc_alloc_window) -#define ZFREE_WINDOW dfltcc_free_window +#define ZFREE_WINDOW PREFIX(dfltcc_free_window) -#define TRY_FREE_WINDOW dfltcc_free_window +#define TRY_FREE_WINDOW PREFIX(dfltcc_free_window) #define DFLTCC_BLOCK_HEADER_BITS 3 #define DFLTCC_HLITS_COUNT_BITS 5 diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index dcb3f7c5d7..b088913017 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -43,7 +43,7 @@ static inline int dfltcc_can_deflate_with_params(PREFIX3(streamp) strm, int leve return 1; } -int Z_INTERNAL dfltcc_can_deflate(PREFIX3(streamp) strm) { +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); @@ -77,8 +77,8 @@ static inline dfltcc_cc dfltcc_cmpr(PREFIX3(streamp) strm) { static inline void send_eobs(PREFIX3(streamp) strm, const struct dfltcc_param_v0 *param) { deflate_state *state = (deflate_state *)strm->state; - send_bits(state, bi_reverse(param->eobs >> (15 - param->eobl), param->eobl), param->eobl, state->bi_buf, state->bi_valid); - flush_pending(strm); + send_bits(state, PREFIX(bi_reverse)(param->eobs >> (15 - param->eobl), param->eobl), param->eobl, state->bi_buf, state->bi_valid); + PREFIX(flush_pending)(strm); if (state->pending != 0) { /* The remaining data is located in pending_out[0:pending]. If someone * calls put_byte() - this might happen in deflate() - the byte will be @@ -94,7 +94,7 @@ static inline void send_eobs(PREFIX3(streamp) strm, const struct dfltcc_param_v0 #endif } -int Z_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *result) { +int Z_INTERNAL PREFIX(dfltcc_deflate)(PREFIX3(streamp) strm, int flush, block_state *result) { deflate_state *state = (deflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; @@ -104,7 +104,7 @@ int Z_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *res int soft_bcc; int no_flush; - if (!dfltcc_can_deflate(strm)) { + if (!PREFIX(dfltcc_can_deflate)(strm)) { /* Clear history. */ if (flush == Z_FULL_FLUSH) param->hl = 0; @@ -299,9 +299,9 @@ static int dfltcc_was_deflate_used(PREFIX3(streamp) strm) { return strm->total_in > 0 || param->nt == 0 || param->hl > 0; } -int Z_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strategy, int *flush) { +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 = dfltcc_can_deflate(strm); + int could_deflate = PREFIX(dfltcc_can_deflate)(strm); int can_deflate = dfltcc_can_deflate_with_params(strm, level, state->w_bits, strategy, state->reproducible); if (can_deflate == could_deflate) @@ -317,7 +317,7 @@ int Z_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strat return Z_OK; } -int Z_INTERNAL dfltcc_deflate_done(PREFIX3(streamp) strm, int flush) { +int Z_INTERNAL PREFIX(dfltcc_deflate_done)(PREFIX3(streamp) strm, int flush) { deflate_state *state = (deflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; @@ -333,10 +333,10 @@ int Z_INTERNAL dfltcc_deflate_done(PREFIX3(streamp) strm, int flush) { * buffered some data (Continuation Flag is set), or has not written EOBS * yet (Block-Continuation Flag is set). */ - return !dfltcc_can_deflate(strm) || (!param->cf && !param->bcf); + return !PREFIX(dfltcc_can_deflate)(strm) || (!param->cf && !param->bcf); } -int Z_INTERNAL dfltcc_can_set_reproducible(PREFIX3(streamp) strm, int reproducible) { +int Z_INTERNAL PREFIX(dfltcc_can_set_reproducible)(PREFIX3(streamp) strm, int reproducible) { deflate_state *state = (deflate_state *)strm->state; return reproducible != state->reproducible && !dfltcc_was_deflate_used(strm); @@ -375,7 +375,7 @@ static void append_history(struct dfltcc_param_v0 *param, unsigned char *history } } -int Z_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm, +int Z_INTERNAL PREFIX(dfltcc_deflate_set_dictionary)(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length) { deflate_state *state = (deflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); @@ -387,7 +387,7 @@ int Z_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm, return Z_OK; } -int Z_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt *dict_length) { +int Z_INTERNAL PREFIX(dfltcc_deflate_get_dictionary)(PREFIX3(streamp) strm, unsigned char *dictionary, uInt *dict_length) { deflate_state *state = (deflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; diff --git a/arch/s390/dfltcc_deflate.h b/arch/s390/dfltcc_deflate.h index 218e594693..15473540c9 100644 --- a/arch/s390/dfltcc_deflate.h +++ b/arch/s390/dfltcc_deflate.h @@ -3,53 +3,53 @@ #include "dfltcc_common.h" -int Z_INTERNAL dfltcc_can_deflate(PREFIX3(streamp) strm); -int Z_INTERNAL dfltcc_deflate(PREFIX3(streamp) strm, int flush, block_state *result); -int Z_INTERNAL dfltcc_deflate_params(PREFIX3(streamp) strm, int level, int strategy, int *flush); -int Z_INTERNAL dfltcc_deflate_done(PREFIX3(streamp) strm, int flush); -int Z_INTERNAL dfltcc_can_set_reproducible(PREFIX3(streamp) strm, int reproducible); -int Z_INTERNAL dfltcc_deflate_set_dictionary(PREFIX3(streamp) strm, +int Z_INTERNAL PREFIX(dfltcc_can_deflate)(PREFIX3(streamp) strm); +int Z_INTERNAL PREFIX(dfltcc_deflate)(PREFIX3(streamp) strm, int flush, block_state *result); +int Z_INTERNAL PREFIX(dfltcc_deflate_params)(PREFIX3(streamp) strm, int level, int strategy, int *flush); +int Z_INTERNAL PREFIX(dfltcc_deflate_done)(PREFIX3(streamp) strm, int flush); +int Z_INTERNAL PREFIX(dfltcc_can_set_reproducible)(PREFIX3(streamp) strm, int reproducible); +int Z_INTERNAL PREFIX(dfltcc_deflate_set_dictionary)(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length); -int Z_INTERNAL dfltcc_deflate_get_dictionary(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length); +int Z_INTERNAL PREFIX(dfltcc_deflate_get_dictionary)(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length); #define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \ do { \ - if (dfltcc_can_deflate((strm))) \ - return dfltcc_deflate_set_dictionary((strm), (dict), (dict_len)); \ + if (PREFIX(dfltcc_can_deflate)((strm))) \ + return PREFIX(dfltcc_deflate_set_dictionary)((strm), (dict), (dict_len)); \ } while (0) #define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \ do { \ - if (dfltcc_can_deflate((strm))) \ - return dfltcc_deflate_get_dictionary((strm), (dict), (dict_len)); \ + if (PREFIX(dfltcc_can_deflate)((strm))) \ + return PREFIX(dfltcc_deflate_get_dictionary)((strm), (dict), (dict_len)); \ } while (0) #define DEFLATE_RESET_KEEP_HOOK(strm) \ - dfltcc_reset((strm), sizeof(deflate_state)) + PREFIX(dfltcc_reset)((strm), sizeof(deflate_state)) #define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) \ do { \ int err; \ \ - err = dfltcc_deflate_params((strm), (level), (strategy), (hook_flush)); \ + err = PREFIX(dfltcc_deflate_params)((strm), (level), (strategy), (hook_flush)); \ if (err == Z_STREAM_ERROR) \ return err; \ } while (0) -#define DEFLATE_DONE dfltcc_deflate_done +#define DEFLATE_DONE PREFIX(dfltcc_deflate_done) #define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \ do { \ - if (dfltcc_can_deflate((strm))) \ + if (PREFIX(dfltcc_can_deflate)((strm))) \ (complen) = DEFLATE_BOUND_COMPLEN(source_len); \ } while (0) -#define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) (dfltcc_can_deflate((strm))) +#define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) (PREFIX(dfltcc_can_deflate)((strm))) -#define DEFLATE_HOOK dfltcc_deflate +#define DEFLATE_HOOK PREFIX(dfltcc_deflate) -#define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm))) +#define DEFLATE_NEED_CHECKSUM(strm) (!PREFIX(dfltcc_can_deflate)((strm))) -#define DEFLATE_CAN_SET_REPRODUCIBLE dfltcc_can_set_reproducible +#define DEFLATE_CAN_SET_REPRODUCIBLE PREFIX(dfltcc_can_set_reproducible) #endif diff --git a/arch/s390/dfltcc_inflate.c b/arch/s390/dfltcc_inflate.c index 253506466d..99024dc9c5 100644 --- a/arch/s390/dfltcc_inflate.c +++ b/arch/s390/dfltcc_inflate.c @@ -20,7 +20,7 @@ #include "dfltcc_inflate.h" #include "dfltcc_detail.h" -int Z_INTERNAL dfltcc_can_inflate(PREFIX3(streamp) strm) { +int Z_INTERNAL PREFIX(dfltcc_can_inflate)(PREFIX3(streamp) strm) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); @@ -47,7 +47,7 @@ static inline dfltcc_cc dfltcc_xpnd(PREFIX3(streamp) strm) { return cc; } -dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret) { +dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, int flush, int *ret) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); struct dfltcc_param_v0 *param = &dfltcc_state->param; @@ -55,7 +55,7 @@ dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush if (flush == Z_BLOCK || flush == Z_TREES) { /* DFLTCC does not support stopping on block boundaries */ - if (dfltcc_inflate_disable(strm)) { + if (PREFIX(dfltcc_inflate_disable)(strm)) { *ret = Z_STREAM_ERROR; return DFLTCC_INFLATE_BREAK; } else @@ -75,7 +75,7 @@ dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush if (strm->avail_in == 0 && !param->cf) return DFLTCC_INFLATE_BREAK; - if (inflate_ensure_window(state)) { + if (PREFIX(inflate_ensure_window)(state)) { state->mode = MEM; return DFLTCC_INFLATE_CONTINUE; } @@ -112,20 +112,20 @@ dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE; } -int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm) { +int Z_INTERNAL PREFIX(dfltcc_was_inflate_used)(PREFIX3(streamp) strm) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_param_v0 *param = &GET_DFLTCC_STATE(state)->param; return !param->nt; } -int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm) { +int Z_INTERNAL PREFIX(dfltcc_inflate_disable)(PREFIX3(streamp) strm) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - if (!dfltcc_can_inflate(strm)) + if (!PREFIX(dfltcc_can_inflate)(strm)) return 0; - if (dfltcc_was_inflate_used(strm)) + if (PREFIX(dfltcc_was_inflate_used)(strm)) /* DFLTCC has already decompressed some data. Since there is not * enough information to resume decompression in software, the call * must fail. diff --git a/arch/s390/dfltcc_inflate.h b/arch/s390/dfltcc_inflate.h index fc8a000f7b..69158ef032 100644 --- a/arch/s390/dfltcc_inflate.h +++ b/arch/s390/dfltcc_inflate.h @@ -3,28 +3,28 @@ #include "dfltcc_common.h" -int Z_INTERNAL dfltcc_can_inflate(PREFIX3(streamp) strm); +int Z_INTERNAL PREFIX(dfltcc_can_inflate)(PREFIX3(streamp) strm); typedef enum { DFLTCC_INFLATE_CONTINUE, DFLTCC_INFLATE_BREAK, DFLTCC_INFLATE_SOFTWARE, } dfltcc_inflate_action; -dfltcc_inflate_action Z_INTERNAL dfltcc_inflate(PREFIX3(streamp) strm, int flush, int *ret); -int Z_INTERNAL dfltcc_was_inflate_used(PREFIX3(streamp) strm); -int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm); +dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, int flush, int *ret); +int Z_INTERNAL PREFIX(dfltcc_was_inflate_used)(PREFIX3(streamp) strm); +int Z_INTERNAL PREFIX(dfltcc_inflate_disable)(PREFIX3(streamp) strm); #define INFLATE_RESET_KEEP_HOOK(strm) \ - dfltcc_reset((strm), sizeof(struct inflate_state)) + PREFIX(dfltcc_reset)((strm), sizeof(struct inflate_state)) #define INFLATE_PRIME_HOOK(strm, bits, value) \ - do { if (dfltcc_inflate_disable((strm))) return Z_STREAM_ERROR; } while (0) + do { if (PREFIX(dfltcc_inflate_disable)((strm))) return Z_STREAM_ERROR; } while (0) #define INFLATE_TYPEDO_HOOK(strm, flush) \ - if (dfltcc_can_inflate((strm))) { \ + if (PREFIX(dfltcc_can_inflate)((strm))) { \ dfltcc_inflate_action action; \ \ RESTORE(); \ - action = dfltcc_inflate((strm), (flush), &ret); \ + action = PREFIX(dfltcc_inflate)((strm), (flush), &ret); \ LOAD(); \ if (action == DFLTCC_INFLATE_CONTINUE) \ break; \ @@ -32,18 +32,18 @@ int Z_INTERNAL dfltcc_inflate_disable(PREFIX3(streamp) strm); goto inf_leave; \ } -#define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm))) +#define INFLATE_NEED_CHECKSUM(strm) (!PREFIX(dfltcc_can_inflate)((strm))) -#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm))) +#define INFLATE_NEED_UPDATEWINDOW(strm) (!PREFIX(dfltcc_can_inflate)((strm))) #define INFLATE_MARK_HOOK(strm) \ do { \ - if (dfltcc_was_inflate_used((strm))) return -(1L << 16); \ + if (PREFIX(dfltcc_was_inflate_used)((strm))) return -(1L << 16); \ } while (0) #define INFLATE_SYNC_POINT_HOOK(strm) \ do { \ - if (dfltcc_was_inflate_used((strm))) return Z_STREAM_ERROR; \ + if (PREFIX(dfltcc_was_inflate_used)((strm))) return Z_STREAM_ERROR; \ } while (0) #endif diff --git a/arch/s390/s390_features.c b/arch/s390/s390_features.c index 30bdde91e3..0658e4bbeb 100644 --- a/arch/s390/s390_features.c +++ b/arch/s390/s390_features.c @@ -5,10 +5,10 @@ # include #endif -Z_INTERNAL int s390_cpu_has_vx = 0; +Z_INTERNAL int PREFIX(s390_cpu_has_vx) = 0; -void Z_INTERNAL s390_check_features(void) { +void Z_INTERNAL PREFIX(s390_check_features)(void) { #ifdef S390_FEATURES - s390_cpu_has_vx = getauxval(AT_HWCAP) & HWCAP_S390_VX; + PREFIX(s390_cpu_has_vx) = getauxval(AT_HWCAP) & HWCAP_S390_VX; #endif } diff --git a/arch/s390/s390_features.h b/arch/s390/s390_features.h index 5ab9e92ee7..9e2608fa9e 100644 --- a/arch/s390/s390_features.h +++ b/arch/s390/s390_features.h @@ -1,8 +1,8 @@ #ifndef S390_FEATURES_H_ #define S390_FEATURES_H_ -extern int s390_cpu_has_vx; +extern int PREFIX(s390_cpu_has_vx); -void Z_INTERNAL s390_check_features(void); +void Z_INTERNAL PREFIX(s390_check_features)(void); #endif diff --git a/cpu_features.c b/cpu_features.c index 6ef5aa2c4b..b5e7257696 100644 --- a/cpu_features.c +++ b/cpu_features.c @@ -18,7 +18,7 @@ Z_INTERNAL void cpu_check_features(void) { #elif defined(PPC_FEATURES) || defined(POWER_FEATURES) power_check_features(); #elif defined(S390_FEATURES) - s390_check_features(); + PREFIX(s390_check_features)(); #endif features_checked = 1; } diff --git a/cpu_features.h b/cpu_features.h index 5607672178..81e13a3c8e 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -105,7 +105,7 @@ extern uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len) #elif defined(POWER8_VSX_CRC32) extern uint32_t crc32_power8(uint32_t crc, const unsigned char *buf, uint64_t len); #elif defined(S390_CRC32_VX) -extern uint32_t s390_crc32_vx(uint32_t crc, const unsigned char *buf, uint64_t len); +extern uint32_t PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf, uint64_t len); #endif /* compare256 */ diff --git a/deflate.c b/deflate.c index 233a629c42..cbf2b1cb4d 100644 --- a/deflate.c +++ b/deflate.c @@ -662,7 +662,7 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long * applications may wish to modify it to avoid allocating a large * strm->next_out buffer and copying into it. (See also read_buf()). */ -Z_INTERNAL void flush_pending(PREFIX3(stream) *strm) { +Z_INTERNAL void PREFIX(flush_pending)(PREFIX3(stream) *strm) { uint32_t len; deflate_state *s = strm->state; @@ -715,7 +715,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { /* Flush as much pending output as possible */ if (s->pending != 0) { - flush_pending(strm); + PREFIX(flush_pending)(strm); if (strm->avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and @@ -770,7 +770,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ - flush_pending(strm); + PREFIX(flush_pending)(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; @@ -792,7 +792,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ - flush_pending(strm); + PREFIX(flush_pending)(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; @@ -826,7 +826,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { s->pending = s->pending_buf_size; HCRC_UPDATE(beg); s->gzindex += copy; - flush_pending(strm); + PREFIX(flush_pending)(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; @@ -849,7 +849,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { do { if (s->pending == s->pending_buf_size) { HCRC_UPDATE(beg); - flush_pending(strm); + PREFIX(flush_pending)(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; @@ -872,7 +872,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { do { if (s->pending == s->pending_buf_size) { HCRC_UPDATE(beg); - flush_pending(strm); + PREFIX(flush_pending)(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; @@ -889,7 +889,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { if (s->status == HCRC_STATE) { if (s->gzhead->hcrc) { if (s->pending + 2 > s->pending_buf_size) { - flush_pending(strm); + PREFIX(flush_pending)(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; @@ -901,7 +901,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ - flush_pending(strm); + PREFIX(flush_pending)(strm); if (s->pending != 0) { s->last_flush = -1; return Z_OK; @@ -953,7 +953,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { } } } - flush_pending(strm); + PREFIX(flush_pending)(strm); if (strm->avail_out == 0) { s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ return Z_OK; @@ -975,7 +975,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { #endif if (s->wrap == 1) put_uint32_msb(s, strm->adler); - flush_pending(strm); + PREFIX(flush_pending)(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. */ diff --git a/deflate.h b/deflate.h index 87108914ee..b5ae2f8e66 100644 --- a/deflate.h +++ b/deflate.h @@ -381,8 +381,8 @@ void Z_INTERNAL zng_tr_flush_block(deflate_state *s, char *buf, uint32_t stored_ void Z_INTERNAL zng_tr_flush_bits(deflate_state *s); void Z_INTERNAL zng_tr_align(deflate_state *s); void Z_INTERNAL zng_tr_stored_block(deflate_state *s, char *buf, uint32_t stored_len, int last); -uint16_t Z_INTERNAL bi_reverse(unsigned code, int len); -void Z_INTERNAL flush_pending(PREFIX3(streamp) strm); +uint16_t Z_INTERNAL PREFIX(bi_reverse)(unsigned code, int len); +void Z_INTERNAL PREFIX(flush_pending)(PREFIX3(streamp) strm); #define d_code(dist) ((dist) < 256 ? zng_dist_code[dist] : zng_dist_code[256+((dist)>>7)]) /* Mapping from a distance to a distance code. dist is the distance - 1 and * must not have side effects. zng_dist_code[256] and zng_dist_code[257] are never diff --git a/deflate_p.h b/deflate_p.h index da667a0f9d..af24681a56 100644 --- a/deflate_p.h +++ b/deflate_p.h @@ -47,7 +47,7 @@ static inline void check_match(deflate_state *s, Pos start, Pos match, int lengt #define check_match(s, start, match, length) #endif -Z_INTERNAL void flush_pending(PREFIX3(stream) *strm); +Z_INTERNAL void PREFIX(flush_pending)(PREFIX3(stream) *strm); Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned size); /* =========================================================================== @@ -96,7 +96,7 @@ static inline int zng_tr_tally_dist(deflate_state *s, uint32_t dist, uint32_t le (uint32_t)((int)s->strstart - s->block_start), \ (last)); \ s->block_start = (int)s->strstart; \ - flush_pending(s->strm); \ + PREFIX(flush_pending)(s->strm); \ } /* Same but force premature exit if necessary. */ diff --git a/deflate_quick.c b/deflate_quick.c index a3162675ed..f7dfbe8aca 100644 --- a/deflate_quick.c +++ b/deflate_quick.c @@ -37,7 +37,7 @@ extern const ct_data static_dtree[D_CODES]; zng_tr_emit_end_block(s, static_ltree, last); \ s->block_open = 0; \ s->block_start = (int)s->strstart; \ - flush_pending(s->strm); \ + PREFIX(flush_pending)(s->strm); \ if (s->strm->avail_out == 0) \ return (last) ? finish_started : need_more; \ } \ @@ -63,7 +63,7 @@ Z_INTERNAL block_state deflate_quick(deflate_state *s, int flush) { for (;;) { if (UNLIKELY(s->pending + ((BIT_BUF_SIZE + 7) >> 3) >= s->pending_buf_size)) { - flush_pending(s->strm); + PREFIX(flush_pending)(s->strm); if (s->strm->avail_out == 0) { return (last && s->strm->avail_in == 0 && s->bi_valid == 0 && s->block_open == 0) ? finish_started : need_more; } diff --git a/deflate_stored.c b/deflate_stored.c index 92e57fad80..a9bc92164c 100644 --- a/deflate_stored.c +++ b/deflate_stored.c @@ -73,7 +73,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { put_short(s, (uint16_t)~len); /* Write the stored block header bytes. */ - flush_pending(s->strm); + PREFIX(flush_pending)(s->strm); /* Update debugging counts for the data about to be copied. */ cmpr_bits_add(s, len << 3); @@ -178,7 +178,7 @@ Z_INTERNAL block_state deflate_stored(deflate_state *s, int flush) { last = flush == Z_FINISH && s->strm->avail_in == 0 && len == left ? 1 : 0; zng_tr_stored_block(s, (char *)s->window + s->block_start, len, last); s->block_start += (int)len; - flush_pending(s->strm); + PREFIX(flush_pending)(s->strm); } /* We've done all we can with the available input and output. */ diff --git a/functable.c b/functable.c index ffb0d3f479..68aef1d338 100644 --- a/functable.c +++ b/functable.c @@ -371,8 +371,8 @@ Z_INTERNAL uint32_t crc32_stub(uint32_t crc, const unsigned char *buf, uint64_t if (power_cpu_has_arch_2_07) functable.crc32 = &crc32_power8; #elif defined(S390_CRC32_VX) - if (s390_cpu_has_vx) - functable.crc32 = &s390_crc32_vx; + if (PREFIX(s390_cpu_has_vx)) + functable.crc32 = &PREFIX(s390_crc32_vx); #elif defined(X86_PCLMULQDQ_CRC) if (x86_cpu_has_pclmulqdq) functable.crc32 = &crc32_pclmulqdq; diff --git a/inflate.c b/inflate.c index 291582d057..86f02cc4bf 100644 --- a/inflate.c +++ b/inflate.c @@ -198,7 +198,7 @@ void Z_INTERNAL fixedtables(struct inflate_state *state) { state->distbits = 5; } -int Z_INTERNAL inflate_ensure_window(struct inflate_state *state) { +int Z_INTERNAL PREFIX(inflate_ensure_window)(struct inflate_state *state) { /* if it hasn't been done already, allocate space for the window */ if (state->window == NULL) { unsigned wsize = 1U << state->wbits; @@ -243,7 +243,7 @@ static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t state = (struct inflate_state *)strm->state; - if (inflate_ensure_window(state)) return 1; + if (PREFIX(inflate_ensure_window)(state)) return 1; /* copy state->wsize or less output bytes into the circular window */ if (copy >= state->wsize) { diff --git a/inflate.h b/inflate.h index 3f57e78408..ffa2d0bd80 100644 --- a/inflate.h +++ b/inflate.h @@ -133,7 +133,7 @@ struct inflate_state { uint32_t chunksize; /* size of memory copying chunk */ }; -int Z_INTERNAL inflate_ensure_window(struct inflate_state *state); +int Z_INTERNAL PREFIX(inflate_ensure_window)(struct inflate_state *state); void Z_INTERNAL fixedtables(struct inflate_state *state); #endif /* INFLATE_H_ */ diff --git a/test/benchmarks/benchmark_crc32.cc b/test/benchmarks/benchmark_crc32.cc index 5908116f1c..06a11cfa0e 100644 --- a/test/benchmarks/benchmark_crc32.cc +++ b/test/benchmarks/benchmark_crc32.cc @@ -62,7 +62,7 @@ BENCHMARK_CRC32(acle, crc32_acle, arm_cpu_has_crc32); #elif defined(POWER8_VSX_CRC32) BENCHMARK_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07); #elif defined(S390_CRC32_VX) -BENCHMARK_CRC32(vx, s390_crc32_vx, s390_cpu_has_vx); +BENCHMARK_CRC32(vx, PREFIX(s390_crc32_vx), PREFIX(s390_cpu_has_vx)); #elif defined(X86_PCLMULQDQ_CRC) /* CRC32 fold does a memory copy while hashing */ BENCHMARK_CRC32(pclmulqdq, crc32_pclmulqdq, x86_cpu_has_pclmulqdq); diff --git a/test/test_crc32.cc b/test/test_crc32.cc index af0dd3b784..f76f838adf 100644 --- a/test/test_crc32.cc +++ b/test/test_crc32.cc @@ -213,7 +213,7 @@ TEST_CRC32(acle, crc32_acle, arm_cpu_has_crc32) #elif defined(POWER8_VSX_CRC32) TEST_CRC32(power8, crc32_power8, power_cpu_has_arch_2_07) #elif defined(S390_CRC32_VX) -TEST_CRC32(vx, s390_crc32_vx, s390_cpu_has_vx) +TEST_CRC32(vx, PREFIX(s390_crc32_vx), PREFIX(s390_cpu_has_vx)) #elif defined(X86_PCLMULQDQ_CRC) TEST_CRC32(pclmulqdq, crc32_pclmulqdq, x86_cpu_has_pclmulqdq) #endif diff --git a/tools/maketrees.c b/tools/maketrees.c index 282bddc2e5..97688c7aae 100644 --- a/tools/maketrees.c +++ b/tools/maketrees.c @@ -90,7 +90,7 @@ static void tr_static_init(void) { /* The static distance tree is trivial: */ for (n = 0; n < D_CODES; n++) { static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); + static_dtree[n].Code = PREFIX(bi_reverse)((unsigned)n, 5); } } diff --git a/trees.c b/trees.c index 5ff07636f4..7bc70075b5 100644 --- a/trees.c +++ b/trees.c @@ -305,7 +305,7 @@ Z_INTERNAL void gen_codes(ct_data *tree, int max_code, uint16_t *bl_count) { if (len == 0) continue; /* Now reverse the bits */ - tree[n].Code = bi_reverse(next_code[len]++, len); + tree[n].Code = PREFIX(bi_reverse)(next_code[len]++, len); Tracecv(tree != static_ltree, (stderr, "\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n & 0xff) ? n : ' '), len, tree[n].Code, next_code[len]-1)); @@ -808,7 +808,7 @@ static void bi_flush(deflate_state *s) { /* =========================================================================== * Reverse the first len bits of a code using bit manipulation */ -Z_INTERNAL uint16_t bi_reverse(unsigned code, int len) { +Z_INTERNAL uint16_t PREFIX(bi_reverse)(unsigned code, int len) { /* code: the value to invert */ /* len: its bit length */ Assert(len >= 1 && len <= 15, "code length must be 1-15"); From d0fc4e10b02c95bbc6ae5c169635d9ffb3f3665a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 9 Apr 2022 13:43:53 -0700 Subject: [PATCH 382/798] Remove CVE testing from configure script. --- .gitattributes | 1 - test/Makefile.in | 7 +------ test/testCVEinputs.sh | 30 ------------------------------ 3 files changed, 1 insertion(+), 37 deletions(-) delete mode 100755 test/testCVEinputs.sh diff --git a/.gitattributes b/.gitattributes index 3b35744b02..49d4490d70 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,4 +3,3 @@ *.h text Makefile text configure text eol=lf -testCVEinputs.sh text eol=lf diff --git a/test/Makefile.in b/test/Makefile.in index 119eb6802e..4cd1399ec5 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -13,7 +13,7 @@ TEST_LDFLAGS=-L.. ../$(LIBNAME).a QEMU_RUN= QEMU_VER:=$(shell command -v $(QEMU_RUN) --version 2> /dev/null) -all: oldtests cvetests ghtests +all: oldtests ghtests oldtests: #set by ../configure check_cross_dep: @@ -49,11 +49,6 @@ testshared: check_cross_dep fi; \ rm -f $$TMPSH $$HELLOSH -cvetests: testCVEinputs - -testCVEinputs: check_cross_dep - @EXE=$(EXE) QEMU_RUN="${QEMU_RUN}" $(SRCDIR)/testCVEinputs.sh - .PHONY: ghtests ghtests: testGH-361 testGH-364 testGH-751 testGH-1235 diff --git a/test/testCVEinputs.sh b/test/testCVEinputs.sh deleted file mode 100755 index 84f6b31c54..0000000000 --- a/test/testCVEinputs.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -TESTDIR="$(dirname "$0")" - -# check for QEMU if QEMU_RUN is set -if [ ! -z "${QEMU_RUN}" ]; then - QEMU_VERSION=$(${QEMU_RUN} --version 2> /dev/null) - if [ -z "${QEMU_VERSION}" ]; then - echo "**** You need QEMU to run tests on non-native platform" - exit 1 - fi -fi - -CVEs="CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096" - -for CVE in $CVEs; do - fail=0 - for testcase in ${TESTDIR}/${CVE}/*.gz; do - ${QEMU_RUN} ../minigzip${EXE} -d < "$testcase" - # we expect that a 1 error code is OK - # for a vulnerable failure we'd expect 134 or similar - if [ $? -ne 1 ] && [ $? -ne 0 ]; then - fail=1 - fi - done - if [ $fail -eq 0 ]; then - echo " --- zlib not vulnerable to $CVE ---"; - else - echo " --- zlib VULNERABLE to $CVE ---"; exit 1; - fi -done From 48e20af11043aa67c9ded8f8da77ffa026e61a59 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Fri, 22 Apr 2022 14:58:24 -0700 Subject: [PATCH 383/798] Fixed forcing CMAKE_BUILD_TYPE to Release on multi config generators such as Xcode or MSVC. Co-authored-by: Sergey Markelov --- CMakeLists.txt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 447d92aca7..f0b0880889 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,13 +59,15 @@ endif() # Make sure we use an appropriate BUILD_TYPE by default, "Release" to be exact # this should select the maximum generic optimisation on the current platform (i.e. -O3 for gcc/clang) -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING - "Choose the type of build, standard options are: Debug Release RelWithDebInfo MinSizeRel." - FORCE) - add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (default)") -else() - add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (selected)") +if(NOT GENERATOR_IS_MULTI_CONFIG) + if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING + "Choose the type of build, standard options are: Debug Release RelWithDebInfo MinSizeRel." + FORCE) + add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (default)") + else() + add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (selected)") + endif() endif() # From ae433e7ee1fc70c507f7d5ce5a19c6f704bf4acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C5=BEenan=20Zuki=C4=87?= Date: Mon, 25 Apr 2022 14:42:11 -0400 Subject: [PATCH 384/798] Remove trailing whitespace in several source code files --- arch/arm/adler32_neon.c | 14 +++++++------- arch/arm/slide_hash_neon.c | 4 ++-- arch/x86/adler32_avx2.c | 12 ++++++------ arch/x86/adler32_avx512.c | 4 ++-- arch/x86/adler32_avx512_p.h | 4 ++-- arch/x86/adler32_avx512_vnni.c | 4 ++-- arch/x86/adler32_ssse3.c | 2 +- arch/x86/crc32_fold_pclmulqdq.c | 6 +++--- chunkset_tpl.h | 2 +- cmake/detect-intrinsics.cmake | 2 +- 10 files changed, 27 insertions(+), 27 deletions(-) diff --git a/arch/arm/adler32_neon.c b/arch/arm/adler32_neon.c index dfbd54def9..7c2c51fae0 100644 --- a/arch/arm/adler32_neon.c +++ b/arch/arm/adler32_neon.c @@ -1,6 +1,6 @@ /* Copyright (C) 1995-2011, 2016 Mark Adler * Copyright (C) 2017 ARM Holdings Inc. - * Authors: + * Authors: * Adenilson Cavalcanti * Adam Stylinski * For conditions of distribution and use, see copyright notice in zlib.h @@ -23,7 +23,7 @@ static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) { 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, - 16, 15, 14, 13, 12, 11, 10, 9, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; uint32x4_t adacc = vdupq_n_u32(0); @@ -59,21 +59,21 @@ static void NEON_accum32(uint32_t *s, const unsigned char *buf, size_t len) { hsum_fold.val[0] = vpadalq_u8(hsum.val[0], d0_d3.val[2]); hsum_fold.val[1] = vpadalq_u8(hsum.val[1], d0_d3.val[3]); - adacc = vpadalq_u16(adacc, hsum_fold.val[0]); + adacc = vpadalq_u16(adacc, hsum_fold.val[0]); s3acc = vaddq_u32(s3acc, adacc_prev); - adacc = vpadalq_u16(adacc, hsum_fold.val[1]); - + adacc = vpadalq_u16(adacc, hsum_fold.val[1]); + /* If we do straight widening additions to the 16 bit values, we don't incur * the usual penalties of a pairwise add. We can defer the multiplications * until the very end. These will not overflow because we are incurring at * most 408 loop iterations (NMAX / 64), and a given lane is only going to be * summed into once. This means for the maximum input size, the largest value * we will see is 255 * 102 = 26010, safely under uint16 max */ - s2_0 = vaddw_u8(s2_0, vget_low_u8(d0_d3.val[0])); + s2_0 = vaddw_u8(s2_0, vget_low_u8(d0_d3.val[0])); s2_1 = vaddw_high_u8(s2_1, d0_d3.val[0]); s2_2 = vaddw_u8(s2_2, vget_low_u8(d0_d3.val[1])); s2_3 = vaddw_high_u8(s2_3, d0_d3.val[1]); - s2_4 = vaddw_u8(s2_4, vget_low_u8(d0_d3.val[2])); + s2_4 = vaddw_u8(s2_4, vget_low_u8(d0_d3.val[2])); s2_5 = vaddw_high_u8(s2_5, d0_d3.val[2]); s2_6 = vaddw_u8(s2_6, vget_low_u8(d0_d3.val[3])); s2_7 = vaddw_high_u8(s2_7, d0_d3.val[3]); diff --git a/arch/arm/slide_hash_neon.c b/arch/arm/slide_hash_neon.c index 6ff7a0bb60..8dc887379c 100644 --- a/arch/arm/slide_hash_neon.c +++ b/arch/arm/slide_hash_neon.c @@ -32,8 +32,8 @@ static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize n = size / (sizeof(uint16x8_t) * 8); do { - p0 = vld1q_u16_x4(table); - p1 = vld1q_u16_x4(table+32); + p0 = vld1q_u16_x4(table); + p1 = vld1q_u16_x4(table+32); vqsubq_u16_x4_x1(p0, p0, v); vqsubq_u16_x4_x1(p1, p1, v); vst1q_u16_x4(table, p0); diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index bd3547d0b1..50cea317ec 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -92,7 +92,7 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ /* The compiler is generating the following sequence for this integer modulus * when done the scalar way, in GPRs: - + adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); @@ -100,9 +100,9 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ ... vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax - imul %rdi,%rsi // do a signed multiplication with magic constant and vector element + imul %rdi,%rsi // do a signed multiplication with magic constant and vector element shr $0x2f,%rsi // shift right by 47 - imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 + imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above ... // repeats for each element with vpextract instructions @@ -110,17 +110,17 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_ This is tricky with AVX2 for a number of reasons: 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate - back down to 32 bit precision later (there is in AVX512) + back down to 32 bit precision later (there is in AVX512) 3.) Full width integer multiplications aren't cheap - We can, however, and do a relatively cheap sequence for horizontal sums. + We can, however, and do a relatively cheap sequence for horizontal sums. Then, we simply do the integer modulus on the resulting 64 bit GPR, on a scalar value. It was previously thought that casting to 64 bit precision was needed prior to the horizontal sum, but that is simply not the case, as NMAX is defined as the maximum number of scalar sums that can be performed on the maximum possible inputs before overflow */ - + /* In AVX2-land, this trip through GPRs will probably be unvoidable, as there's no cheap and easy * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index 05f8068a60..5571be45eb 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -19,8 +19,8 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, siz /* For impossibly tiny sizes, use the smaller width versions. We still need * to check for compile time support for these but they are likely there */ -#ifdef X86_SSE41_ADLER32 - if (len < 32) +#ifdef X86_SSE41_ADLER32 + if (len < 32) return adler32_sse41(adler, buf, len); #endif diff --git a/arch/x86/adler32_avx512_p.h b/arch/x86/adler32_avx512_p.h index 3751a449e1..5b79d2ab6e 100644 --- a/arch/x86/adler32_avx512_p.h +++ b/arch/x86/adler32_avx512_p.h @@ -24,7 +24,7 @@ static inline uint32_t _mm512_reduce_add_epu32(__m512i x) { static inline uint32_t partial_hsum(__m512i x) { /* We need a permutation vector to extract every other integer. The * rest are going to be zeros. Marking this const so the compiler stands - * a better chance of keeping this resident in a register through entire + * a better chance of keeping this resident in a register through entire * loop execution. We certainly have enough zmm registers (32) */ const __m512i perm_vec = _mm512_setr_epi32(0, 2, 4, 6, 8, 10, 12, 14, 1, 1, 1, 1, 1, 1, 1, 1); @@ -33,7 +33,7 @@ static inline uint32_t partial_hsum(__m512i x) { /* From here, it's a simple 256 bit wide reduction sum */ __m256i non_zero_avx = _mm512_castsi512_si256(non_zero); - + /* See Agner Fog's vectorclass for a decent reference. Essentially, phadd is * pretty slow, much slower than the longer instruction sequence below */ __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(non_zero_avx, 1), diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index 180f7f413e..253eed9c6a 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -20,8 +20,8 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf /* For impossibly tiny sizes, use the smaller width versions. We still need * to check for compile time support for these but they are likely there */ -#ifdef X86_SSE41_ADLER32 - if (len < 32) +#ifdef X86_SSE41_ADLER32 + if (len < 32) return adler32_sse41(adler, buf, len); #endif diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index 014c89a881..b2ef0115c8 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -87,7 +87,7 @@ Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size /* lop off the max number of sums based on the scalar sums done * above */ len -= align_offset; - max_iters -= align_offset; + max_iters -= align_offset; } diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 9072a47e7d..800e3d1766 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -402,7 +402,7 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t int32_t first = init_crc != 0; /* Technically the CRC functions don't even call this for input < 64, but a bare minimum of 31 - * bytes of input is needed for the aligning load that occurs. If there's an initial CRC, to + * bytes of input is needed for the aligning load that occurs. If there's an initial CRC, to * carry it forward through the folded CRC there must be 16 - src % 16 + 16 bytes available, which * by definition can be up to 15 bytes + one full vector load. */ assert(len >= 31 || first == 0); @@ -477,7 +477,7 @@ Z_INTERNAL void crc32_fold_pclmulqdq(crc32_fold *crc, const uint8_t *src, size_t xmm_crc2 = _mm_xor_si128(xmm_crc2, xmm_t1); xmm_crc3 = _mm_xor_si128(xmm_crc3, xmm_t2); len -= 48; - src += 48; + src += 48; } else if (len >= 32) { xmm_t0 = _mm_load_si128((__m128i *)src); xmm_t1 = _mm_load_si128((__m128i *)src + 1); @@ -596,7 +596,7 @@ Z_INTERNAL uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc) { uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len) { /* For lens < 64, crc32_byfour method is faster. The CRC32 instruction for * these short lengths might also prove to be effective */ - if (len < 64) + if (len < 64) return crc32_byfour(crc32, buf, len); crc32_fold ALIGNED_(16) crc_state; diff --git a/chunkset_tpl.h b/chunkset_tpl.h index f0539921ad..25ee955967 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -109,7 +109,7 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { bytes_remaining -= cpy_dist; cur_chunk += cpy_dist; /* This allows us to bypass an expensive integer division since we're effectively - * counting in this loop, anyway. However, we may have to derive a similarly + * counting in this loop, anyway. However, we may have to derive a similarly * sensible solution for if we use a permutation table that allows us to construct * this vector in one load and one permute instruction */ chunk_mod = cpy_dist; diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 80fecf2b1d..578a489dff 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -167,7 +167,7 @@ macro(check_neon_ld4_intrinsics) endif() endif() endif() - # Check whether compiler supports loading 4 neon vecs into a register range + # Check whether compiler supports loading 4 neon vecs into a register range set(CMAKE_REQUIRED_FLAGS "${NEONFLAG}") check_c_source_compiles( "#ifdef _M_ARM64 From d41f8ead569ee805b323b45fca30430cefe91cfd Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 18 Mar 2022 21:01:00 +0000 Subject: [PATCH 385/798] macOs M1 build fix on arm cpu checks. --- arch/arm/arm_features.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/arm_features.c b/arch/arm/arm_features.c index f6b67687f3..979204b83b 100644 --- a/arch/arm/arm_features.c +++ b/arch/arm/arm_features.c @@ -11,6 +11,9 @@ # define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32 # endif #elif defined(__APPLE__) +# if !defined(_DARWIN_C_SOURCE) +# define _DARWIN_C_SOURCE /* enable types aliases (eg u_int) */ +# endif # include #elif defined(_WIN32) # include From c592b1b33206be038a2de95577c29d28d4e76526 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 13 Apr 2022 13:46:24 +0200 Subject: [PATCH 386/798] IBM Z DFLTCC: Split deflate and inflate states Currently deflate and inflate both use a common state struct. There are several variables in this struct that we don't need for inflate, and more may be coming in the future. Therefore split them in two separate structs. This in turn requires splitting ZALLOC_STATE and ZCOPY_STATE macros. --- arch/s390/README.md | 3 ++- arch/s390/dfltcc_common.c | 53 -------------------------------------- arch/s390/dfltcc_common.h | 7 ----- arch/s390/dfltcc_deflate.c | 45 +++++++++++++++++++++++++++----- arch/s390/dfltcc_deflate.h | 9 +++++-- arch/s390/dfltcc_detail.h | 50 ++++++++++++++++++++++++++++++++--- arch/s390/dfltcc_inflate.c | 15 +++++++++++ arch/s390/dfltcc_inflate.h | 9 +++++-- deflate.c | 10 +++---- infback.c | 2 +- inflate.c | 6 ++--- inflate_p.h | 4 +-- 12 files changed, 126 insertions(+), 87 deletions(-) diff --git a/arch/s390/README.md b/arch/s390/README.md index 90066f0f96..18a7ca8cd9 100644 --- a/arch/s390/README.md +++ b/arch/s390/README.md @@ -61,7 +61,8 @@ integrated with the rest of zlib-ng using hook macros. ## Hook macros DFLTCC takes as arguments a parameter block, an input buffer, an output -buffer and a window. `ZALLOC_STATE()`, `ZFREE_STATE()`, `ZCOPY_STATE()`, +buffer and a window. `ZALLOC_DEFLATE_STATE()`, `ZALLOC_INFLATE_STATE()`, +`ZFREE_STATE()`, `ZCOPY_DEFLATE_STATE()`, `ZCOPY_INFLATE_STATE()`, `ZALLOC_WINDOW()` and `TRY_FREE_WINDOW()` macros encapsulate allocation details for the parameter block (which is allocated alongside zlib-ng state) and the window (which must be page-aligned). diff --git a/arch/s390/dfltcc_common.c b/arch/s390/dfltcc_common.c index a5b5e1f3f3..2937d8d645 100644 --- a/arch/s390/dfltcc_common.c +++ b/arch/s390/dfltcc_common.c @@ -12,59 +12,6 @@ `posix_memalign' is not an option. Thus, we overallocate and take the aligned portion of the buffer. */ -static inline int is_dfltcc_enabled(void) { - uint64_t facilities[(DFLTCC_FACILITY / 64) + 1]; - Z_REGISTER uint8_t r0 __asm__("r0"); - - memset(facilities, 0, sizeof(facilities)); - r0 = sizeof(facilities) / sizeof(facilities[0]) - 1; - /* STFLE is supported since z9-109 and only in z/Architecture mode. When - * compiling with -m31, gcc defaults to ESA mode, however, since the kernel - * is 64-bit, it's always z/Architecture mode at runtime. - */ - __asm__ volatile( -#ifndef __clang__ - ".machinemode push\n" - ".machinemode zarch\n" -#endif - "stfle %[facilities]\n" -#ifndef __clang__ - ".machinemode pop\n" -#endif - : [facilities] "=Q" (facilities), [r0] "+r" (r0) :: "cc"); - return is_bit_set((const char *)facilities, DFLTCC_FACILITY); -} - -void Z_INTERNAL PREFIX(dfltcc_reset)(PREFIX3(streamp) strm, uInt size) { - struct dfltcc_state *dfltcc_state = (struct dfltcc_state *)((char *)strm->state + ALIGN_UP(size, 8)); - struct dfltcc_qaf_param *param = (struct dfltcc_qaf_param *)&dfltcc_state->param; - - /* Initialize available functions */ - if (is_dfltcc_enabled()) { - dfltcc(DFLTCC_QAF, param, NULL, NULL, NULL, NULL, NULL); - memmove(&dfltcc_state->af, param, sizeof(dfltcc_state->af)); - } else - memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); - - /* Initialize parameter block */ - memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param)); - dfltcc_state->param.nt = 1; - - /* Initialize tuning parameters */ - dfltcc_state->level_mask = DFLTCC_LEVEL_MASK; - dfltcc_state->block_size = DFLTCC_BLOCK_SIZE; - dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE; - dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE; - dfltcc_state->param.ribm = DFLTCC_RIBM; -} - -void Z_INTERNAL *PREFIX(dfltcc_alloc_state)(PREFIX3(streamp) strm, uInt items, uInt size) { - return ZALLOC(strm, ALIGN_UP(items * size, 8) + sizeof(struct dfltcc_state), sizeof(unsigned char)); -} - -void Z_INTERNAL PREFIX(dfltcc_copy_state)(void *dst, const void *src, uInt size) { - memcpy(dst, src, ALIGN_UP(size, 8) + sizeof(struct dfltcc_state)); -} static const int PAGE_ALIGN = 0x1000; diff --git a/arch/s390/dfltcc_common.h b/arch/s390/dfltcc_common.h index 374e06e271..4f48bd9a4f 100644 --- a/arch/s390/dfltcc_common.h +++ b/arch/s390/dfltcc_common.h @@ -3,18 +3,11 @@ #include "zutil.h" -void Z_INTERNAL *PREFIX(dfltcc_alloc_state)(PREFIX3(streamp) strm, uInt items, uInt size); -void Z_INTERNAL PREFIX(dfltcc_copy_state)(void *dst, const void *src, uInt size); -void Z_INTERNAL PREFIX(dfltcc_reset)(PREFIX3(streamp) strm, uInt size); void Z_INTERNAL *PREFIX(dfltcc_alloc_window)(PREFIX3(streamp) strm, uInt items, uInt size); void Z_INTERNAL PREFIX(dfltcc_free_window)(PREFIX3(streamp) strm, void *w); -#define ZALLOC_STATE PREFIX(dfltcc_alloc_state) - #define ZFREE_STATE ZFREE -#define ZCOPY_STATE PREFIX(dfltcc_copy_state) - #define ZALLOC_WINDOW PREFIX(dfltcc_alloc_window) #define ZFREE_WINDOW PREFIX(dfltcc_free_window) diff --git a/arch/s390/dfltcc_deflate.c b/arch/s390/dfltcc_deflate.c index b088913017..0210ddc17f 100644 --- a/arch/s390/dfltcc_deflate.c +++ b/arch/s390/dfltcc_deflate.c @@ -19,10 +19,41 @@ #include "dfltcc_deflate.h" #include "dfltcc_detail.h" +struct dfltcc_deflate_state { + struct dfltcc_state common; + uint16_t level_mask; /* Levels on which to use DFLTCC */ + uint32_t block_size; /* New block each X bytes */ + size_t block_threshold; /* New block after total_in > X */ + uint32_t dht_threshold; /* New block only if avail_in >= X */ +}; + +#define GET_DFLTCC_DEFLATE_STATE(state) ((struct dfltcc_deflate_state *)GET_DFLTCC_STATE(state)) + +void Z_INTERNAL *PREFIX(dfltcc_alloc_deflate_state)(PREFIX3(streamp) strm) { + return dfltcc_alloc_state(strm, sizeof(deflate_state), sizeof(struct dfltcc_deflate_state)); +} + +void Z_INTERNAL PREFIX(dfltcc_reset_deflate_state)(PREFIX3(streamp) strm) { + deflate_state *state = (deflate_state *)strm->state; + struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state); + + dfltcc_reset_state(&dfltcc_state->common); + + /* Initialize tuning parameters */ + dfltcc_state->level_mask = DFLTCC_LEVEL_MASK; + dfltcc_state->block_size = DFLTCC_BLOCK_SIZE; + dfltcc_state->block_threshold = DFLTCC_FIRST_FHT_BLOCK_SIZE; + dfltcc_state->dht_threshold = DFLTCC_DHT_MIN_SAMPLE_SIZE; +} + +void Z_INTERNAL PREFIX(dfltcc_copy_deflate_state)(void *dst, const void *src) { + dfltcc_copy_state(dst, src, sizeof(deflate_state), sizeof(struct dfltcc_deflate_state)); +} + static inline int dfltcc_can_deflate_with_params(PREFIX3(streamp) strm, int level, uInt window_bits, int strategy, int reproducible) { deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); + struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state); /* Unsupported compression settings */ if ((dfltcc_state->level_mask & (1 << level)) == 0) @@ -35,9 +66,9 @@ static inline int dfltcc_can_deflate_with_params(PREFIX3(streamp) strm, int leve return 0; /* Unsupported hardware */ - if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) || - !is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) || - !is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0)) + if (!is_bit_set(dfltcc_state->common.af.fns, DFLTCC_GDHT) || + !is_bit_set(dfltcc_state->common.af.fns, DFLTCC_CMPR) || + !is_bit_set(dfltcc_state->common.af.fmts, DFLTCC_FMT0)) return 0; return 1; @@ -96,8 +127,8 @@ static inline void send_eobs(PREFIX3(streamp) strm, const struct dfltcc_param_v0 int Z_INTERNAL PREFIX(dfltcc_deflate)(PREFIX3(streamp) strm, int flush, block_state *result) { deflate_state *state = (deflate_state *)strm->state; - struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); - struct dfltcc_param_v0 *param = &dfltcc_state->param; + struct dfltcc_deflate_state *dfltcc_state = GET_DFLTCC_DEFLATE_STATE(state); + struct dfltcc_param_v0 *param = &dfltcc_state->common.param; uInt masked_avail_in; dfltcc_cc cc; int need_empty_block; @@ -234,7 +265,7 @@ int Z_INTERNAL PREFIX(dfltcc_deflate)(PREFIX3(streamp) strm, int flush, block_st } while (cc == DFLTCC_CC_AGAIN); /* Translate parameter block to stream */ - strm->msg = oesc_msg(dfltcc_state->msg, param->oesc); + strm->msg = oesc_msg(dfltcc_state->common.msg, param->oesc); state->bi_valid = param->sbb; if (state->bi_valid == 0) state->bi_buf = 0; /* Avoid accessing next_out */ diff --git a/arch/s390/dfltcc_deflate.h b/arch/s390/dfltcc_deflate.h index 15473540c9..d12523017d 100644 --- a/arch/s390/dfltcc_deflate.h +++ b/arch/s390/dfltcc_deflate.h @@ -3,6 +3,9 @@ #include "dfltcc_common.h" +void Z_INTERNAL *PREFIX(dfltcc_alloc_deflate_state)(PREFIX3(streamp)); +void Z_INTERNAL PREFIX(dfltcc_reset_deflate_state)(PREFIX3(streamp)); +void Z_INTERNAL PREFIX(dfltcc_copy_deflate_state)(void *dst, const void *src); int Z_INTERNAL PREFIX(dfltcc_can_deflate)(PREFIX3(streamp) strm); int Z_INTERNAL PREFIX(dfltcc_deflate)(PREFIX3(streamp) strm, int flush, block_state *result); int Z_INTERNAL PREFIX(dfltcc_deflate_params)(PREFIX3(streamp) strm, int level, int strategy, int *flush); @@ -12,6 +15,9 @@ int Z_INTERNAL PREFIX(dfltcc_deflate_set_dictionary)(PREFIX3(streamp) strm, const unsigned char *dictionary, uInt dict_length); int Z_INTERNAL PREFIX(dfltcc_deflate_get_dictionary)(PREFIX3(streamp) strm, unsigned char *dictionary, uInt* dict_length); +#define ZALLOC_DEFLATE_STATE PREFIX(dfltcc_alloc_deflate_state) +#define ZCOPY_DEFLATE_STATE PREFIX(dfltcc_copy_deflate_state) + #define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \ do { \ if (PREFIX(dfltcc_can_deflate)((strm))) \ @@ -24,8 +30,7 @@ int Z_INTERNAL PREFIX(dfltcc_deflate_get_dictionary)(PREFIX3(streamp) strm, unsi return PREFIX(dfltcc_deflate_get_dictionary)((strm), (dict), (dict_len)); \ } while (0) -#define DEFLATE_RESET_KEEP_HOOK(strm) \ - PREFIX(dfltcc_reset)((strm), sizeof(deflate_state)) +#define DEFLATE_RESET_KEEP_HOOK PREFIX(dfltcc_reset_deflate_state) #define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) \ do { \ diff --git a/arch/s390/dfltcc_detail.h b/arch/s390/dfltcc_detail.h index 4ec03f8097..82924231ea 100644 --- a/arch/s390/dfltcc_detail.h +++ b/arch/s390/dfltcc_detail.h @@ -1,6 +1,7 @@ #include #include #include +#include #ifdef HAVE_SYS_SDT_H #include @@ -115,6 +116,29 @@ static inline void clear_bit(char *bits, int n) { bits[n / 8] &= ~(1 << (7 - (n % 8))); } +static inline int is_dfltcc_enabled(void) { + uint64_t facilities[(DFLTCC_FACILITY / 64) + 1]; + Z_REGISTER uint8_t r0 __asm__("r0"); + + memset(facilities, 0, sizeof(facilities)); + r0 = sizeof(facilities) / sizeof(facilities[0]) - 1; + /* STFLE is supported since z9-109 and only in z/Architecture mode. When + * compiling with -m31, gcc defaults to ESA mode, however, since the kernel + * is 64-bit, it's always z/Architecture mode at runtime. + */ + __asm__ volatile( +#ifndef __clang__ + ".machinemode push\n" + ".machinemode zarch\n" +#endif + "stfle %[facilities]\n" +#ifndef __clang__ + ".machinemode pop\n" +#endif + : [facilities] "=Q" (facilities), [r0] "+r" (r0) :: "cc"); + return is_bit_set((const char *)facilities, DFLTCC_FACILITY); +} + #define DFLTCC_FMT0 0 /* @@ -187,13 +211,31 @@ static inline z_const char *oesc_msg(char *buf, int oesc) { struct dfltcc_state { struct dfltcc_param_v0 param; /* Parameter block. */ struct dfltcc_qaf_param af; /* Available functions. */ - uint16_t level_mask; /* Levels on which to use DFLTCC */ - uint32_t block_size; /* New block each X bytes */ - size_t block_threshold; /* New block after total_in > X */ - uint32_t dht_threshold; /* New block only if avail_in >= X */ char msg[64]; /* Buffer for strm->msg */ }; #define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1)) #define GET_DFLTCC_STATE(state) ((struct dfltcc_state *)((char *)(state) + ALIGN_UP(sizeof(*state), 8))) + +static inline void *dfltcc_alloc_state(PREFIX3(streamp) strm, uInt size, uInt extension_size) { + return ZALLOC(strm, 1, ALIGN_UP(size, 8) + extension_size); +} + +static inline void dfltcc_reset_state(struct dfltcc_state *dfltcc_state) { + /* Initialize available functions */ + if (is_dfltcc_enabled()) { + dfltcc(DFLTCC_QAF, &dfltcc_state->param, NULL, NULL, NULL, NULL, NULL); + memmove(&dfltcc_state->af, &dfltcc_state->param, sizeof(dfltcc_state->af)); + } else + memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af)); + + /* Initialize parameter block */ + memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param)); + dfltcc_state->param.nt = 1; + dfltcc_state->param.ribm = DFLTCC_RIBM; +} + +static inline void dfltcc_copy_state(void *dst, const void *src, uInt size, uInt extension_size) { + memcpy(dst, src, ALIGN_UP(size, 8) + extension_size); +} diff --git a/arch/s390/dfltcc_inflate.c b/arch/s390/dfltcc_inflate.c index 99024dc9c5..7a422d97e4 100644 --- a/arch/s390/dfltcc_inflate.c +++ b/arch/s390/dfltcc_inflate.c @@ -20,6 +20,21 @@ #include "dfltcc_inflate.h" #include "dfltcc_detail.h" +struct inflate_state Z_INTERNAL *PREFIX(dfltcc_alloc_inflate_state)(PREFIX3(streamp) strm) { + return (struct inflate_state *)dfltcc_alloc_state(strm, sizeof(struct inflate_state), sizeof(struct dfltcc_state)); +} + +void Z_INTERNAL PREFIX(dfltcc_reset_inflate_state)(PREFIX3(streamp) strm) { + struct inflate_state *state = (struct inflate_state *)strm->state; + struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); + + dfltcc_reset_state(dfltcc_state); +} + +void Z_INTERNAL PREFIX(dfltcc_copy_inflate_state)(struct inflate_state *dst, const struct inflate_state *src) { + dfltcc_copy_state(dst, src, sizeof(struct inflate_state), sizeof(struct dfltcc_state)); +} + int Z_INTERNAL PREFIX(dfltcc_can_inflate)(PREFIX3(streamp) strm) { struct inflate_state *state = (struct inflate_state *)strm->state; struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state); diff --git a/arch/s390/dfltcc_inflate.h b/arch/s390/dfltcc_inflate.h index 69158ef032..5e86fe87f4 100644 --- a/arch/s390/dfltcc_inflate.h +++ b/arch/s390/dfltcc_inflate.h @@ -3,6 +3,9 @@ #include "dfltcc_common.h" +struct inflate_state Z_INTERNAL *PREFIX(dfltcc_alloc_inflate_state)(PREFIX3(streamp) strm); +void Z_INTERNAL PREFIX(dfltcc_reset_inflate_state)(PREFIX3(streamp) strm); +void Z_INTERNAL PREFIX(dfltcc_copy_inflate_state)(struct inflate_state *dst, const struct inflate_state *src); int Z_INTERNAL PREFIX(dfltcc_can_inflate)(PREFIX3(streamp) strm); typedef enum { DFLTCC_INFLATE_CONTINUE, @@ -13,8 +16,10 @@ dfltcc_inflate_action Z_INTERNAL PREFIX(dfltcc_inflate)(PREFIX3(streamp) strm, i int Z_INTERNAL PREFIX(dfltcc_was_inflate_used)(PREFIX3(streamp) strm); int Z_INTERNAL PREFIX(dfltcc_inflate_disable)(PREFIX3(streamp) strm); -#define INFLATE_RESET_KEEP_HOOK(strm) \ - PREFIX(dfltcc_reset)((strm), sizeof(struct inflate_state)) +#define ZALLOC_INFLATE_STATE PREFIX(dfltcc_alloc_inflate_state) +#define ZCOPY_INFLATE_STATE PREFIX(dfltcc_copy_inflate_state) + +#define INFLATE_RESET_KEEP_HOOK PREFIX(dfltcc_reset_inflate_state) #define INFLATE_PRIME_HOOK(strm, bits, value) \ do { if (PREFIX(dfltcc_inflate_disable)((strm))) return Z_STREAM_ERROR; } while (0) diff --git a/deflate.c b/deflate.c index cbf2b1cb4d..a98988a831 100644 --- a/deflate.c +++ b/deflate.c @@ -68,9 +68,9 @@ const char PREFIX(deflate_copyright)[] = " deflate 1.2.11.f Copyright 1995-2016 # include "arch/s390/dfltcc_deflate.h" #else /* Memory management for the deflate state. Useful for allocating arch-specific extension blocks. */ -# define ZALLOC_STATE(strm, items, size) ZALLOC(strm, items, size) +# define ZALLOC_DEFLATE_STATE(strm) ((deflate_state *)ZALLOC(strm, 1, sizeof(deflate_state))) # define ZFREE_STATE(strm, addr) ZFREE(strm, addr) -# define ZCOPY_STATE(dst, src, size) memcpy(dst, src, size) +# define ZCOPY_DEFLATE_STATE(dst, src) memcpy(dst, src, sizeof(deflate_state)) /* Memory management for the window. Useful for allocation the aligned window. */ # define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) # define TRY_FREE_WINDOW(strm, addr) TRY_FREE(strm, addr) @@ -230,7 +230,7 @@ int32_t Z_EXPORT PREFIX(deflateInit2_)(PREFIX3(stream) *strm, int32_t level, int if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC_STATE(strm, 1, sizeof(deflate_state)); + s = ZALLOC_DEFLATE_STATE(strm); if (s == NULL) return Z_MEM_ERROR; strm->state = (struct internal_state *)s; @@ -1024,11 +1024,11 @@ int32_t Z_EXPORT PREFIX(deflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou memcpy((void *)dest, (void *)source, sizeof(PREFIX3(stream))); - ds = (deflate_state *) ZALLOC_STATE(dest, 1, sizeof(deflate_state)); + ds = ZALLOC_DEFLATE_STATE(dest); if (ds == NULL) return Z_MEM_ERROR; dest->state = (struct internal_state *) ds; - ZCOPY_STATE((void *)ds, (void *)ss, sizeof(deflate_state)); + ZCOPY_DEFLATE_STATE(ds, ss); ds->strm = dest; #ifdef X86_PCLMULQDQ_CRC diff --git a/infback.c b/infback.c index c3f0fccc8a..5112a332b4 100644 --- a/infback.c +++ b/infback.c @@ -40,7 +40,7 @@ int32_t Z_EXPORT PREFIX(inflateBackInit_)(PREFIX3(stream) *strm, int32_t windowB } if (strm->zfree == NULL) strm->zfree = zng_cfree; - state = (struct inflate_state *)ZALLOC_STATE(strm, 1, sizeof(struct inflate_state)); + state = ZALLOC_INFLATE_STATE(strm); if (state == NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); diff --git a/inflate.c b/inflate.c index 86f02cc4bf..8ada6466af 100644 --- a/inflate.c +++ b/inflate.c @@ -145,7 +145,7 @@ int32_t Z_EXPORT PREFIX(inflateInit2_)(PREFIX3(stream) *strm, int32_t windowBits } if (strm->zfree == NULL) strm->zfree = zng_cfree; - state = (struct inflate_state *) ZALLOC_STATE(strm, 1, sizeof(struct inflate_state)); + state = ZALLOC_INFLATE_STATE(strm); if (state == NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); @@ -1278,7 +1278,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou state = (struct inflate_state *)source->state; /* allocate space */ - copy = (struct inflate_state *)ZALLOC_STATE(source, 1, sizeof(struct inflate_state)); + copy = ZALLOC_INFLATE_STATE(source); if (copy == NULL) return Z_MEM_ERROR; window = NULL; @@ -1293,7 +1293,7 @@ int32_t Z_EXPORT PREFIX(inflateCopy)(PREFIX3(stream) *dest, PREFIX3(stream) *sou /* copy state */ memcpy((void *)dest, (void *)source, sizeof(PREFIX3(stream))); - ZCOPY_STATE((void *)copy, (void *)state, sizeof(struct inflate_state)); + ZCOPY_INFLATE_STATE(copy, state); copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); diff --git a/inflate_p.h b/inflate_p.h index ecc1060642..a0b6aa8fb5 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -10,9 +10,9 @@ # include "arch/s390/dfltcc_inflate.h" #else /* Memory management for the inflate state. Useful for allocating arch-specific extension blocks. */ -# define ZALLOC_STATE(strm, items, size) ZALLOC(strm, items, size) +# define ZALLOC_INFLATE_STATE(strm) ((struct inflate_state *)ZALLOC(strm, 1, sizeof(struct inflate_state))) # define ZFREE_STATE(strm, addr) ZFREE(strm, addr) -# define ZCOPY_STATE(dst, src, size) memcpy(dst, src, size) +# define ZCOPY_INFLATE_STATE(dst, src) memcpy(dst, src, sizeof(struct inflate_state)) /* Memory management for the window. Useful for allocation the aligned window. */ # define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size) # define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr) From 84f116a3d782b39047b666bc6804e2c0c2138e6d Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Tue, 26 Apr 2022 21:53:30 -0400 Subject: [PATCH 387/798] Fixed regression introduced by inlining CRC + copy Pretty much every time updatewindow has been called, implicitly a checksum was performed unless on s/390 or state->wrap & 4 == 0. The inflateSetDictionary function instead separately calls this checksum before invoking update window and checks the checksum to see if it matches the initial checksum (a property that happens from parsing the DICTID section of the headers). Instead, we can make updatewindow have a "copy" parameter, which is the state->wrap value that is being checked anyway. We instead move the 3rd bit check to be checked by the caller rather than the callee. --- inflate.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/inflate.c b/inflate.c index 8ada6466af..8a48e79334 100644 --- a/inflate.c +++ b/inflate.c @@ -15,7 +15,7 @@ /* function prototypes */ static int inflateStateCheck(PREFIX3(stream) *strm); -static int updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t copy); +static int updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t len, int32_t cksum); static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t len); static inline void inf_chksum_cpy(PREFIX3(stream) *strm, uint8_t *dst, @@ -237,7 +237,7 @@ int Z_INTERNAL PREFIX(inflate_ensure_window)(struct inflate_state *state) { output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t copy) { +static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t len, int32_t cksum) { struct inflate_state *state; uint32_t dist; @@ -245,16 +245,16 @@ static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t if (PREFIX(inflate_ensure_window)(state)) return 1; - /* copy state->wsize or less output bytes into the circular window */ - if (copy >= state->wsize) { + /* len state->wsize or less output bytes into the circular window */ + if (len >= state->wsize) { /* Only do this if the caller specifies to checksum bytes AND the platform requires * it (s/390 being the primary exception to this. Also, for now, do the adler checksums * if not a gzip based header. The inline adler checksums will come in the near future, * possibly the next commit */ - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4)) { + if (INFLATE_NEED_CHECKSUM(strm) && cksum) { /* We have to split the checksum over non-copied and copied bytes */ - if (copy > state->wsize) - inf_chksum(strm, end - copy, copy - state->wsize); + if (len > state->wsize) + inf_chksum(strm, end - len, len - state->wsize); inf_chksum_cpy(strm, state->window, end - state->wsize, state->wsize); } else { memcpy(state->window, end - state->wsize, state->wsize); @@ -266,21 +266,21 @@ static int32_t updatewindow(PREFIX3(stream) *strm, const uint8_t *end, uint32_t dist = state->wsize - state->wnext; /* Only do this if the caller specifies to checksum bytes AND the platform requires * We need to maintain the correct order here for the checksum */ - dist = MIN(dist, copy); - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4)) { - inf_chksum_cpy(strm, state->window + state->wnext, end - copy, dist); + dist = MIN(dist, len); + if (INFLATE_NEED_CHECKSUM(strm) && cksum) { + inf_chksum_cpy(strm, state->window + state->wnext, end - len, dist); } else { - memcpy(state->window + state->wnext, end - copy, dist); + memcpy(state->window + state->wnext, end - len, dist); } - copy -= dist; - if (copy) { - if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4)) { - inf_chksum_cpy(strm, state->window, end - copy, copy); + len -= dist; + if (len) { + if (INFLATE_NEED_CHECKSUM(strm) && cksum) { + inf_chksum_cpy(strm, state->window, end - len, len); } else { - memcpy(state->window, end - copy, copy); + memcpy(state->window, end - len, len); } - state->wnext = copy; + state->wnext = len; state->whave = state->wsize; } else { state->wnext += dist; @@ -1070,7 +1070,8 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { if (INFLATE_NEED_UPDATEWINDOW(strm) && (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH)))) { - if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + /* update sliding window with respective checksum if not in "raw" mode */ + if (updatewindow(strm, strm->next_out, out - strm->avail_out, state->wrap & 4)) { state->mode = MEM; return Z_MEM_ERROR; } @@ -1140,7 +1141,7 @@ int32_t Z_EXPORT PREFIX(inflateSetDictionary)(PREFIX3(stream) *strm, const uint8 /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ - ret = updatewindow(strm, dictionary + dictLength, dictLength); + ret = updatewindow(strm, dictionary + dictLength, dictLength, 0); if (ret) { state->mode = MEM; return Z_MEM_ERROR; From 485bcbdd762470e4ed7adad827dbb25a1da5523d Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 26 Apr 2022 17:21:13 -0700 Subject: [PATCH 388/798] Add test for stream adler after inflateSetDictionary This test passes prior to commit 8550a90de4dcb8589a7d48fe308c4c45bba5a466 ("Leverage inline CRC + copy") and fails after that commit. --- test/test_dict.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_dict.cc b/test/test_dict.cc index 223f0a6cb2..af9662e3de 100644 --- a/test/test_dict.cc +++ b/test/test_dict.cc @@ -72,6 +72,7 @@ TEST(dictionary, basic) { EXPECT_EQ(d_stream.adler, dict_adler); err = PREFIX(inflateSetDictionary)(&d_stream, (const unsigned char*)dictionary, (uint32_t)sizeof(dictionary)); + EXPECT_EQ(d_stream.adler, dict_adler); } EXPECT_EQ(err, Z_OK); } From 7684a733b1052897cdc31843410ac8adc35356f4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Wed, 27 Apr 2022 09:26:31 -0700 Subject: [PATCH 389/798] Fixed MSVC warning about unknown option for AVX512 flag. cl : command line warning D9002: ignoring unknown option '/ARCH:AVX512' --- cmake/detect-intrinsics.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 578a489dff..1ea4ec9418 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -40,7 +40,7 @@ macro(check_avx512_intrinsics) endif() endif() elseif(MSVC) - set(AVX512FLAG "/ARCH:AVX512") + set(AVX512FLAG "/arch:AVX512") endif() # Check whether compiler supports AVX512 intrinsics set(CMAKE_REQUIRED_FLAGS "${AVX512FLAG} ${NATIVEFLAG}") @@ -78,7 +78,7 @@ macro(check_avx512vnni_intrinsics) if(CMAKE_HOST_UNIX OR APPLE) set(AVX512VNNIFLAG "-mavx512f -mavx512bw -mavx512dq -mavx512vl -mavx512vnni") else() - set(AVX512VNNIFLAG "/ARCH:AVX512") + set(AVX512VNNIFLAG "/arch:AVX512") endif() elseif(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") if(NOT NATIVEFLAG) @@ -88,7 +88,7 @@ macro(check_avx512vnni_intrinsics) endif() endif() elseif(MSVC) - set(AVX512VNNIFLAG "/ARCH:AVX512") + set(AVX512VNNIFLAG "/arch:AVX512") endif() # Check whether compiler supports AVX512vnni intrinsics From e123ecdcd2e543b37324e564139e25952a5d5446 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 9 Apr 2022 22:19:56 -0700 Subject: [PATCH 390/798] Added compressBound tests for small buffers. Co-authored-by: Mika T. Lindqvist --- test/CMakeLists.txt | 1 + test/test_compress_bound.cc | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 test/test_compress_bound.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6ebaf7c966..8b250ed780 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,7 @@ set(TEST_SRCS test_aligned_alloc.cc test_compare256.cc test_compress.cc + test_compress_bound.cc test_crc32.cc test_cve-2003-0107.cc test_deflate_bound.cc diff --git a/test/test_compress_bound.cc b/test/test_compress_bound.cc new file mode 100644 index 0000000000..2757fb2cf2 --- /dev/null +++ b/test/test_compress_bound.cc @@ -0,0 +1,59 @@ +/* test_compress_bound.cc - Test compressBound() with small buffers */ + +#include "zbuild.h" +#ifdef ZLIB_COMPAT +# include "zlib.h" +#else +# include "zlib-ng.h" +#endif + +#include +#include +#include +#include + +#include "test_shared.h" + +#include + +#define MAX_LENGTH (32) + +class compress_bound_variant : public testing::TestWithParam { +public: + void estimate(z_size_t level) { + z_size_t estimate_len = 0; + uint8_t *uncompressed = NULL; + uint8_t dest[128]; + int err; + + uncompressed = (uint8_t *)malloc(MAX_LENGTH); + ASSERT_TRUE(uncompressed != NULL); + + /* buffer with values for worst case compression */ + for (int32_t j = 0; j < MAX_LENGTH; j++) { + uncompressed[j] = (uint8_t)j; + } + + for (z_size_t i = 0; i < MAX_LENGTH; i++) { + z_size_t dest_len = sizeof(dest); + + /* calculate actual output length */ + estimate_len = PREFIX(compressBound)(i); + + err = PREFIX(compress2)(dest, &dest_len, uncompressed, i, level); + EXPECT_EQ(err, Z_OK); + EXPECT_GE(estimate_len, dest_len) << + "level: " << level << "\n" << + "length: " << i; + } + + free(uncompressed); + } +}; + +TEST_P(compress_bound_variant, estimate) { + estimate(GetParam()); +} + +INSTANTIATE_TEST_SUITE_P(compress_bound, compress_bound_variant, + testing::Values(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); From afbc9406a64624982c21d11efd8fb84b9bc00cd3 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sat, 9 Apr 2022 22:20:39 -0700 Subject: [PATCH 391/798] Improve deflateBound unit test to test a range of small buffer lengths with various deflateBound initialization values. Co-authored-by: Mika T. Lindqvist --- test/test_deflate_bound.cc | 101 +++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 32 deletions(-) diff --git a/test/test_deflate_bound.cc b/test/test_deflate_bound.cc index d6f576a824..27020c6f92 100644 --- a/test/test_deflate_bound.cc +++ b/test/test_deflate_bound.cc @@ -16,38 +16,75 @@ #include -TEST(deflate, bound) { - PREFIX3(stream) c_stream; - int estimate_len = 0; - uint8_t *out_buf = NULL; - int err; - - memset(&c_stream, 0, sizeof(c_stream)); - - c_stream.avail_in = hello_len; - c_stream.next_in = (z_const unsigned char *)hello; - c_stream.avail_out = 0; - c_stream.next_out = out_buf; - - err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION); - EXPECT_EQ(err, Z_OK); - - /* calculate actual output length and update structure */ - estimate_len = PREFIX(deflateBound)(&c_stream, hello_len); - out_buf = (uint8_t *)malloc(estimate_len); - - if (out_buf != NULL) { - /* update zlib configuration */ - c_stream.avail_out = estimate_len; - c_stream.next_out = out_buf; - - /* do the compression */ - err = PREFIX(deflate)(&c_stream, Z_FINISH); - EXPECT_EQ(err, Z_STREAM_END); - } +#define MAX_LENGTH (32) + +typedef struct { + int32_t level; + int32_t window_size; + int32_t mem_level; +} deflate_bound_test; + +static const deflate_bound_test tests[] = { + {0, MAX_WBITS + 16, 1}, + {Z_BEST_SPEED, MAX_WBITS, MAX_MEM_LEVEL}, + {Z_BEST_COMPRESSION, MAX_WBITS, MAX_MEM_LEVEL} +}; + +class deflate_bound_variant : public testing::TestWithParam { +public: + void estimate(deflate_bound_test param) { + PREFIX3(stream) c_stream; + int estimate_len = 0; + uint8_t *uncompressed = NULL; + uint8_t *out_buf = NULL; + int err; + + uncompressed = (uint8_t *)malloc(MAX_LENGTH); + ASSERT_TRUE(uncompressed != NULL); + memset(uncompressed, 'a', MAX_LENGTH); + + for (int32_t i = 0; i < MAX_LENGTH; i++) { + memset(&c_stream, 0, sizeof(c_stream)); + + c_stream.avail_in = i; + c_stream.next_in = (z_const unsigned char *)uncompressed; + c_stream.avail_out = 0; + c_stream.next_out = out_buf; + + err = PREFIX(deflateInit2)(&c_stream, param.level, Z_DEFLATED, + param.window_size, param.mem_level, Z_DEFAULT_STRATEGY); + EXPECT_EQ(err, Z_OK); - err = PREFIX(deflateEnd)(&c_stream); - EXPECT_EQ(err, Z_OK); + /* calculate actual output length and update structure */ + estimate_len = PREFIX(deflateBound)(&c_stream, i); + out_buf = (uint8_t *)malloc(estimate_len); - free(out_buf); + if (out_buf != NULL) { + /* update zlib configuration */ + c_stream.avail_out = estimate_len; + c_stream.next_out = out_buf; + + /* do the compression */ + err = PREFIX(deflate)(&c_stream, Z_FINISH); + EXPECT_EQ(err, Z_STREAM_END) << + "level: " << param.level << "\n" << + "window_size: " << param.window_size << "\n" << + "mem_level: " << param.mem_level << "\n" << + "length: " << i; + + free(out_buf); + } + + err = PREFIX(deflateEnd)(&c_stream); + EXPECT_EQ(err, Z_OK); + } + + free(uncompressed); + } +}; + +TEST_P(deflate_bound_variant, estimate) { + estimate(GetParam()); } + +INSTANTIATE_TEST_SUITE_P(deflate_bound, deflate_bound_variant, testing::ValuesIn(tests)); From 4422a6ba2eeab4edc4e35b600ade0488e3e7a92c Mon Sep 17 00:00:00 2001 From: Mika Lindqvist Date: Tue, 3 May 2022 03:47:52 +0300 Subject: [PATCH 392/798] Disable redirection to 64-bit function variants when Z_SOLO is defined See #1262. --- zlib.h.in | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/zlib.h.in b/zlib.h.in index d170e25c9c..5dcba8e944 100644 --- a/zlib.h.in +++ b/zlib.h.in @@ -1803,7 +1803,7 @@ Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ #endif #endif -#if !defined(Z_INTERNAL) && defined(Z_WANT64) +#if !defined(Z_SOLO) && !defined(Z_INTERNAL) && defined(Z_WANT64) # define @ZLIB_SYMBOL_PREFIX@gzopen @ZLIB_SYMBOL_PREFIX@gzopen64 # define @ZLIB_SYMBOL_PREFIX@gzseek @ZLIB_SYMBOL_PREFIX@gzseek64 # define @ZLIB_SYMBOL_PREFIX@gztell @ZLIB_SYMBOL_PREFIX@gztell64 @@ -1821,13 +1821,15 @@ Z_EXTERN int Z_EXPORT gzgetc_(gzFile file); /* backward compatibility */ Z_EXTERN void Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen64(uint32_t *op, z_off64_t); # endif #else - Z_EXTERN gzFile Z_EXPORT gzopen(const char *, const char *); - Z_EXTERN z_off_t Z_EXPORT gzseek(gzFile, z_off_t, int); - Z_EXTERN z_off_t Z_EXPORT gztell(gzFile); - Z_EXTERN z_off_t Z_EXPORT gzoffset(gzFile); - Z_EXTERN unsigned long Z_EXPORT adler32_combine(unsigned long, unsigned long, z_off_t); - Z_EXTERN unsigned long Z_EXPORT crc32_combine(unsigned long, unsigned long, z_off_t); - Z_EXTERN void Z_EXPORT crc32_combine_gen(uint32_t *op, z_off_t); +# ifndef Z_SOLO + Z_EXTERN gzFile Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzopen(const char *, const char *); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzseek(gzFile, z_off_t, int); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gztell(gzFile); + Z_EXTERN z_off_t Z_EXPORT @ZLIB_SYMBOL_PREFIX@gzoffset(gzFile); +# endif + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@adler32_combine(unsigned long, unsigned long, z_off_t); + Z_EXTERN unsigned long Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine(unsigned long, unsigned long, z_off_t); + Z_EXTERN void Z_EXPORT @ZLIB_SYMBOL_PREFIX@crc32_combine_gen(uint32_t *op, z_off_t); #endif /* undocumented functions */ From 3e6fce5f709fb346c77b14d744a72c53122284e4 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 3 May 2022 15:40:44 -0700 Subject: [PATCH 393/798] Remove unused chunkmemset_1 code. --- arch/arm/chunkset_neon.c | 5 ----- arch/power/chunkset_power8.c | 5 ----- arch/x86/chunkset_avx.c | 5 ----- arch/x86/chunkset_sse2.c | 5 ----- chunkset.c | 5 ----- 5 files changed, 25 deletions(-) diff --git a/arch/arm/chunkset_neon.c b/arch/arm/chunkset_neon.c index 2ca8ce07e5..e2b9b8be4b 100644 --- a/arch/arm/chunkset_neon.c +++ b/arch/arm/chunkset_neon.c @@ -14,15 +14,10 @@ typedef uint8x16_t chunk_t; #define CHUNK_SIZE 16 -#define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 #define HAVE_CHUNKMEMSET_8 -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { - *chunk = vld1q_dup_u8(from); -} - static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { uint16_t tmp; zmemcpy_2(&tmp, from); diff --git a/arch/power/chunkset_power8.c b/arch/power/chunkset_power8.c index 52734cb2df..5db782144d 100644 --- a/arch/power/chunkset_power8.c +++ b/arch/power/chunkset_power8.c @@ -10,15 +10,10 @@ typedef vector unsigned char chunk_t; #define CHUNK_SIZE 16 -#define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 #define HAVE_CHUNKMEMSET_8 -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { - *chunk = vec_splats(*from); -} - static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { uint16_t tmp; zmemcpy_2(&tmp, from); diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index ff5d3c61e3..6643b04683 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -10,15 +10,10 @@ typedef __m256i chunk_t; #define CHUNK_SIZE 32 -#define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 #define HAVE_CHUNKMEMSET_8 -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { - *chunk = _mm256_set1_epi8(*(int8_t *)from); -} - static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { int16_t tmp; zmemcpy_2(&tmp, from); diff --git a/arch/x86/chunkset_sse2.c b/arch/x86/chunkset_sse2.c index 778e4ca14a..be195cf73c 100644 --- a/arch/x86/chunkset_sse2.c +++ b/arch/x86/chunkset_sse2.c @@ -11,15 +11,10 @@ typedef __m128i chunk_t; #define CHUNK_SIZE 16 -#define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 #define HAVE_CHUNKMEMSET_8 -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { - *chunk = _mm_set1_epi8(*(int8_t *)from); -} - static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { int16_t tmp; zmemcpy_2(&tmp, from); diff --git a/chunkset.c b/chunkset.c index 14c913ee6a..96684f4707 100644 --- a/chunkset.c +++ b/chunkset.c @@ -8,14 +8,9 @@ typedef uint64_t chunk_t; #define CHUNK_SIZE 8 -#define HAVE_CHUNKMEMSET_1 #define HAVE_CHUNKMEMSET_4 #define HAVE_CHUNKMEMSET_8 -static inline void chunkmemset_1(uint8_t *from, chunk_t *chunk) { - memset(chunk, *from, sizeof(chunk_t)); -} - static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { uint8_t *dest = (uint8_t *)chunk; zmemcpy_4(dest, from); From f8a7f264cfa2b2bd7e9486ba107e861504d9c170 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 3 May 2022 11:12:46 -0700 Subject: [PATCH 394/798] Fixed warning about strict prototypes for cpu_check_features. --- cpu_features.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpu_features.h b/cpu_features.h index 81e13a3c8e..4dcf8e5908 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -19,7 +19,7 @@ # include "arch/s390/s390_features.h" #endif -extern void cpu_check_features(); +extern void cpu_check_features(void); /* adler32 */ typedef uint32_t (*adler32_func)(uint32_t adler, const unsigned char *buf, size_t len); From 48f346e806ff9c9fd4cb45c57191f972d5a56c35 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Sun, 17 Apr 2022 18:47:07 -0700 Subject: [PATCH 395/798] Implement neon version of compare256. Co-authored-by: Adam Stylinski --- CMakeLists.txt | 5 ++- README.md | 2 +- arch/arm/Makefile.in | 7 +++ arch/arm/compare256_neon.c | 60 +++++++++++++++++++++++++ configure | 31 ++++++++----- cpu_features.h | 9 ++++ functable.c | 8 ++++ test/benchmarks/benchmark_compare256.cc | 3 ++ test/test_compare256.cc | 3 ++ win32/Makefile.a64 | 3 +- win32/Makefile.arm | 3 +- 11 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 arch/arm/compare256_neon.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f0b0880889..ed438f79a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -601,8 +601,9 @@ if(WITH_OPTIM) if(WITH_NEON) check_neon_compiler_flag() if(MFPU_NEON_AVAILABLE) - add_definitions(-DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) - set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c ${ARCHDIR}/slide_hash_neon.c) + add_definitions(-DARM_NEON -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH) + set(NEON_SRCS ${ARCHDIR}/adler32_neon.c ${ARCHDIR}/chunkset_neon.c + ${ARCHDIR}/compare256_neon.c ${ARCHDIR}/slide_hash_neon.c) list(APPEND ZLIB_ARCH_SRCS ${NEON_SRCS}) set_property(SOURCE ${NEON_SRCS} PROPERTY COMPILE_FLAGS "${NEONFLAG} ${NOLTOFLAG}") if(MSVC) diff --git a/README.md b/README.md index e02e04b316..40ad1f858d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Features * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, ACLE, & IBM Z * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX - * Compare256 implementations using SSE2 & AVX2 + * Compare256 implementations using SSE2, AVX2, & Neon * Inflate chunk copying using SSE2, AVX, Neon & VSX * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements diff --git a/arch/arm/Makefile.in b/arch/arm/Makefile.in index f47325c231..abf6193fc0 100644 --- a/arch/arm/Makefile.in +++ b/arch/arm/Makefile.in @@ -20,6 +20,7 @@ all: \ adler32_neon.o adler32_neon.lo \ arm_features.o arm_features.lo \ chunkset_neon.o chunkset_neon.lo \ + compare256_neon.o compare256_neon.lo \ crc32_acle.o crc32_acle.lo \ slide_hash_neon.o slide_hash_neon.lo \ insert_string_acle.o insert_string_acle.lo @@ -42,6 +43,12 @@ chunkset_neon.o: chunkset_neon.lo: $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_neon.c +compare256_neon.o: + $(CC) $(CFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_neon.c + +compare256_neon.lo: + $(CC) $(SFLAGS) $(NEONFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_neon.c + crc32_acle.o: $(CC) $(CFLAGS) $(ACLEFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_acle.c diff --git a/arch/arm/compare256_neon.c b/arch/arm/compare256_neon.c new file mode 100644 index 0000000000..53a088cc00 --- /dev/null +++ b/arch/arm/compare256_neon.c @@ -0,0 +1,60 @@ +/* compare256_neon.c - NEON version of compare256 + * Copyright (C) 2022 Nathan Moinvaziri + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +#ifdef _M_ARM64 +# include +#else +# include +#endif +#include "../../zbuild.h" + +static inline uint32_t compare256_neon_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0; + + do { + uint8x16_t a, b, cmp; + uint64_t lane; + + a = vld1q_u8(src0); + b = vld1q_u8(src1); + + cmp = veorq_u8(a, b); + + lane = vgetq_lane_u64(vreinterpretq_u64_u8(cmp), 0); + if (lane) { + uint32_t match_byte = (uint32_t)__builtin_ctzll(lane) / 8; + return len + match_byte; + } + len += 8; + lane = vgetq_lane_u64(vreinterpretq_u64_u8(cmp), 1); + if (lane) { + uint32_t match_byte = (uint32_t)__builtin_ctzll(lane) / 8; + return len + match_byte; + } + len += 8; + + src0 += 16, src1 += 16; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_neon(const uint8_t *src0, const uint8_t *src1) { + return compare256_neon_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_neon +#define COMPARE256 compare256_neon_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_neon +#define COMPARE256 compare256_neon_static + +#include "match_tpl.h" + +#endif diff --git a/configure b/configure index a357e1c8aa..836e03072b 100755 --- a/configure +++ b/configure @@ -1659,7 +1659,10 @@ EOF fi if test $buildneon -eq 1; then - if test $MFPU_NEON_AVAILABLE -eq 1;then + CFLAGS="${CFLAGS} -DARM_NEON" + SFLAGS="${SFLAGS} -DARM_NEON" + + if test $MFPU_NEON_AVAILABLE -eq 1; then neonflag="-mfpu=neon" fi @@ -1671,8 +1674,8 @@ EOF CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_hash_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_hash_neon.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi fi ;; @@ -1683,6 +1686,9 @@ EOF fi if test $buildneon -eq 1; then + CFLAGS="${CFLAGS} -DARM_NEON" + SFLAGS="${SFLAGS} -DARM_NEON" + if test $MFPU_NEON_AVAILABLE -eq 1;then neonflag="-mfpu=neon" fi @@ -1695,8 +1701,8 @@ EOF CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_hash_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_hash_neon.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi fi ;; @@ -1713,6 +1719,9 @@ EOF fi if test $buildneon -eq 1; then + CFLAGS="${CFLAGS} -DARM_NEON" + SFLAGS="${SFLAGS} -DARM_NEON" + if test $MFPU_NEON_AVAILABLE -eq 1;then neonflag="-mfpu=neon" fi @@ -1725,8 +1734,8 @@ EOF CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_hash_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_hash_neon.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi fi ;; @@ -1786,10 +1795,10 @@ EOF if test $native -eq 0; then ARCH="${ARCH}+simd" fi - CFLAGS="${CFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - SFLAGS="${SFLAGS} -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o slide_hash_neon.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo slide_hash_neon.lo" + CFLAGS="${CFLAGS} -DARM_NEON -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" + SFLAGS="${SFLAGS} -DARM_NEON -DARM_NEON_ADLER32 -DARM_NEON_CHUNKSET -DARM_NEON_SLIDEHASH" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_neon.o chunkset_neon.o compare256_neon.o slide_hash_neon.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_neon.lo chunkset_neon.lo compare256_neon.lo slide_hash_neon.lo" fi fi diff --git a/cpu_features.h b/cpu_features.h index 4dcf8e5908..504c6a93e7 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -127,6 +127,9 @@ extern uint32_t compare256_sse2(const uint8_t *src0, const uint8_t *src1); #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) extern uint32_t compare256_avx2(const uint8_t *src0, const uint8_t *src1); #endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +extern uint32_t compare256_neon(const uint8_t *src0, const uint8_t *src1); +#endif #ifdef DEFLATE_H_ /* insert_string */ @@ -154,6 +157,9 @@ extern uint32_t longest_match_sse2(deflate_state *const s, Pos cur_match); #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) extern uint32_t longest_match_avx2(deflate_state *const s, Pos cur_match); #endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +extern uint32_t longest_match_neon(deflate_state *const s, Pos cur_match); +#endif /* longest_match_slow */ extern uint32_t longest_match_slow_c(deflate_state *const s, Pos cur_match); @@ -170,6 +176,9 @@ extern uint32_t longest_match_slow_sse2(deflate_state *const s, Pos cur_match); #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) extern uint32_t longest_match_slow_avx2(deflate_state *const s, Pos cur_match); #endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +extern uint32_t longest_match_slow_neon(deflate_state *const s, Pos cur_match); +#endif /* quick_insert_string */ extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); diff --git a/functable.c b/functable.c index 68aef1d338..74381e1589 100644 --- a/functable.c +++ b/functable.c @@ -117,6 +117,10 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { if (x86_cpu_has_avx2) functable.longest_match = &longest_match_avx2; #endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) + if (arm_cpu_has_neon) + functable.longest_match = &longest_match_neon; +#endif return functable.longest_match(s, cur_match); } @@ -142,6 +146,10 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc if (x86_cpu_has_avx2) functable.longest_match_slow = &longest_match_slow_avx2; #endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) + if (arm_cpu_has_neon) + functable.longest_match_slow = &longest_match_slow_neon; +#endif return functable.longest_match_slow(s, cur_match); } diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index cc1ee5c19a..c579d9ac81 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -76,3 +76,6 @@ BENCHMARK_COMPARE256(sse2, compare256_sse2, x86_cpu_has_sse2); #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) BENCHMARK_COMPARE256(avx2, compare256_avx2, x86_cpu_has_avx2); #endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +BENCHMARK_COMPARE256(neon, compare256_neon, arm_cpu_has_neon); +#endif diff --git a/test/test_compare256.cc b/test/test_compare256.cc index c252cfada7..61c6e19bcc 100644 --- a/test/test_compare256.cc +++ b/test/test_compare256.cc @@ -72,3 +72,6 @@ TEST_COMPARE256(sse2, compare256_sse2, x86_cpu_has_sse2) #if defined(X86_AVX2) && defined(HAVE_BUILTIN_CTZ) TEST_COMPARE256(avx2, compare256_avx2, x86_cpu_has_avx2) #endif +#if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) +TEST_COMPARE256(neon, compare256_neon, arm_cpu_has_neon) +#endif diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index 29e66ceed1..b0d7993d54 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -93,12 +93,13 @@ OBJS = $(OBJS) gzlib.obj gzread.obj gzwrite.obj WFLAGS = $(WFLAGS) \ -DARM_ACLE_CRC_HASH \ -D__ARM_NEON__=1 \ + -DARM_NEON \ -DARM_NEON_ADLER32 \ -DARM_NEON_CHUNKSET \ -DARM_NEON_SLIDEHASH \ -DARM_NOCHECK_NEON \ # -OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj adler32_neon.obj chunkset_neon.obj slide_hash_neon.obj +OBJS = $(OBJS) crc32_acle.obj insert_string_acle.obj adler32_neon.obj chunkset_neon.obj compare256_neon.obj slide_hash_neon.obj # targets all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ diff --git a/win32/Makefile.arm b/win32/Makefile.arm index a43dc59b1c..14df718d84 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -105,12 +105,13 @@ NEON_ARCH = /arch:VFPv3 CFLAGS = $(CFLAGS) $(NEON_ARCH) WFLAGS = $(WFLAGS) \ -D__ARM_NEON__=1 \ + -DARM_NEON \ -DARM_NEON_ADLER32 \ -DARM_NEON_CHUNKSET \ -DARM_NEON_SLIDEHASH \ -DARM_NOCHECK_NEON \ # -OBJS = $(OBJS) adler32_neon.obj chunkset_neon.obj slide_hash_neon.obj +OBJS = $(OBJS) adler32_neon.obj chunkset_neon.obj compare256_neon.obj slide_hash_neon.obj !endif # targets From d45b27a4896d0c02d13950f91dd032dce1836128 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 5 May 2022 16:51:17 +0500 Subject: [PATCH 396/798] The names CMAKE_INTERPROCEDURAL_OPTIMIZATION_* must be uppercase. Signed-off-by: Vladislav Shchapov --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed438f79a2..5b01f451de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -255,7 +255,8 @@ endif() if(NOT WITH_NATIVE_INSTRUCTIONS) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) foreach(_cfg_name IN LISTS CMAKE_CONFIGURATION_TYPES) - set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_${_cfg_name} OFF) + string(TOUPPER "${_cfg_name}" _cfg_name_uc) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_${_cfg_name_uc} OFF) endforeach() endif() From 02d10b252cc54159f7c33823048daec4b023fb22 Mon Sep 17 00:00:00 2001 From: Matheus Castanho Date: Sat, 16 Apr 2022 17:12:53 -0700 Subject: [PATCH 397/798] Implement power9 version of compare256. Co-authored-by: Nathan Moinvaziri --- CMakeLists.txt | 19 ++++++- README.md | 2 +- arch/power/Makefile.in | 9 ++++ arch/power/compare256_power9.c | 66 +++++++++++++++++++++++++ arch/power/power_features.c | 3 ++ arch/power/power_features.h | 1 + cmake/detect-intrinsics.cmake | 17 +++++++ configure | 26 +++++++++- cpu_features.h | 9 ++++ functable.c | 12 +++++ test/benchmarks/benchmark_compare256.cc | 3 ++ test/test_compare256.cc | 3 ++ 12 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 arch/power/compare256_power9.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b01f451de..6c45fd8446 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,7 @@ if(BASEARCH_ARM_FOUND) elseif(BASEARCH_PPC_FOUND) option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON) option(WITH_POWER8 "Build with optimisations for POWER8" ON) + option(WITH_POWER9 "Build with optimisations for POWER9" ON) elseif(BASEARCH_S360_FOUND) option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF) option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF) @@ -138,6 +139,7 @@ mark_as_advanced(FORCE WITH_PCLMULQDQ WITH_ALTIVEC WITH_POWER8 + WITH_POWER9 WITH_INFLATE_STRICT WITH_INFLATE_ALLOW_INVALID_DIST WITH_UNALIGNED @@ -628,7 +630,10 @@ if(WITH_OPTIM) if(WITH_POWER8) check_power8_intrinsics() endif() - if(HAVE_VMX OR HAVE_POWER8_INTRIN) + if(WITH_POWER9) + check_power9_intrinsics() + endif() + if(HAVE_VMX OR HAVE_POWER8_INTRIN OR HAVE_POWER9_INTRIN) list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/power_features.h) list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/power_features.c) endif() @@ -667,6 +672,17 @@ if(WITH_OPTIM) set(WITH_POWER8 OFF) endif() endif() + # Power9 specific options and files + if(WITH_POWER9) + if(HAVE_POWER9_INTRIN) + add_definitions(-DPOWER9) + set(POWER9_SRCS ${ARCHDIR}/compare256_power9.c) + list(APPEND ZLIB_ARCH_SRCS ${POWER9_SRCS}) + set_property(SOURCE ${POWER9_SRCS} PROPERTY COMPILE_FLAGS "${POWER9FLAG} ${NOLTOFLAG}") + else() + set(WITH_POWER9 OFF) + endif() + endif() elseif(BASEARCH_S360_FOUND) check_s390_intrinsics() if(HAVE_S390_INTRIN) @@ -1463,6 +1479,7 @@ if(BASEARCH_ARM_FOUND) elseif(BASEARCH_PPC_FOUND) add_feature_info(WITH_ALTIVEC WITH_ALTIVEC "Build with AltiVec optimisations") add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8") + add_feature_info(WITH_POWER9 WITH_POWER9 "Build with optimisations for POWER9") elseif(BASEARCH_S360_FOUND) add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z") add_feature_info(WITH_DFLTCC_INFLATE WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z") diff --git a/README.md b/README.md index 40ad1f858d..0dd1b1c37e 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Features * CRC32-B implementation using PCLMULQDQ, VPCLMULQDQ, ACLE, & IBM Z * Hash table implementation using CRC32-C intrinsics on x86 and ARM * Slide hash implementations using SSE2, AVX2, Neon, VMX & VSX - * Compare256 implementations using SSE2, AVX2, & Neon + * Compare256 implementations using SSE2, AVX2, Neon, & POWER9 * Inflate chunk copying using SSE2, AVX, Neon & VSX * Support for hardware-accelerated deflate using IBM Z DFLTCC * Unaligned memory read/writes and large bit buffer improvements diff --git a/arch/power/Makefile.in b/arch/power/Makefile.in index ca0e2ba9ca..e9be6dddba 100644 --- a/arch/power/Makefile.in +++ b/arch/power/Makefile.in @@ -10,6 +10,7 @@ INCLUDES= SUFFIX= P8FLAGS=-mcpu=power8 +P9FLAGS=-mcpu=power9 PPCFLAGS=-maltivec NOLTOFLAG= @@ -25,6 +26,8 @@ all: power_features.o \ adler32_vmx.lo \ chunkset_power8.o \ chunkset_power8.lo \ + compare256_power9.o \ + compare256_power9.lo \ crc32_power8.o \ crc32_power8.lo \ slide_hash_power8.o \ @@ -56,6 +59,12 @@ chunkset_power8.o: chunkset_power8.lo: $(CC) $(SFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_power8.c +compare256_power9.o: + $(CC) $(CFLAGS) $(P9FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_power9.c + +compare256_power9.lo: + $(CC) $(SFLAGS) $(P9FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_power9.c + crc32_power8.o: $(CC) $(CFLAGS) $(P8FLAGS) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/crc32_power8.c diff --git a/arch/power/compare256_power9.c b/arch/power/compare256_power9.c new file mode 100644 index 0000000000..9b3e617014 --- /dev/null +++ b/arch/power/compare256_power9.c @@ -0,0 +1,66 @@ +/* compare256_power9.c - Power9 version of compare256 + * Copyright (C) 2019 Matheus Castanho , IBM + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef POWER9 +#include +#include "../../zbuild.h" +#include "../../zendian.h" + +/* Older versions of GCC misimplemented semantics for these bit counting builtins. + * https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=3f30f2d1dbb3228b8468b26239fe60c2974ce2ac */ +#if defined(__GNUC__) && (__GNUC__ < 12) +# define zng_vec_vctzlsbb(vc, len) __asm__ volatile("vctzlsbb %0, %1\n\t" : "=r" (len) : "v" (vc)) +# define zng_vec_vclzlsbb(vc, len) __asm__ volatile("vclzlsbb %0, %1\n\t" : "=r" (len) : "v" (vc)) +#else +# define zng_vec_vctzlsbb(vc, len) len = __builtin_vec_vctzlsbb(vc) +# define zng_vec_vclzlsbb(vc, len) len = __builtin_vec_vclzlsbb(vc) +#endif + +static inline uint32_t compare256_power9_static(const uint8_t *src0, const uint8_t *src1) { + uint32_t len = 0, cmplen; + + do { + vector unsigned char vsrc0, vsrc1, vc; + + vsrc0 = *((vector unsigned char *)src0); + vsrc1 = *((vector unsigned char *)src1); + + /* Compare 16 bytes at a time. Each byte of vc will be either + * all ones or all zeroes, depending on the result of the comparison. */ + vc = (vector unsigned char)vec_cmpne(vsrc0, vsrc1); + + /* Since the index of matching bytes will contain only zeroes + * on vc (since we used cmpne), counting the number of consecutive + * bytes where LSB == 0 is the same as counting the length of the match. */ +#if BYTE_ORDER == LITTLE_ENDIAN + zng_vec_vctzlsbb(vc, cmplen); +#else + zng_vec_vclzlsbb(vc, cmplen); +#endif + if (cmplen != 16) + return len + cmplen; + + src0 += 16, src1 += 16, len += 16; + } while (len < 256); + + return 256; +} + +Z_INTERNAL uint32_t compare256_power9(const uint8_t *src0, const uint8_t *src1) { + return compare256_power9_static(src0, src1); +} + +#define LONGEST_MATCH longest_match_power9 +#define COMPARE256 compare256_power9_static + +#include "match_tpl.h" + +#define LONGEST_MATCH_SLOW +#define LONGEST_MATCH longest_match_slow_power9 +#define COMPARE256 compare256_power9_static + +#include "match_tpl.h" + +#endif diff --git a/arch/power/power_features.c b/arch/power/power_features.c index 65599d9a79..7c0350c66e 100644 --- a/arch/power/power_features.c +++ b/arch/power/power_features.c @@ -12,6 +12,7 @@ Z_INTERNAL int power_cpu_has_altivec = 0; Z_INTERNAL int power_cpu_has_arch_2_07 = 0; +Z_INTERNAL int power_cpu_has_arch_3_00 = 0; void Z_INTERNAL power_check_features(void) { #ifdef PPC_FEATURES @@ -28,5 +29,7 @@ void Z_INTERNAL power_check_features(void) { if (hwcap2 & PPC_FEATURE2_ARCH_2_07) power_cpu_has_arch_2_07 = 1; + if (hwcap2 & PPC_FEATURE2_ARCH_3_00) + power_cpu_has_arch_3_00 = 1; #endif } diff --git a/arch/power/power_features.h b/arch/power/power_features.h index 077bec1158..8df9f9e958 100644 --- a/arch/power/power_features.h +++ b/arch/power/power_features.h @@ -9,6 +9,7 @@ extern int power_cpu_has_altivec; extern int power_cpu_has_arch_2_07; +extern int power_cpu_has_arch_3_00; void Z_INTERNAL power_check_features(void); diff --git a/cmake/detect-intrinsics.cmake b/cmake/detect-intrinsics.cmake index 1ea4ec9418..c638b3bc26 100644 --- a/cmake/detect-intrinsics.cmake +++ b/cmake/detect-intrinsics.cmake @@ -316,6 +316,23 @@ macro(check_s390_intrinsics) ) endmacro() +macro(check_power9_intrinsics) + if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if(NOT NATIVEFLAG) + set(POWER9FLAG "-mcpu=power9") + endif() + endif() + # Check if we have what we need for POWER9 optimizations + set(CMAKE_REQUIRED_FLAGS "${POWER9FLAG} ${NATIVEFLAG}") + check_c_source_compiles( + "int main() { + return 0; + }" + HAVE_POWER9_INTRIN + ) + set(CMAKE_REQUIRED_FLAGS) +endmacro() + macro(check_sse2_intrinsics) if(CMAKE_C_COMPILER_ID MATCHES "Intel") if(CMAKE_HOST_UNIX OR APPLE) diff --git a/configure b/configure index 836e03072b..ff657e698f 100755 --- a/configure +++ b/configure @@ -95,6 +95,7 @@ buildvpclmulqdq=1 buildacle=1 buildaltivec=1 buildpower8=1 +buildpower9=1 buildneon=1 builddfltccdeflate=0 builddfltccinflate=0 @@ -202,6 +203,7 @@ case "$1" in --without-neon) buildneon=0; shift ;; --without-altivec) buildaltivec=0 ; shift ;; --without-power8) buildpower8=0 ; shift ;; + --without-power9) buildpower9=0 ; shift ;; --with-dfltcc-deflate) builddfltccdeflate=1; shift ;; --with-dfltcc-inflate) builddfltccinflate=1; shift ;; --without-crc32-vx) buildcrc32vx=0; shift ;; @@ -1227,7 +1229,7 @@ EOF } check_power8_intrinsics() { - # Check whether features needed by POWER optimisations are available + # Check whether features needed by POWER8 optimisations are available cat > $test.c << EOF #include int main() { return (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07); } @@ -1241,6 +1243,20 @@ EOF fi } +check_power9_intrinsics() { + # Check whether features needed by POWER9 optimisations are available + cat > $test.c << EOF +int main() { return 0; } +EOF + if test $buildpower9 -eq 1 && try $CC -c $CFLAGS -mcpu=power9 $test.c; then + HAVE_POWER9_INTRIN=1 + echo "Check whether POWER9 instructions are available ... Yes." | tee -a configure.log + else + HAVE_POWER9_INTRIN=0 + echo "Check whether POWER9 instructions are available ... No." | tee -a configure.log + fi +} + check_sse2_intrinsics() { # Check whether compiler supports SSE2 intrinsics cat > $test.c << EOF @@ -1824,6 +1840,7 @@ EOF check_ppc_intrinsics check_power8_intrinsics + check_power9_intrinsics if test $HAVE_VMX -eq 1; then CFLAGS="${CFLAGS} -DPPC_FEATURES" @@ -1855,6 +1872,13 @@ EOF ;; esac fi + if test $HAVE_POWER9_INTRIN -eq 1; then + CFLAGS="${CFLAGS} -DPOWER9 -DPOWER_FEATURES" + SFLAGS="${SFLAGS} -DPOWER9 -DPOWER_FEATURES" + + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} compare256_power9.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} compare256_power9.lo" + fi fi ;; s390x) diff --git a/cpu_features.h b/cpu_features.h index 504c6a93e7..861ae0c4d8 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -130,6 +130,9 @@ extern uint32_t compare256_avx2(const uint8_t *src0, const uint8_t *src1); #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) extern uint32_t compare256_neon(const uint8_t *src0, const uint8_t *src1); #endif +#ifdef POWER9 +extern uint32_t compare256_power9(const uint8_t *src0, const uint8_t *src1); +#endif #ifdef DEFLATE_H_ /* insert_string */ @@ -160,6 +163,9 @@ extern uint32_t longest_match_avx2(deflate_state *const s, Pos cur_match); #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) extern uint32_t longest_match_neon(deflate_state *const s, Pos cur_match); #endif +#ifdef POWER9 +extern uint32_t longest_match_power9(deflate_state *const s, Pos cur_match); +#endif /* longest_match_slow */ extern uint32_t longest_match_slow_c(deflate_state *const s, Pos cur_match); @@ -179,6 +185,9 @@ extern uint32_t longest_match_slow_avx2(deflate_state *const s, Pos cur_match); #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) extern uint32_t longest_match_slow_neon(deflate_state *const s, Pos cur_match); #endif +#ifdef POWER9 +extern uint32_t longest_match_slow_power9(deflate_state *const s, Pos cur_match); +#endif /* quick_insert_string */ extern Pos quick_insert_string_c(deflate_state *const s, const uint32_t str); diff --git a/functable.c b/functable.c index 74381e1589..64992bc7be 100644 --- a/functable.c +++ b/functable.c @@ -121,6 +121,10 @@ Z_INTERNAL uint32_t longest_match_stub(deflate_state *const s, Pos cur_match) { if (arm_cpu_has_neon) functable.longest_match = &longest_match_neon; #endif +#ifdef POWER9 + if (power_cpu_has_arch_3_00) + functable.longest_match = &longest_match_power9; +#endif return functable.longest_match(s, cur_match); } @@ -150,6 +154,10 @@ Z_INTERNAL uint32_t longest_match_slow_stub(deflate_state *const s, Pos cur_matc if (arm_cpu_has_neon) functable.longest_match_slow = &longest_match_slow_neon; #endif +#ifdef POWER9 + if (power_cpu_has_arch_3_00) + functable.longest_match_slow = &longest_match_slow_power9; +#endif return functable.longest_match_slow(s, cur_match); } @@ -410,6 +418,10 @@ Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { if (x86_cpu_has_avx2) functable.compare256 = &compare256_avx2; #endif +#ifdef POWER9 + if (power_cpu_has_arch_3_00) + functable.compare256 = &compare256_power9; +#endif return functable.compare256(src0, src1); } diff --git a/test/benchmarks/benchmark_compare256.cc b/test/benchmarks/benchmark_compare256.cc index c579d9ac81..54459dad06 100644 --- a/test/benchmarks/benchmark_compare256.cc +++ b/test/benchmarks/benchmark_compare256.cc @@ -79,3 +79,6 @@ BENCHMARK_COMPARE256(avx2, compare256_avx2, x86_cpu_has_avx2); #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) BENCHMARK_COMPARE256(neon, compare256_neon, arm_cpu_has_neon); #endif +#ifdef POWER9 +BENCHMARK_COMPARE256(power9, compare256_power9, power_cpu_has_arch_3_00); +#endif diff --git a/test/test_compare256.cc b/test/test_compare256.cc index 61c6e19bcc..7c4dab9899 100644 --- a/test/test_compare256.cc +++ b/test/test_compare256.cc @@ -75,3 +75,6 @@ TEST_COMPARE256(avx2, compare256_avx2, x86_cpu_has_avx2) #if defined(ARM_NEON) && defined(HAVE_BUILTIN_CTZLL) TEST_COMPARE256(neon, compare256_neon, arm_cpu_has_neon) #endif +#ifdef POWER9 +TEST_COMPARE256(power9, compare256_power9, power_cpu_has_arch_3_00) +#endif From caf5d84ef9fda40100d6280dc81f0c320ce7724a Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 9 May 2022 09:53:43 -0700 Subject: [PATCH 398/798] Remove extra CMake messages from ARM toolchains. --- cmake/toolchain-aarch64.cmake | 2 -- cmake/toolchain-arm.cmake | 2 -- cmake/toolchain-armhf.cmake | 2 -- 3 files changed, 6 deletions(-) diff --git a/cmake/toolchain-aarch64.cmake b/cmake/toolchain-aarch64.cmake index 0bb190398f..1e24731077 100644 --- a/cmake/toolchain-aarch64.cmake +++ b/cmake/toolchain-aarch64.cmake @@ -2,8 +2,6 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_SYSTEM_VERSION 1) -message(STATUS "Using cross-compile toolchain: ${CROSS_COMPILE_TOOLCHAIN}") - set(CMAKE_C_COMPILER_TARGET "aarch64-linux-gnu") set(CMAKE_CXX_COMPILER_TARGET "aarch64-linux-gnu") diff --git a/cmake/toolchain-arm.cmake b/cmake/toolchain-arm.cmake index 84cd3e575e..1bdd8d2cc1 100644 --- a/cmake/toolchain-arm.cmake +++ b/cmake/toolchain-arm.cmake @@ -2,8 +2,6 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_SYSTEM_VERSION 1) -message(STATUS "Using cross-compile toolchain: ${CROSS_COMPILE_TOOLCHAIN}") - if(NOT DEFINED CMAKE_C_COMPILER_TARGET) set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabi) endif() diff --git a/cmake/toolchain-armhf.cmake b/cmake/toolchain-armhf.cmake index 85db326720..007859caf6 100644 --- a/cmake/toolchain-armhf.cmake +++ b/cmake/toolchain-armhf.cmake @@ -2,8 +2,6 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(CMAKE_SYSTEM_VERSION 1) -message(STATUS "Using cross-compile toolchain: ${CROSS_COMPILE_TOOLCHAIN}") - set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabihf) set(CMAKE_CXX_COMPILER_TARGET arm-linux-gnueabihf) From 16d27623662dcd1dcc7d24cada7ae25b6cf0124e Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Mon, 9 May 2022 16:02:41 -0400 Subject: [PATCH 399/798] Fixed issue #1264: Use fallback for _mm256_zextsi128_si256 on Xcode < 9.3 --- fallback_builtins.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fallback_builtins.h b/fallback_builtins.h index c9fcceac3b..6ab89c20f8 100644 --- a/fallback_builtins.h +++ b/fallback_builtins.h @@ -46,11 +46,14 @@ static __forceinline unsigned long long __builtin_ctzll(uint64_t value) { #endif // Microsoft AMD64/IA64/x86/ARM/ARM64 test #endif // _MSC_VER & !clang -/* Unfortunately GCC didn't support these things until version 10 */ +/* Unfortunately GCC didn't support these things until version 10. + * Similarly, AppleClang didn't support them in Xcode 9.2 but did in 9.3. + */ #ifdef __AVX2__ #include -#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 10) +#if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 10) \ + || (defined(__apple_build_version__) && __apple_build_version__ < 9020039) static inline __m256i _mm256_zextsi128_si256(__m128i a) { __m128i r; __asm__ volatile ("vmovdqa %1,%0" : "=x" (r) : "x" (a)); @@ -64,7 +67,7 @@ static inline __m512i _mm512_zextsi128_si512(__m128i a) { return _mm512_castsi128_si512(r); } #endif // __AVX512F__ -#endif // gcc version 10 test +#endif // gcc/AppleClang version test #endif // __AVX2__ From 41d67396924ccc7ab1ff9a7e7d434bfb0887b136 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Mon, 9 May 2022 23:32:32 -0700 Subject: [PATCH 400/798] Fixed incorrect case for __clang__ preprocessor macro in zbuild.h. --- zbuild.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zbuild.h b/zbuild.h index 9274cbc1ce..82374b1f14 100644 --- a/zbuild.h +++ b/zbuild.h @@ -100,7 +100,7 @@ # define ZSWAP32(q) _byteswap_ulong(q) # define ZSWAP64(q) _byteswap_uint64(q) -#elif defined(__Clang__) || (defined(__GNUC__) && \ +#elif defined(__clang__) || (defined(__GNUC__) && \ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) # define ZSWAP16(q) __builtin_bswap16(q) # define ZSWAP32(q) __builtin_bswap32(q) @@ -144,7 +144,7 @@ #endif /* Only enable likely/unlikely if the compiler is known to support it */ -#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__INTEL_COMPILER) || defined(__Clang__) +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__INTEL_COMPILER) || defined(__clang__) # define LIKELY_NULL(x) __builtin_expect((x) != 0, 0) # define LIKELY(x) __builtin_expect(!!(x), 1) # define UNLIKELY(x) __builtin_expect(!!(x), 0) From 8730b9a0156e3ac93a27f67d17a5e5a1464bc019 Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 12 May 2022 18:36:42 +0500 Subject: [PATCH 401/798] Make directory for output files. Signed-off-by: Vladislav Shchapov --- cmake/run-and-compare.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmake/run-and-compare.cmake b/cmake/run-and-compare.cmake index 16f4821e55..eb2218dcb5 100644 --- a/cmake/run-and-compare.cmake +++ b/cmake/run-and-compare.cmake @@ -16,6 +16,10 @@ if(NOT DEFINED OUTPUT OR NOT DEFINED COMPARE OR NOT DEFINED COMMAND) message(FATAL_ERROR "Run and compare arguments missing") endif() +# Ensure directory exists for output files +get_filename_component(OUTPUT_DIR "${OUTPUT}" DIRECTORY) +file(MAKE_DIRECTORY "${OUTPUT_DIR}") + if(INPUT) # Run command with stdin input and redirect stdout to output execute_process(COMMAND ${CMAKE_COMMAND} From ef0cf5ca17057062a895b187ff8bef9ad7762c2b Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 10 Apr 2022 13:01:22 -0400 Subject: [PATCH 402/798] Improved chunkset substantially where it's heavily used For most realistic use cases, this doesn't make a ton of difference. However, for things which are highly compressible and enjoy very large run length encodes in the window, this is a huge win. We leverage a permutation table to swizzle the contents of the memory chunk into a vector register and then splat that over memory with a fast copy loop. In essence, where this helps, it helps a lot. Where it doesn't, it does no measurable damage to the runtime. This commit also simplifies a chunkcopy_safe call for determining a distance. Using labs is enough to give the same behavior as before, with the added benefit that no predication is required _and_, most importantly, static analysis by GCC's string fortification can't throw a fit because it conveys better to the compiler that the input into builtin_memcpy will always be in range. --- CMakeLists.txt | 3 ++ arch/x86/Makefile.in | 7 +++ arch/x86/chunk_permute_table.h | 53 ++++++++++++++++++ arch/x86/chunkset_avx.c | 80 +++++++++++++++++++++++++++ arch/x86/chunkset_sse41.c | 98 ++++++++++++++++++++++++++++++++++ chunkset_tpl.h | 54 +++++++++++++------ configure | 3 ++ cpu_features.h | 4 ++ functable.c | 8 +++ inflate_p.h | 6 ++- 10 files changed, 298 insertions(+), 18 deletions(-) create mode 100644 arch/x86/chunk_permute_table.h create mode 100644 arch/x86/chunkset_sse41.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c45fd8446..24fe98b3e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -769,6 +769,9 @@ if(WITH_OPTIM) check_sse41_intrinsics() if(HAVE_SSE41_INTRIN) add_definitions(-DX86_SSE41) + list(APPEND SSE41_SRCS ${ARCHDIR}/chunkset_sse41.c) + list(APPEND ZLIB_ARCH_SRCS ${SSE41_SRCS}) + set_property(SOURCE ${SSE41_SRCS} PROPERTY COMPILE_FLAGS "${SSE41FLAG} ${NOLTOFLAG}") else() set(WITH_SSE41 OFF) endif() diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 05cf144b3e..689e3a0c24 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -31,6 +31,7 @@ all: \ adler32_ssse3.o adler32_ssse3.lo \ chunkset_avx.o chunkset_avx.lo \ chunkset_sse2.o chunkset_sse2.lo \ + chunkset_sse41.o chunkset_sse41.lo \ compare256_avx2.o compare256_avx2.lo \ compare256_sse2.o compare256_sse2.lo \ insert_string_sse42.o insert_string_sse42.lo \ @@ -57,6 +58,12 @@ chunkset_sse2.o: chunkset_sse2.lo: $(CC) $(SFLAGS) $(SSE2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse2.c +chunkset_sse41.o: + $(CC) $(CFLAGS) $(SSE41FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse41.c + +chunkset_sse41.lo: + $(CC) $(SFLAGS) $(SSE41FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/chunkset_sse41.c + compare256_avx2.o: $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/compare256_avx2.c diff --git a/arch/x86/chunk_permute_table.h b/arch/x86/chunk_permute_table.h new file mode 100644 index 0000000000..c7b2d2de7f --- /dev/null +++ b/arch/x86/chunk_permute_table.h @@ -0,0 +1,53 @@ +/* chunk_permute_table.h - shared AVX/SSE4 permutation table for use with chunkmemset family of functions. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef CHUNK_PERMUTE_TABLE_H_ +#define CHUNK_PERMUTE_TABLE_H_ + +#include "zbuild.h" + +/* Need entries for all numbers not an even modulus for 1, 2, 4, 8, 16 & 32 */ +static const ALIGNED_(32) uint8_t permute_table[26*32] = { + 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, /* dist 3 */ + 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, /* dist 5 */ + 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, /* dist 6 */ + 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, /* dist 7 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, /* dist 9 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, /* dist 10 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* dist 11 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, /* dist 12 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5, /* dist 13 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1, 2, 3, /* dist 14 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, /* dist 15 */ + + /* Beyond dists of 15 means we have to permute from a vector > len(m128i). Because AVX couldn't permute + * beyond 128 bit lanes until AVX512 for sub 4-byte sequences, we have to do some math here for an eventual + * blend with a comparison. That means we need to wrap the indices with yet another derived table. For simplicity, + * we'll use absolute indexing here to derive a blend vector. This is actually a lot simpler with ARM's TBL, but, + * this is what we're dealt. + */ + + 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* dist 17 */ + 16, 17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, /* dist 18 */ + 16, 17, 18, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, /* dist 19 */ + 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* dist 20 */ + 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, /* dist 21 */ + 16, 17, 18, 19, 20, 21, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* dist 22 */ + 16, 17, 18, 19, 20, 21, 22, 0, 1, 2, 3, 4, 5, 6, 7, 8, /* dist 23 */ + 16, 17, 18, 19, 20, 21, 22, 23, 0, 1, 2, 3, 4, 5, 6, 7, /* dist 24 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 0, 1, 2, 3, 4, 5, 6, /* dist 25 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 1, 2, 3, 4, 5, /* dist 26 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 1, 2, 3, 4, /* dist 27 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 1, 2, 3, /* dist 28 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 0, 1, 2, /* dist 29 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 1, /* dist 30 */ + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 0, /* dist 31 */ +}; + +typedef struct lut_rem_pair_s { + uint16_t idx; + uint16_t remval; +} lut_rem_pair; + +#endif diff --git a/arch/x86/chunkset_avx.c b/arch/x86/chunkset_avx.c index 6643b04683..91aaa458ec 100644 --- a/arch/x86/chunkset_avx.c +++ b/arch/x86/chunkset_avx.c @@ -5,6 +5,7 @@ #ifdef X86_AVX_CHUNKSET #include +#include "chunk_permute_table.h" typedef __m256i chunk_t; @@ -13,6 +14,41 @@ typedef __m256i chunk_t; #define HAVE_CHUNKMEMSET_2 #define HAVE_CHUNKMEMSET_4 #define HAVE_CHUNKMEMSET_8 +#define HAVE_CHUNK_MAG + +/* Populate don't cares so that this is a direct lookup (with some indirection into the permute table), because dist can + * never be 0 - 2, we'll start with an offset, subtracting 3 from the input */ +static const lut_rem_pair perm_idx_lut[29] = { + { 0, 2}, /* 3 */ + { 0, 0}, /* don't care */ + { 1 * 32, 2}, /* 5 */ + { 2 * 32, 2}, /* 6 */ + { 3 * 32, 4}, /* 7 */ + { 0 * 32, 0}, /* don't care */ + { 4 * 32, 5}, /* 9 */ + { 5 * 32, 22}, /* 10 */ + { 6 * 32, 21}, /* 11 */ + { 7 * 32, 20}, /* 12 */ + { 8 * 32, 6}, /* 13 */ + { 9 * 32, 4}, /* 14 */ + {10 * 32, 2}, /* 15 */ + { 0 * 32, 0}, /* don't care */ + {11 * 32, 15}, /* 17 */ + {11 * 32 + 16, 14}, /* 18 */ + {11 * 32 + 16 * 2, 13}, /* 19 */ + {11 * 32 + 16 * 3, 12}, /* 20 */ + {11 * 32 + 16 * 4, 11}, /* 21 */ + {11 * 32 + 16 * 5, 10}, /* 22 */ + {11 * 32 + 16 * 6, 9}, /* 23 */ + {11 * 32 + 16 * 7, 8}, /* 24 */ + {11 * 32 + 16 * 8, 7}, /* 25 */ + {11 * 32 + 16 * 9, 6}, /* 26 */ + {11 * 32 + 16 * 10, 5}, /* 27 */ + {11 * 32 + 16 * 11, 4}, /* 28 */ + {11 * 32 + 16 * 12, 3}, /* 29 */ + {11 * 32 + 16 * 13, 2}, /* 30 */ + {11 * 32 + 16 * 14, 1} /* 31 */ +}; static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { int16_t tmp; @@ -40,6 +76,50 @@ static inline void storechunk(uint8_t *out, chunk_t *chunk) { _mm256_storeu_si256((__m256i *)out, *chunk); } +static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { + lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; + __m256i ret_vec; + /* While technically we only need to read 4 or 8 bytes into this vector register for a lot of cases, GCC is + * compiling this to a shared load for all branches, preferring the simpler code. Given that the buf value isn't in + * GPRs to begin with the 256 bit load is _probably_ just as inexpensive */ + *chunk_rem = lut_rem.remval; + +#ifdef Z_MEMORY_SANITIZER + /* See note in chunkset_sse4.c for why this is ok */ + __msan_unpoison(buf + dist, 32 - dist); +#endif + + if (dist < 16) { + /* This simpler case still requires us to shuffle in 128 bit lanes, so we must apply a static offset after + * broadcasting the first vector register to both halves. This is _marginally_ faster than doing two separate + * shuffles and combining the halves later */ + const __m256i permute_xform = + _mm256_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16); + __m256i perm_vec = _mm256_load_si256((__m256i*)(permute_table+lut_rem.idx)); + __m128i ret_vec0 = _mm_loadu_si128((__m128i*)buf); + perm_vec = _mm256_add_epi8(perm_vec, permute_xform); + ret_vec = _mm256_inserti128_si256(_mm256_castsi128_si256(ret_vec0), ret_vec0, 1); + ret_vec = _mm256_shuffle_epi8(ret_vec, perm_vec); + } else if (dist == 16) { + __m128i ret_vec0 = _mm_loadu_si128((__m128i*)buf); + return _mm256_inserti128_si256(_mm256_castsi128_si256(ret_vec0), ret_vec0, 1); + } else { + __m128i ret_vec0 = _mm_loadu_si128((__m128i*)buf); + __m128i ret_vec1 = _mm_loadu_si128((__m128i*)(buf + 16)); + /* Take advantage of the fact that only the latter half of the 256 bit vector will actually differ */ + __m128i perm_vec1 = _mm_load_si128((__m128i*)(permute_table + lut_rem.idx)); + __m128i xlane_permutes = _mm_cmpgt_epi8(_mm_set1_epi8(16), perm_vec1); + __m128i xlane_res = _mm_shuffle_epi8(ret_vec0, perm_vec1); + /* Since we can't wrap twice, we can simply keep the later half exactly how it is instead of having to _also_ + * shuffle those values */ + __m128i latter_half = _mm_blendv_epi8(ret_vec1, xlane_res, xlane_permutes); + ret_vec = _mm256_inserti128_si256(_mm256_castsi128_si256(ret_vec0), latter_half, 1); + } + + return ret_vec; +} + #define CHUNKSIZE chunksize_avx #define CHUNKCOPY chunkcopy_avx #define CHUNKCOPY_SAFE chunkcopy_safe_avx diff --git a/arch/x86/chunkset_sse41.c b/arch/x86/chunkset_sse41.c new file mode 100644 index 0000000000..c6f982183a --- /dev/null +++ b/arch/x86/chunkset_sse41.c @@ -0,0 +1,98 @@ +/* chunkset_sse41.c -- SSE4 inline functions to copy small data chunks. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" + +/* This requires SSE2 support. While it's implicit with SSE4, we can minimize + * code size by sharing the chunkcopy functions, which will certainly compile + * to identical machine code */ +#if defined(X86_SSE41) && defined(X86_SSE2) +#include +#include "chunk_permute_table.h" + +typedef __m128i chunk_t; + +#define CHUNK_SIZE 16 + +#define HAVE_CHUNKMEMSET_2 +#define HAVE_CHUNKMEMSET_4 +#define HAVE_CHUNKMEMSET_8 +#define HAVE_CHUNK_MAG +#define HAVE_CHUNKCOPY +#define HAVE_CHUNKUNROLL + +static const lut_rem_pair perm_idx_lut[13] = { + {0, 1}, /* 3 */ + {0, 0}, /* don't care */ + {1 * 32, 1}, /* 5 */ + {2 * 32, 4}, /* 6 */ + {3 * 32, 2}, /* 7 */ + {0 * 32, 0}, /* don't care */ + {4 * 32, 7}, /* 9 */ + {5 * 32, 6}, /* 10 */ + {6 * 32, 5}, /* 11 */ + {7 * 32, 4}, /* 12 */ + {8 * 32, 3}, /* 13 */ + {9 * 32, 2}, /* 14 */ + {10 * 32, 1},/* 15 */ +}; + + +static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) { + int16_t tmp; + zmemcpy_2(&tmp, from); + *chunk = _mm_set1_epi16(tmp); +} + +static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) { + int32_t tmp; + zmemcpy_4(&tmp, from); + *chunk = _mm_set1_epi32(tmp); +} + +static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) { + int64_t tmp; + zmemcpy_8(&tmp, from); + *chunk = _mm_set1_epi64x(tmp); +} + +static inline void loadchunk(uint8_t const *s, chunk_t *chunk) { + *chunk = _mm_loadu_si128((__m128i *)s); +} + +static inline void storechunk(uint8_t *out, chunk_t *chunk) { + _mm_storeu_si128((__m128i *)out, *chunk); +} + +static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { + lut_rem_pair lut_rem = perm_idx_lut[dist - 3]; + __m128i perm_vec, ret_vec; +#ifdef Z_MEMORY_SANITIZER + /* Important to note: + * This is _not_ to subvert the memory sanitizer but to instead unpoison some + * bytes we willingly and purposefully load unitialized that we swizzle over + * in a vector register, anyway. If what we assume is wrong about what is used, + * the memory sanitizer will still usefully flag it */ + __msan_unpoison(buf + dist, 16 - dist); +#endif + ret_vec = _mm_loadu_si128((__m128i*)buf); + *chunk_rem = lut_rem.remval; + + perm_vec = _mm_load_si128((__m128i*)(permute_table + lut_rem.idx)); + ret_vec = _mm_shuffle_epi8(ret_vec, perm_vec); + + return ret_vec; +} + +extern uint8_t* chunkcopy_sse2(uint8_t *out, uint8_t const *from, unsigned len); + +#define CHUNKSIZE chunksize_sse41 +#define CHUNKMEMSET chunkmemset_sse41 +#define CHUNKMEMSET_SAFE chunkmemset_safe_sse41 +#define CHUNKCOPY(a, b, c) chunkcopy_sse2(a, b, c) +#define CHUNKUNROLL(a, b, c) chunkunroll_sse2(a, b, c) + +#include "chunkset_tpl.h" + +#endif diff --git a/chunkset_tpl.h b/chunkset_tpl.h index 25ee955967..f70ef42cdb 100644 --- a/chunkset_tpl.h +++ b/chunkset_tpl.h @@ -5,6 +5,10 @@ #include "zbuild.h" #include +#if CHUNK_SIZE == 32 && defined(X86_SSE41) && defined(X86_SSE2) +extern uint8_t* chunkmemset_sse41(uint8_t *out, unsigned dist, unsigned len); +#endif + /* Returns the chunk size */ Z_INTERNAL uint32_t CHUNKSIZE(void) { return sizeof(chunk_t); @@ -20,6 +24,7 @@ Z_INTERNAL uint32_t CHUNKSIZE(void) { (chunk_t bytes or fewer) will fall straight through the loop without iteration, which will hopefully make the branch prediction more reliable. */ +#ifndef HAVE_CHUNKCOPY Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { Assert(len > 0, "chunkcopy should never have a length 0"); chunk_t chunk; @@ -38,6 +43,7 @@ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { } return out; } +#endif /* Perform short copies until distance can be rewritten as being at least sizeof chunk_t. @@ -47,6 +53,7 @@ Z_INTERNAL uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) { This assumption holds because inflate_fast() starts every iteration with at least 258 bytes of output space available (258 being the maximum length output from a single token; see inflate_fast()'s assumptions below). */ +#ifndef HAVE_CHUNKUNROLL Z_INTERNAL uint8_t* CHUNKUNROLL(uint8_t *out, unsigned *dist, unsigned *len) { unsigned char const *from = out - *dist; chunk_t chunk; @@ -59,6 +66,30 @@ Z_INTERNAL uint8_t* CHUNKUNROLL(uint8_t *out, unsigned *dist, unsigned *len) { } return out; } +#endif + +#ifndef HAVE_CHUNK_MAG +/* Loads a magazine to feed into memory of the pattern */ +static inline chunk_t GET_CHUNK_MAG(uint8_t *buf, uint32_t *chunk_rem, uint32_t dist) { + /* This code takes string of length dist from "from" and repeats + * it for as many times as can fit in a chunk_t (vector register) */ + uint32_t cpy_dist; + uint32_t bytes_remaining = sizeof(chunk_t); + chunk_t chunk_load; + uint8_t *cur_chunk = (uint8_t *)&chunk_load; + while (bytes_remaining) { + cpy_dist = MIN(dist, bytes_remaining); + memcpy(cur_chunk, buf, cpy_dist); + bytes_remaining -= cpy_dist; + cur_chunk += cpy_dist; + /* This allows us to bypass an expensive integer division since we're effectively + * counting in this loop, anyway */ + *chunk_rem = cpy_dist; + } + + return chunk_load; +} +#endif /* Copy DIST bytes from OUT - DIST into OUT + DIST * k, for 0 <= k < LEN/DIST. Return OUT + LEN. */ @@ -66,6 +97,12 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { /* Debug performance related issues when len < sizeof(uint64_t): Assert(len >= sizeof(uint64_t), "chunkmemset should be called on larger chunks"); */ Assert(dist > 0, "chunkmemset cannot have a distance 0"); + /* Only AVX2 */ +#if CHUNK_SIZE == 32 && defined(X86_SSE41) && defined(X86_SSE2) + if (len <= 16) { + return chunkmemset_sse41(out, dist, len); + } +#endif uint8_t *from = out - dist; @@ -98,22 +135,7 @@ Z_INTERNAL uint8_t* CHUNKMEMSET(uint8_t *out, unsigned dist, unsigned len) { } else #endif { - /* This code takes string of length dist from "from" and repeats - * it for as many times as can fit in a chunk_t (vector register) */ - uint32_t cpy_dist; - uint32_t bytes_remaining = sizeof(chunk_t); - uint8_t *cur_chunk = (uint8_t *)&chunk_load; - while (bytes_remaining) { - cpy_dist = MIN(dist, bytes_remaining); - memcpy(cur_chunk, from, cpy_dist); - bytes_remaining -= cpy_dist; - cur_chunk += cpy_dist; - /* This allows us to bypass an expensive integer division since we're effectively - * counting in this loop, anyway. However, we may have to derive a similarly - * sensible solution for if we use a permutation table that allows us to construct - * this vector in one load and one permute instruction */ - chunk_mod = cpy_dist; - } + chunk_load = GET_CHUNK_MAG(from, &chunk_mod, dist); } /* If we're lucky enough and dist happens to be an even modulus of our vector length, diff --git a/configure b/configure index ff657e698f..6f79825a7f 100755 --- a/configure +++ b/configure @@ -1487,6 +1487,9 @@ case "${ARCH}" in if test ${HAVE_SSE41_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE41" SFLAGS="${SFLAGS} -DX86_SSE41" + + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} chunkset_sse41.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} chunkset_sse41.lo" fi check_sse42_intrinsics diff --git a/cpu_features.h b/cpu_features.h index 861ae0c4d8..d3df33b9f6 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -71,6 +71,10 @@ extern uint8_t* chunkunroll_sse2(uint8_t *out, unsigned *dist, unsigned *len); extern uint8_t* chunkmemset_sse2(uint8_t *out, unsigned dist, unsigned len); extern uint8_t* chunkmemset_safe_sse2(uint8_t *out, unsigned dist, unsigned len, unsigned left); #endif +#ifdef X86_SSE41 +extern uint8_t* chunkmemset_sse41(uint8_t *out, unsigned dist, unsigned len); +extern uint8_t* chunkmemset_safe_sse41(uint8_t *out, unsigned dist, unsigned len, unsigned left); +#endif #ifdef X86_AVX_CHUNKSET extern uint32_t chunksize_avx(void); extern uint8_t* chunkcopy_avx(uint8_t *out, uint8_t const *from, unsigned len); diff --git a/functable.c b/functable.c index 64992bc7be..960c51f1bc 100644 --- a/functable.c +++ b/functable.c @@ -331,6 +331,10 @@ Z_INTERNAL uint8_t* chunkmemset_stub(uint8_t *out, unsigned dist, unsigned len) # endif functable.chunkmemset = &chunkmemset_sse2; #endif +#if defined(X86_SSE41) && defined(X86_SSE2) + if (x86_cpu_has_sse41) + functable.chunkmemset = &chunkmemset_sse41; +#endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) functable.chunkmemset = &chunkmemset_avx; @@ -358,6 +362,10 @@ Z_INTERNAL uint8_t* chunkmemset_safe_stub(uint8_t *out, unsigned dist, unsigned # endif functable.chunkmemset_safe = &chunkmemset_safe_sse2; #endif +#if defined(X86_SSE41) && defined(X86_SSE2) + if (x86_cpu_has_sse41) + functable.chunkmemset_safe = &chunkmemset_safe_sse41; +#endif #ifdef X86_AVX_CHUNKSET if (x86_cpu_has_avx2) functable.chunkmemset_safe = &chunkmemset_safe_avx; diff --git a/inflate_p.h b/inflate_p.h index a0b6aa8fb5..65bbd4448a 100644 --- a/inflate_p.h +++ b/inflate_p.h @@ -5,6 +5,8 @@ #ifndef INFLATE_P_H #define INFLATE_P_H +#include + /* Architecture-specific hooks. */ #ifdef S390_DFLTCC_INFLATE # include "arch/s390/dfltcc_inflate.h" @@ -145,8 +147,8 @@ static inline uint8_t* chunkcopy_safe(uint8_t *out, uint8_t *from, size_t len, u * we have to get a bit clever. First if the overlap is such that src falls between dst and dst+len, we can do the * initial bulk memcpy of the nonoverlapping region. Then, we can leverage the size of this to determine the safest * atomic memcpy size we can pick such that we have non-overlapping regions. This effectively becomes a safe look - * behind or lookahead distance */ - size_t non_olap_size = ((from > out) ? from - out : out - from); + * behind or lookahead distance. */ + size_t non_olap_size = llabs(from - out); // llabs vs labs for compatibility with windows memcpy(out, from, non_olap_size); out += non_olap_size; From b1389ac2d5b0850742a10e9ff8243537d678f2f6 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Fri, 1 Apr 2022 19:02:05 -0400 Subject: [PATCH 403/798] Create adler32_fold_c* functions These are very simple wrappers that do nothing clever but serve as a shim interface for implementing versions which do cleverly track the number of scalar sums performed so that we can minimize rebasing and also have an efficient copy elision. This serves as the baseline as each vectorization gets its own commit. That way the PR will be bisectable. --- CMakeLists.txt | 1 + Makefile.in | 2 ++ adler32_fold.c | 30 ++++++++++++++++++++++++++++++ adler32_fold.h | 22 ++++++++++++++++++++++ functable.c | 24 ++++++++++++++++++++++++ functable.h | 5 +++++ inflate.c | 14 +++++++++++--- inflate.h | 2 ++ win32/Makefile.a64 | 2 ++ win32/Makefile.arm | 2 ++ win32/Makefile.msc | 2 ++ 11 files changed, 103 insertions(+), 3 deletions(-) create mode 100644 adler32_fold.c create mode 100644 adler32_fold.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 24fe98b3e6..247af86d22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -951,6 +951,7 @@ set(ZLIB_PRIVATE_HDRS ) set(ZLIB_SRCS adler32.c + adler32_fold.c chunkset.c compare256.c compress.c diff --git a/Makefile.in b/Makefile.in index 96bb93828f..10decf5d7b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -75,6 +75,7 @@ pkgconfigdir = ${libdir}/pkgconfig OBJZ = \ adler32.o \ + adler32_fold.o \ chunkset.o \ compare256.o \ compress.o \ @@ -112,6 +113,7 @@ OBJC = $(OBJZ) $(OBJG) PIC_OBJZ = \ adler32.lo \ + adler32_fold.lo \ chunkset.lo \ compare256.lo \ compress.lo \ diff --git a/adler32_fold.c b/adler32_fold.c new file mode 100644 index 0000000000..3f745cd9c6 --- /dev/null +++ b/adler32_fold.c @@ -0,0 +1,30 @@ +/* crc32_fold.c -- adler32 folding interface + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zbuild.h" +#include "functable.h" +#include "adler32_fold.h" + +Z_INTERNAL void adler32_fold_reset_c(adler32_fold *adler, uint32_t init_adler) { + /* So, for the "C" version, we'll just stash the value into nsums. + * This is mostly a compatibility shim, these functions in the functable + * will have more optimal versions that make use of adler and sum2. In order + * to make each implementation bisectable, each new implementation will be a + * new commit */ + adler->nsums = init_adler; +} + +Z_INTERNAL void adler32_fold_copy_c(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { + adler->nsums = functable.adler32(adler->nsums, src, len); + memcpy(dst, src, len); +} + +Z_INTERNAL void adler32_fold_c(adler32_fold *adler, const uint8_t *src, size_t len) { + adler->nsums = functable.adler32(adler->nsums, src, len); +} + +Z_INTERNAL uint32_t adler32_fold_final_c(adler32_fold *adler) { + return adler->nsums; +} diff --git a/adler32_fold.h b/adler32_fold.h new file mode 100644 index 0000000000..d93a510534 --- /dev/null +++ b/adler32_fold.h @@ -0,0 +1,22 @@ +/* adler32_fold.h -- adler32 folding interface + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_FOLD_H_ +#define ADLER32_FOLD_H_ + +#include + +typedef struct adler32_fold_s { + uint8_t adler[64]; // First half of component sums + uint8_t sum2[64]; // Second half of component sums + uint32_t nsums; // The number of scalar sums performed +} adler32_fold; + +Z_INTERNAL void adler32_fold_reset_c(adler32_fold *adler, uint32_t init_adler); +Z_INTERNAL void adler32_fold_copy_c(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); +Z_INTERNAL void adler32_fold_c(adler32_fold *adler, const uint8_t *src, size_t len); +Z_INTERNAL uint32_t adler32_fold_final_c(adler32_fold *adler); + +#endif diff --git a/functable.c b/functable.c index 960c51f1bc..317349f303 100644 --- a/functable.c +++ b/functable.c @@ -202,6 +202,26 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ return functable.adler32(adler, buf, len); } +Z_INTERNAL void adler32_fold_reset_stub(adler32_fold *adler, uint32_t init_adler) { + functable.adler32_fold_reset = &adler32_fold_reset_c; + functable.adler32_fold_reset(adler, init_adler); +} + +Z_INTERNAL void adler32_fold_copy_stub(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { + functable.adler32_fold_copy = &adler32_fold_copy_c; + functable.adler32_fold_copy(adler, dst, src, len); +} + +Z_INTERNAL void adler32_fold_stub(adler32_fold *adler, const uint8_t *src, size_t len) { + functable.adler32_fold = &adler32_fold_c; + functable.adler32_fold(adler, src, len); +} + +Z_INTERNAL uint32_t adler32_fold_final_stub(adler32_fold *adler) { + functable.adler32_fold_final = &adler32_fold_final_c; + return functable.adler32_fold_final(adler); +} + Z_INTERNAL uint32_t crc32_fold_reset_stub(crc32_fold *crc) { functable.crc32_fold_reset = &crc32_fold_reset_c; cpu_check_features(); @@ -437,6 +457,10 @@ Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { adler32_stub, + adler32_fold_reset_stub, + adler32_fold_copy_stub, + adler32_fold_stub, + adler32_fold_final_stub, crc32_stub, crc32_fold_reset_stub, crc32_fold_copy_stub, diff --git a/functable.h b/functable.h index 61dde2105f..8889e74afa 100644 --- a/functable.h +++ b/functable.h @@ -8,9 +8,14 @@ #include "deflate.h" #include "crc32_fold.h" +#include "adler32_fold.h" struct functable_s { uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, size_t len); + void (* adler32_fold_reset) (adler32_fold *adler, uint32_t init_adler); + void (* adler32_fold_copy) (adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); + void (* adler32_fold) (adler32_fold *adler, const uint8_t *src, size_t len); + uint32_t (* adler32_fold_final) (adler32_fold *adler); uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); uint32_t (* crc32_fold_reset) (crc32_fold *crc); void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); diff --git a/inflate.c b/inflate.c index 8a48e79334..9e816a40d8 100644 --- a/inflate.c +++ b/inflate.c @@ -27,8 +27,9 @@ static inline void inf_chksum_cpy(PREFIX3(stream) *strm, uint8_t *dst, } else #endif { - strm->adler = state->check = functable.adler32(state->check, src, copy); - memcpy(dst, src, copy); + /*strm->adler = state->check = functable.adler32(state->check, src, copy); + memcpy(dst, src, copy);*/ + functable.adler32_fold_copy(&state->adler_fold, dst, src, copy); } } @@ -40,7 +41,8 @@ static inline void inf_chksum(PREFIX3(stream) *strm, const uint8_t *src, uint32_ } else #endif { - strm->adler = state->check = functable.adler32(state->check, src, len); + //strm->adler = state->check = functable.adler32(state->check, src, len); + functable.adler32_fold(&state->adler_fold, src, len); } } @@ -463,6 +465,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->dmax = 1U << len; state->flags = 0; /* indicate zlib header */ Tracev((stderr, "inflate: zlib header ok\n")); + functable.adler32_fold_reset(&state->adler_fold, ADLER32_INITIAL_VALUE); strm->adler = state->check = ADLER32_INITIAL_VALUE; state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); @@ -609,7 +612,9 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #endif case DICTID: NEEDBITS(32); + //strm->adler = state->check = ZSWAP32(hold); strm->adler = state->check = ZSWAP32(hold); + functable.adler32_fold_reset(&state->adler_fold, strm->adler); INITBITS(); state->mode = DICT; @@ -619,6 +624,7 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { return Z_NEED_DICT; } strm->adler = state->check = ADLER32_INITIAL_VALUE; + functable.adler32_fold_reset(&state->adler_fold, ADLER32_INITIAL_VALUE); state->mode = TYPE; case TYPE: @@ -1011,6 +1017,8 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #ifdef GUNZIP if (state->flags) strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold); + else + strm->adler = state->check = functable.adler32_fold_final(&state->adler_fold); #endif } out = left; diff --git a/inflate.h b/inflate.h index ffa2d0bd80..8c65f1dbe1 100644 --- a/inflate.h +++ b/inflate.h @@ -12,6 +12,7 @@ #define INFLATE_H_ #include "crc32_fold.h" +#include "adler32_fold.h" /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. @@ -103,6 +104,7 @@ struct inflate_state { uint32_t wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if needed */ + struct adler32_fold_s ALIGNED_(64) adler_fold; struct crc32_fold_s ALIGNED_(16) crc_fold; /* bit accumulator */ diff --git a/win32/Makefile.a64 b/win32/Makefile.a64 index b0d7993d54..5d5824bda3 100644 --- a/win32/Makefile.a64 +++ b/win32/Makefile.a64 @@ -43,6 +43,7 @@ SUFFIX = OBJS = \ adler32.obj \ + adler32_fold.obj \ arm_features.obj \ chunkset.obj \ compare256.obj \ @@ -179,6 +180,7 @@ $(TOP)/zconf$(SUFFIX).h: zconf SRCDIR = $(TOP) # Keep the dependences in sync with top-level Makefile.in adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h +adler32_fold.obj: $(SRCDIR)/adler32_fold.c $(SRCDIR)/zbuild.h $(SRCDIR)/adler32_fold.h $(SRCDIR)/functable.h chunkset.obj: $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86_features.h gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h diff --git a/win32/Makefile.arm b/win32/Makefile.arm index 14df718d84..765bbb83ba 100644 --- a/win32/Makefile.arm +++ b/win32/Makefile.arm @@ -47,6 +47,7 @@ SUFFIX = OBJS = \ adler32.obj \ + adler32_fold.obj \ arm_features.obj \ chunkset.obj \ compare256.obj \ @@ -192,6 +193,7 @@ $(TOP)/zconf$(SUFFIX).h: zconf SRCDIR = $(TOP) # Keep the dependences in sync with top-level Makefile.in adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h +adler32_fold.obj: $(SRCDIR)/adler32_fold.c $(SRCDIR)/zbuild.h $(SRCDIR)/adler32_fold.h $(SRCDIR)/functable.h functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86_features.h gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 9caa8211c8..b121cde22c 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -48,6 +48,7 @@ SUFFIX = OBJS = \ adler32.obj \ + adler32_fold.obj \ chunkset.obj \ chunkset_avx.obj \ chunkset_sse2.obj \ @@ -181,6 +182,7 @@ $(TOP)/zconf$(SUFFIX).h: zconf SRCDIR = $(TOP) # Keep the dependences in sync with top-level Makefile.in adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h +adler32_fold.obj: $(SRCDIR)/adler32_fold.c $(SRCDIR)/zbuild.h $(SRCDIR)/adler32_fold.h $(SRCDIR)/functable.h functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86_features.h gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h gzread.obj: $(SRCDIR)/gzread.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h From 21f461e23829a0ce8ec4b267a885b5406c1d9b99 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Sun, 3 Apr 2022 12:18:12 -0400 Subject: [PATCH 404/798] Adding an SSE42 optimized copy + adler checksum implementation We are protecting its usage around a lot of preprocessor macros as the other methods are not yet implemented and calling this version bypasses the faster adler implementations implicitly. When more versions are written for faster vectorizations, the functable entries will be populated and preprocessor macros removed. This round, the copy + checksum is not employing as many tricks as one would hope with a "folded" checksum routine. The reason for this is the particularly tricky case of dealing with unaligned buffers. The implementations which don't have CPUs in the mix that have a huge penalty for unaligned loads will have a much faster implementation. Fancier methods that minimized rebasing, while having the potential to be faster, ended up being slower because the compiler structured the code in a way that ended up either spilling to the stack or trampolining out of a loop and back in it instead of just jumping over the first load and store. Revisiting this for AVX512, where more registers are abundant and more advanced loads exist, may be prudent. --- CMakeLists.txt | 4 +- adler32_fold.h | 4 +- adler32_p.h | 12 +++ arch/x86/Makefile.in | 15 ++- arch/x86/adler32_sse42.c | 31 ++++++ arch/x86/adler32_sse42_tpl.h | 132 ++++++++++++++++++++++++ arch/x86/adler32_ssse3.c | 15 +-- arch/x86/adler32_ssse3_p.h | 29 ++++++ arch/x86/adler32_ssse3_tpl.h | 188 +++++++++++++++++++++++++++++++++++ configure | 8 +- cpu_features.h | 7 ++ deflate.c | 18 +++- deflate.h | 2 + functable.c | 16 +++ inflate.c | 1 + win32/Makefile.msc | 15 +++ 16 files changed, 468 insertions(+), 29 deletions(-) create mode 100644 arch/x86/adler32_sse42.c create mode 100644 arch/x86/adler32_sse42_tpl.h create mode 100644 arch/x86/adler32_ssse3_p.h create mode 100644 arch/x86/adler32_ssse3_tpl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 247af86d22..9719468bf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -779,8 +779,8 @@ if(WITH_OPTIM) if(WITH_SSE42) check_sse42_intrinsics() if(HAVE_SSE42CRC_INLINE_ASM OR HAVE_SSE42CRC_INTRIN) - add_definitions(-DX86_SSE42_CRC_HASH) - set(SSE42_SRCS ${ARCHDIR}/insert_string_sse42.c) + add_definitions(-DX86_SSE42_CRC_HASH -DX86_SSE42_ADLER32) + set(SSE42_SRCS ${ARCHDIR}/adler32_sse42.c ${ARCHDIR}/insert_string_sse42.c) add_feature_info(SSE42_CRC 1 "Support SSE4.2 optimized CRC hash generation, using \"${SSE42FLAG}\"") list(APPEND ZLIB_ARCH_SRCS ${SSE42_SRCS}) set_property(SOURCE ${SSE42_SRCS} PROPERTY COMPILE_FLAGS "${SSE42FLAG} ${NOLTOFLAG}") diff --git a/adler32_fold.h b/adler32_fold.h index d93a510534..ec4270a7ab 100644 --- a/adler32_fold.h +++ b/adler32_fold.h @@ -11,7 +11,9 @@ typedef struct adler32_fold_s { uint8_t adler[64]; // First half of component sums uint8_t sum2[64]; // Second half of component sums - uint32_t nsums; // The number of scalar sums performed + uint8_t leftover[16]; // A buffer for sub 16 sized carry over, sized for full loads and alignment + uint32_t nsums; // The number of scalar sums leftover + uint32_t bytes_leftover; // The number of leftover bytes from the previous sum } adler32_fold; Z_INTERNAL void adler32_fold_reset_c(adler32_fold *adler, uint32_t init_adler); diff --git a/adler32_p.h b/adler32_p.h index 1adc1ccb0a..5a14172f73 100644 --- a/adler32_p.h +++ b/adler32_p.h @@ -26,6 +26,18 @@ static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, u return adler | (sum2 << 16); } +static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char *buf, uint8_t *dst, size_t len, uint32_t sum2) { + while (len--) { + *dst = *buf++; + adler += *dst++; + sum2 += adler; + } + adler %= BASE; + sum2 %= BASE; /* only added so many BASE's */ + /* return recombined sums */ + return adler | (sum2 << 16); +} + static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) { while (len) { --len; diff --git a/arch/x86/Makefile.in b/arch/x86/Makefile.in index 689e3a0c24..f9aedf82ba 100644 --- a/arch/x86/Makefile.in +++ b/arch/x86/Makefile.in @@ -28,6 +28,7 @@ all: \ adler32_avx2.o adler32_avx2.lo \ adler32_avx512.o adler32_avx512.lo \ adler32_avx512_vnni.o adler32_avx512_vnni.lo \ + adler32_sse42.o adler32_sse42.lo \ adler32_ssse3.o adler32_ssse3.lo \ chunkset_avx.o chunkset_avx.lo \ chunkset_sse2.o chunkset_sse2.lo \ @@ -110,25 +111,31 @@ adler32_avx2.o: $(SRCDIR)/adler32_avx2.c $(CC) $(CFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx2.c adler32_avx2.lo: $(SRCDIR)/adler32_avx2.c - $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx2.c + $(CC) $(SFLAGS) $(AVX2FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx2.c adler32_avx512.o: $(SRCDIR)/adler32_avx512.c $(CC) $(CFLAGS) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512.c adler32_avx512.lo: $(SRCDIR)/adler32_avx512.c - $(CC) $(SFLAGS) $(AVX512FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512.c + $(CC) $(SFLAGS) $(AVX512FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512.c adler32_avx512_vnni.o: $(SRCDIR)/adler32_avx512_vnni.c $(CC) $(CFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c adler32_avx512_vnni.lo: $(SRCDIR)/adler32_avx512_vnni.c - $(CC) $(SFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c + $(CC) $(SFLAGS) $(AVX512VNNIFLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_avx512_vnni.c adler32_ssse3.o: $(SRCDIR)/adler32_ssse3.c $(CC) $(CFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c adler32_ssse3.lo: $(SRCDIR)/adler32_ssse3.c - $(CC) $(SFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c + $(CC) $(SFLAGS) $(SSSE3FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_ssse3.c + +adler32_sse42.o: $(SRCDIR)/adler32_sse42.c + $(CC) $(CFLAGS) $(SSE42FLAG) $(NOLTOFLAG) $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_sse42.c + +adler32_sse42.lo: $(SRCDIR)/adler32_sse42.c + $(CC) $(SFLAGS) $(SSE42FLAG) $(NOLTOFLAG) -DPIC $(INCLUDES) -c -o $@ $(SRCDIR)/adler32_sse42.c mostlyclean: clean clean: diff --git a/arch/x86/adler32_sse42.c b/arch/x86/adler32_sse42.c new file mode 100644 index 0000000000..dce1550280 --- /dev/null +++ b/arch/x86/adler32_sse42.c @@ -0,0 +1,31 @@ +/* adler32_sse4.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011 Mark Adler + * Authors: + * Adam Stylinski + * Brian Bockelman + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "../../zbuild.h" +#include "../../adler32_p.h" +#include "../../adler32_fold.h" +#include "adler32_ssse3_p.h" +#include + +#ifdef X86_SSE42_ADLER32 + +Z_INTERNAL void adler32_fold_reset_sse42(adler32_fold *adler, uint32_t init_adler) { + adler->nsums = init_adler; +} + +Z_INTERNAL uint32_t adler32_fold_final_sse42(adler32_fold *adler) { + return adler->nsums; +} + +#include "adler32_sse42_tpl.h" +#undef ADLER32_SSE42_TPL_H_ +#define COPY +#include "adler32_sse42_tpl.h" +#undef COPY + +#endif diff --git a/arch/x86/adler32_sse42_tpl.h b/arch/x86/adler32_sse42_tpl.h new file mode 100644 index 0000000000..71d1db818b --- /dev/null +++ b/arch/x86/adler32_sse42_tpl.h @@ -0,0 +1,132 @@ +/* adler32_ssse3_tpl.h -- adler32 ssse3 vectorized function templates + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_SSE42_TPL_H_ +#define ADLER32_SSE42_TPL_H_ + +#include "../../zbuild.h" +#include +#include "../../adler32_fold.h" +#include "../../adler32_p.h" +#include "adler32_ssse3_p.h" + +#ifdef COPY +Z_INTERNAL void adler32_fold_copy_sse42(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { +#else +Z_INTERNAL void adler32_fold_sse42(adler32_fold *adler, const uint8_t *src, size_t len) { +#endif + + uint32_t adler0, adler1; + adler1 = (adler->nsums >> 16) & 0xffff; + adler0 = adler->nsums & 0xffff; + + if (len < 16) { +rem_peel: +#ifdef COPY + adler->nsums = adler32_copy_len_16(adler0, src, dst, len, adler1); +#else + adler->nsums = adler32_len_16(adler0, src, len, adler1); +#endif + return; + } + + __m128i vbuf, vbuf_0; + __m128i vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, + v_sad_sum2, vsum2, vsum2_0; + __m128i zero = _mm_setzero_si128(); + const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); + const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i dot3v = _mm_set1_epi16(1); + size_t k; + + while (len >= 16) { + + k = MIN(len, NMAX); + k -= k % 16; + len -= k; + + vs1 = _mm_cvtsi32_si128(adler0); + vs2 = _mm_cvtsi32_si128(adler1); + + vs3 = _mm_setzero_si128(); + vs2_0 = _mm_setzero_si128(); + vs1_0 = vs1; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_loadu_si128((__m128i*)src); + vbuf_0 = _mm_loadu_si128((__m128i*)(src + 16)); + src += 32; + k -= 32; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); +#ifdef COPY + _mm_storeu_si128((__m128i*)dst, vbuf); + _mm_storeu_si128((__m128i*)(dst + 16), vbuf_0); + dst += 32; +#endif + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); + + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); + vs1 = _mm_add_epi32(v_sad_sum2, vs1); + vs2 = _mm_add_epi32(vsum2, vs2); + vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); + vs1_0 = vs1; + } + + vs2 = _mm_add_epi32(vs2_0, vs2); + vs3 = _mm_slli_epi32(vs3, 5); + vs2 = _mm_add_epi32(vs3, vs2); + vs3 = _mm_setzero_si128(); + + while (k >= 16) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_loadu_si128((__m128i*)src); + src += 16; + k -= 16; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); + + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + +#ifdef COPY + _mm_storeu_si128((__m128i*)dst, vbuf); + dst += 16; +#endif + } + + vs3 = _mm_slli_epi32(vs3, 4); + vs2 = _mm_add_epi32(vs2, vs3); + + adler0 = partial_hsum(vs1) % BASE; + adler1 = hsum(vs2) % BASE; + } + + /* If this is true, there's fewer than 16 elements remaining */ + if (len) { + goto rem_peel; + } + + adler->nsums = adler0 | (adler1 << 16); +} + +#endif diff --git a/arch/x86/adler32_ssse3.c b/arch/x86/adler32_ssse3.c index b2ef0115c8..8c55badf98 100644 --- a/arch/x86/adler32_ssse3.c +++ b/arch/x86/adler32_ssse3.c @@ -8,25 +8,12 @@ #include "../../zbuild.h" #include "../../adler32_p.h" +#include "adler32_ssse3_p.h" #ifdef X86_SSSE3_ADLER32 #include -static inline uint32_t partial_hsum(__m128i x) { - __m128i second_int = _mm_bsrli_si128(x, 8); - __m128i sum = _mm_add_epi32(x, second_int); - return _mm_cvtsi128_si32(sum); -} - -static inline uint32_t hsum(__m128i x) { - __m128i sum1 = _mm_unpackhi_epi64(x, x); - __m128i sum2 = _mm_add_epi32(x, sum1); - __m128i sum3 = _mm_shuffle_epi32(sum2, 0x01); - __m128i sum4 = _mm_add_epi32(sum2, sum3); - return _mm_cvtsi128_si32(sum4); -} - Z_INTERNAL uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len) { uint32_t sum2; diff --git a/arch/x86/adler32_ssse3_p.h b/arch/x86/adler32_ssse3_p.h new file mode 100644 index 0000000000..ba914e1df5 --- /dev/null +++ b/arch/x86/adler32_ssse3_p.h @@ -0,0 +1,29 @@ +/* adler32_ssse3_p.h -- adler32 ssse3 utility functions + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_SSSE3_P_H_ +#define ADLER32_SSSE3_P_H_ + +#ifdef X86_SSSE3_ADLER32 + +#include +#include + +static inline uint32_t partial_hsum(__m128i x) { + __m128i second_int = _mm_bsrli_si128(x, 8); + __m128i sum = _mm_add_epi32(x, second_int); + return _mm_cvtsi128_si32(sum); +} + +static inline uint32_t hsum(__m128i x) { + __m128i sum1 = _mm_unpackhi_epi64(x, x); + __m128i sum2 = _mm_add_epi32(x, sum1); + __m128i sum3 = _mm_shuffle_epi32(sum2, 0x01); + __m128i sum4 = _mm_add_epi32(sum2, sum3); + return _mm_cvtsi128_si32(sum4); +} +#endif + +#endif diff --git a/arch/x86/adler32_ssse3_tpl.h b/arch/x86/adler32_ssse3_tpl.h new file mode 100644 index 0000000000..aedfa81241 --- /dev/null +++ b/arch/x86/adler32_ssse3_tpl.h @@ -0,0 +1,188 @@ +/* adler32_ssse3_tpl.h -- adler32 ssse3 vectorized function templates + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_SSSE3_TPL_H_ +#define ADLER32_SSSE3_TPL_H_ + +#include "../../zbuild.h" +#include +#include "../../adler32_fold.h" +#include "../../adler32_p.h" +#include "adler32_ssse3_p.h" + +#ifdef COPY +Z_INTERNAL void adler32_fold_copy_ssse3(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { +#else +Z_INTERNAL void adler32_fold_ssse3(adler32_fold *adler, const uint8_t *src, size_t len) { +#endif + uint32_t adler0, adler1; + + /* split Adler-32 into component sums */ + adler1 = (adler->nsums >> 16) & 0xffff; + adler0 = adler->nsums & 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (UNLIKELY(len == 1)) { +#ifdef COPY + *(dst++) = *src; +#endif + adler->nsums = adler32_len_1(adler0, src, adler1); + return; + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (UNLIKELY(src == NULL)) { + adler->nsums = 1L; + return; + } + + /* in case short lengths are provided, keep it somewhat fast */ + if (UNLIKELY(len < 16)) { + goto sub16; + } + + const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); + const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i dot3v = _mm_set1_epi16(1); + const __m128i zero = _mm_setzero_si128(); + + __m128i vbuf, vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, + vbuf_0, v_sad_sum2, vsum2, vsum2_0; + + /* If our buffer is unaligned (likely), make the determination whether + * or not there's enough of a buffer to consume to make the scalar, aligning + * additions worthwhile or if it's worth it to just eat the cost of an unaligned + * load. This is a pretty simple test, just test if 16 - the remainder + len is + * < 16 */ + size_t max_iters = NMAX; + size_t rem = (uintptr_t)src & 15; + size_t align_offset = 16 - rem; + size_t k = 0; + if (rem) { + if (len < 16 + align_offset) { + /* Let's eat the cost of this one unaligned load so that + * we don't completely skip over the vectorization. Doing + * 16 bytes at a time unaligned is is better than 16 + <= 15 + * sums */ + vbuf = _mm_loadu_si128((__m128i*)src); + len -= 16; + src += 16; +#ifdef COPY + _mm_storeu_si128((__m128i*)dst, vbuf); + dst += 16; +#endif + vs1 = _mm_cvtsi32_si128(adler0); + vs2 = _mm_cvtsi32_si128(adler1); + vs3 = _mm_setzero_si128(); + vs1_0 = vs1; + goto unaligned_jmp; + } + +#ifdef COPY + memcpy(dst, src, align_offset); + dst += align_offset; +#endif + for (size_t i = 0; i < align_offset; ++i) { + adler0 += *(src++); + adler1 += adler0; + } + + /* lop off the max number of sums based on the scalar sums done + * above */ + len -= align_offset; + max_iters -= align_offset; + } + + + while (len >= 16) { + vs1 = _mm_cvtsi32_si128(adler0); + vs2 = _mm_cvtsi32_si128(adler1); + vs3 = _mm_setzero_si128(); + vs2_0 = _mm_setzero_si128(); + vs1_0 = vs1; + + k = (len < max_iters ? len : max_iters); + k -= k % 16; + len -= k; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_load_si128((__m128i*)src); + vbuf_0 = _mm_load_si128((__m128i*)(src + 16)); + src += 32; + k -= 32; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); +#ifdef COPY + _mm_storeu_si128((__m128i*)dst, vbuf); + _mm_storeu_si128((__m128i*)(dst + 16), vbuf_0); + dst += 32; +#endif + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + + vs1 = _mm_add_epi32(v_sad_sum2, vs1); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); + vs2 = _mm_add_epi32(vsum2, vs2); + vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); + vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); + vs1_0 = vs1; + } + + vs2 = _mm_add_epi32(vs2_0, vs2); + vs3 = _mm_slli_epi32(vs3, 5); + vs2 = _mm_add_epi32(vs3, vs2); + vs3 = _mm_setzero_si128(); + + while (k >= 16) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_load_si128((__m128i*)src); + src += 16; + k -= 16; + +unaligned_jmp: + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); +#ifdef COPY + _mm_storeu_si128((__m128i*)dst, vbuf); + dst += 16; +#endif + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + vs3 = _mm_slli_epi32(vs3, 4); + vs2 = _mm_add_epi32(vs2, vs3); + + /* We don't actually need to do a full horizontal sum, since psadbw is actually doing + * a partial reduction sum implicitly and only summing to integers in vector positions + * 0 and 2. This saves us some contention on the shuffle port(s) */ + adler0 = partial_hsum(vs1) % BASE; + adler1 = hsum(vs2) % BASE; + max_iters = NMAX; + } + +sub16: +#ifdef COPY + adler->nsums = adler32_copy_len_16(adler0, src, dst, len, adler1); +#else + /* Process tail (len < 16). */ + adler->nsums = adler32_len_16(adler0, src, len, adler1); +#endif +} + +#endif diff --git a/configure b/configure index 6f79825a7f..b90c2342fc 100755 --- a/configure +++ b/configure @@ -1495,16 +1495,16 @@ case "${ARCH}" in check_sse42_intrinsics if test ${HAVE_SSE42CRC_INTRIN} -eq 1 || test ${HAVE_SSE42CRC_INLINE_ASM} -eq 1; then - CFLAGS="${CFLAGS} -DX86_SSE42_CRC_HASH" - SFLAGS="${SFLAGS} -DX86_SSE42_CRC_HASH" + CFLAGS="${CFLAGS} -DX86_SSE42_CRC_HASH -DX86_SSE42_ADLER32" + SFLAGS="${SFLAGS} -DX86_SSE42_CRC_HASH -DX86_SSE42_ADLER32" if test ${HAVE_SSE42CRC_INTRIN} -eq 1; then CFLAGS="${CFLAGS} -DX86_SSE42_CRC_INTRIN" SFLAGS="${SFLAGS} -DX86_SSE42_CRC_INTRIN" fi - ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} insert_string_sse42.o" - ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} insert_string_sse42.lo" + ARCH_STATIC_OBJS="${ARCH_STATIC_OBJS} adler32_sse42.o insert_string_sse42.o" + ARCH_SHARED_OBJS="${ARCH_SHARED_OBJS} adler32_sse42.lo insert_string_sse42.lo" fi check_sse2_intrinsics diff --git a/cpu_features.h b/cpu_features.h index d3df33b9f6..3dfaf6ce2e 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -7,6 +7,7 @@ #define CPU_FEATURES_H_ #include "crc32_fold.h" +#include "adler32_fold.h" #if defined(X86_FEATURES) # include "arch/x86/x86_features.h" @@ -34,6 +35,12 @@ extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len #ifdef X86_SSSE3_ADLER32 extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); #endif +#ifdef X86_SSE42_ADLER32 +extern void adler32_fold_reset_sse42(adler32_fold *adler, uint32_t init_adler); +extern void adler32_fold_copy_sse42(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); +extern void adler32_fold_sse42(adler32_fold *adler, const uint8_t *src, size_t len); +extern uint32_t adler32_fold_final_sse42(adler32_fold *adler); +#endif #ifdef X86_AVX2_ADLER32 extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); #endif diff --git a/deflate.c b/deflate.c index a98988a831..6818a860a0 100644 --- a/deflate.c +++ b/deflate.c @@ -448,7 +448,11 @@ int32_t Z_EXPORT PREFIX(deflateResetKeep)(PREFIX3(stream) *strm) { strm->adler = functable.crc32_fold_reset(&s->crc_fold); else #endif + //strm->adler = ADLER32_INITIAL_VALUE; + { strm->adler = ADLER32_INITIAL_VALUE; + functable.adler32_fold_reset(&s->adler_fold, ADLER32_INITIAL_VALUE); + } s->last_flush = -2; zng_tr_init(s); @@ -767,6 +771,7 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { if (s->strstart != 0) put_uint32_msb(s, strm->adler); strm->adler = ADLER32_INITIAL_VALUE; + functable.adler32_fold_reset(&s->adler_fold, ADLER32_INITIAL_VALUE); s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ @@ -973,8 +978,11 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { put_uint32(s, (uint32_t)strm->total_in); } else #endif - if (s->wrap == 1) - put_uint32_msb(s, strm->adler); + { + strm->adler = functable.adler32_fold_final(&s->adler_fold); + if (s->wrap == 1) + put_uint32_msb(s, strm->adler); + } PREFIX(flush_pending)(strm); /* If avail_out is zero, the application will call deflate again * to flush the rest. @@ -1083,9 +1091,11 @@ Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned functable.crc32_fold_copy(&strm->state->crc_fold, buf, strm->next_in, len); #endif } else { - memcpy(buf, strm->next_in, len); if (strm->state->wrap == 1) - strm->adler = functable.adler32(strm->adler, buf, len); + functable.adler32_fold_copy(&strm->state->adler_fold, buf, strm->next_in, len); + else + memcpy(buf, strm->next_in, len); + //strm->adler = functable.adler32(strm->adler, buf, len); } strm->next_in += len; strm->total_in += len; diff --git a/deflate.h b/deflate.h index b5ae2f8e66..2d34c95edf 100644 --- a/deflate.h +++ b/deflate.h @@ -10,6 +10,7 @@ subject to change. Applications should only use zlib.h. */ +#include "adler32_fold.h" #include "zutil.h" #include "zendian.h" #include "crc32_fold.h" @@ -211,6 +212,7 @@ struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ + struct adler32_fold_s ALIGNED_(64) adler_fold; struct crc32_fold_s ALIGNED_(16) crc_fold; /* used by trees.c: */ diff --git a/functable.c b/functable.c index 317349f303..a2c75c9fcf 100644 --- a/functable.c +++ b/functable.c @@ -204,21 +204,37 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ Z_INTERNAL void adler32_fold_reset_stub(adler32_fold *adler, uint32_t init_adler) { functable.adler32_fold_reset = &adler32_fold_reset_c; +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX2_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) + if (x86_cpu_has_sse42) + functable.adler32_fold_reset = &adler32_fold_reset_sse42; +#endif functable.adler32_fold_reset(adler, init_adler); } Z_INTERNAL void adler32_fold_copy_stub(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { functable.adler32_fold_copy = &adler32_fold_copy_c; +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX2_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) + if (x86_cpu_has_sse42) + functable.adler32_fold_copy = &adler32_fold_copy_sse42; +#endif functable.adler32_fold_copy(adler, dst, src, len); } Z_INTERNAL void adler32_fold_stub(adler32_fold *adler, const uint8_t *src, size_t len) { functable.adler32_fold = &adler32_fold_c; +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX2_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) + if (x86_cpu_has_sse42) + functable.adler32_fold = &adler32_fold_sse42; +#endif functable.adler32_fold(adler, src, len); } Z_INTERNAL uint32_t adler32_fold_final_stub(adler32_fold *adler) { functable.adler32_fold_final = &adler32_fold_final_c; +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX2_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) + if (x86_cpu_has_sse42) + functable.adler32_fold_final = &adler32_fold_final_sse42; +#endif return functable.adler32_fold_final(adler); } diff --git a/inflate.c b/inflate.c index 9e816a40d8..864ca8882c 100644 --- a/inflate.c +++ b/inflate.c @@ -20,6 +20,7 @@ static uint32_t syncsearch(uint32_t *have, const unsigned char *buf, uint32_t le static inline void inf_chksum_cpy(PREFIX3(stream) *strm, uint8_t *dst, const uint8_t *src, uint32_t copy) { + if (!copy) return; struct inflate_state *state = (struct inflate_state*)strm->state; #ifdef GUNZIP if (state->flags) { diff --git a/win32/Makefile.msc b/win32/Makefile.msc index b121cde22c..bce5c00449 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -30,9 +30,12 @@ WFLAGS = \ -DX86_FEATURES \ -DX86_PCLMULQDQ_CRC \ -DX86_SSE2 \ + -DX86_SSE42_ADLER32 \ -DX86_SSE42_CRC_INTRIN \ -DX86_SSE42_CRC_HASH \ + -DX86_SSSE3_ADLER32 \ -DX86_AVX2 \ + -DX86_AVX2_ADLER32 \ -DX86_AVX_CHUNKSET \ -DX86_SSE2_CHUNKSET \ # @@ -48,6 +51,11 @@ SUFFIX = OBJS = \ adler32.obj \ + adler32_avx2.obj \ + adler32_avx512.obj \ + adler32_avx512_vnni.obj \ + adler32_sse42.obj \ + adler32_ssse3.obj \ adler32_fold.obj \ chunkset.obj \ chunkset_avx.obj \ @@ -182,6 +190,13 @@ $(TOP)/zconf$(SUFFIX).h: zconf SRCDIR = $(TOP) # Keep the dependences in sync with top-level Makefile.in adler32.obj: $(SRCDIR)/adler32.c $(SRCDIR)/zbuild.h $(SRCDIR)/zutil.h $(SRCDIR)/functable.h $(SRCDIR)/adler32_p.h +adler32_avx2.obj: $(SRCDIR)/arch/x86/adler32_avx2.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/fallback_builtins.h +adler32_avx512.obj: $(SRCDIR)/arch/x86/adler32_avx512.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/arch/x86/adler32_avx512_p.h +adler32_avx512_vnni.obj: $(SRCDIR)/arch/x86/adler32_avx512_vnni.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/arch/x86/adler32_avx512_p.h +adler32_sse42.obj: $(SRCDIR)/arch/x86/adler32_sse42.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/adler32_fold.h \ + $(SRCDIR)/arch/x86/adler32_ssse3_p.h $(SRCDIR)/arch/x86/adler32_sse42_tpl.h +adler32_ssse3.obj: $(SRCDIR)/arch/x86/adler32_ssse3.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/adler32_fold.h \ + $(SRCDIR)/arch/x86/adler32_ssse3_p.h adler32_fold.obj: $(SRCDIR)/adler32_fold.c $(SRCDIR)/zbuild.h $(SRCDIR)/adler32_fold.h $(SRCDIR)/functable.h functable.obj: $(SRCDIR)/functable.c $(SRCDIR)/zbuild.h $(SRCDIR)/functable.h $(SRCDIR)/deflate.h $(SRCDIR)/deflate_p.h $(SRCDIR)/zendian.h $(SRCDIR)/arch/x86/x86_features.h gzlib.obj: $(SRCDIR)/gzlib.c $(SRCDIR)/zbuild.h $(SRCDIR)/gzguts.h $(SRCDIR)/zutil_p.h From 2f2b7e9d6972dcba001c02aedb758a991b82b30d Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Wed, 6 Apr 2022 15:38:20 -0400 Subject: [PATCH 405/798] Add AVX2 inline copy + adler implementation This was pretty much across the board wins for performance, but the wins are very data dependent and it sort of depends on what copy runs look like. On our less than realistic data in benchmark_zlib_apps, the decode test saw some of the bigger gains, ranging anywhere from 6 to 11% when compiled with AVX2 on a Cascade Lake CPU (and with only AVX2 enabled). The decode on realistic imagery enjoyed smaller gains, somewhere between 2 and 4%. Interestingly, there was one outlier on encode, at level 5. The best theory for this is that the copy runs for that particular compression level were such that glibc's ERMS aware memmove implementation managed to marginally outpace the copy during the checksum with the move rep str sequence thanks to clever microcoding on Intel's part. It's hard to say for sure but the most standout difference between the two perf profiles was more time spent in memmove (which is expected, as it's calling memcpy instead of copying the bytes during the checksum). There's the distinct possibility that the AVX2 checksums could be marginally improved by one level of unrolling (like what's done in the SSE3 implementation). The AVX512 implementations are certainly getting gains from this but it's not appropriate to append this optimization in this series of commits. --- arch/x86/adler32_avx2.c | 134 +++++---------------------------- arch/x86/adler32_avx2_p.h | 32 ++++++++ arch/x86/adler32_avx2_tpl.h | 143 ++++++++++++++++++++++++++++++++++++ cpu_features.h | 4 + functable.c | 24 +++++- 5 files changed, 217 insertions(+), 120 deletions(-) create mode 100644 arch/x86/adler32_avx2_p.h create mode 100644 arch/x86/adler32_avx2_tpl.h diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index 50cea317ec..be7bd6f038 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -8,132 +8,34 @@ #include "../../zbuild.h" #include "../../adler32_p.h" #include "../../fallback_builtins.h" +#include "adler32_avx2_p.h" +#include "../../adler32_fold.h" #include #ifdef X86_AVX2_ADLER32 -/* 32 bit horizontal sum, adapted from Agner Fog's vector library. */ -static inline uint32_t hsum(__m256i x) { - __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(x, 1), - _mm256_castsi256_si128(x)); - __m128i sum2 = _mm_add_epi32(sum1, _mm_unpackhi_epi64(sum1, sum1)); - __m128i sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1)); - return (uint32_t)_mm_cvtsi128_si32(sum3); +Z_INTERNAL void adler32_fold_reset_avx2(adler32_fold *adler, uint32_t init_adler) { + adler->nsums = init_adler; } -static inline uint32_t partial_hsum(__m256i x) { - /* We need a permutation vector to extract every other integer. The - * rest are going to be zeros */ - const __m256i perm_vec = _mm256_setr_epi32(0, 2, 4, 6, 1, 1, 1, 1); - __m256i non_zero = _mm256_permutevar8x32_epi32(x, perm_vec); - __m128i non_zero_sse = _mm256_castsi256_si128(non_zero); - __m128i sum2 = _mm_add_epi32(non_zero_sse,_mm_unpackhi_epi64(non_zero_sse, non_zero_sse)); - __m128i sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1)); - return (uint32_t)_mm_cvtsi128_si32(sum3); +Z_INTERNAL uint32_t adler32_fold_final_avx2(adler32_fold *adler) { + return adler->nsums; } -Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len) { - uint32_t sum2; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) - return adler32_len_1(adler, buf, sum2); - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (UNLIKELY(buf == NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (UNLIKELY(len < 16)) - return adler32_len_16(adler, buf, len, sum2); - - __m256i vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler)); - __m256i vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(sum2)); - - const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, - 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); - const __m256i dot3v = _mm256_set1_epi16(1); - const __m256i zero = _mm256_setzero_si256(); - - while (len >= 32) { - __m256i vs1_0 = vs1; - __m256i vs3 = _mm256_setzero_si256(); - - int k = (len < NMAX ? (int)len : NMAX); - k -= k % 32; - len -= k; - - while (k >= 32) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 32 vs1 + sum( (32-i+1) c[i] ) - */ - __m256i vbuf = _mm256_loadu_si256((__m256i*)buf); - buf += 32; - k -= 32; - - __m256i vs1_sad = _mm256_sad_epu8(vbuf, zero); // Sum of abs diff, resulting in 2 x int32's - vs1 = _mm256_add_epi32(vs1, vs1_sad); - vs3 = _mm256_add_epi32(vs3, vs1_0); - __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); // sum 32 uint8s to 16 shorts - __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); // sum 16 shorts to 8 uint32s - vs2 = _mm256_add_epi32(vsum2, vs2); - vs1_0 = vs1; - } +#include "adler32_avx2_tpl.h" +#undef ADLER32_AVX2_TPL_H_ +#define COPY +#include "adler32_avx2_tpl.h" +#undef COPY - /* Defer the multiplication with 32 to outside of the loop */ - vs3 = _mm256_slli_epi32(vs3, 5); - vs2 = _mm256_add_epi32(vs2, vs3); - - /* The compiler is generating the following sequence for this integer modulus - * when done the scalar way, in GPRs: - - adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + - (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); - - mov $0x80078071,%edi // move magic constant into 32 bit register %edi - ... - vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi - mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax - imul %rdi,%rsi // do a signed multiplication with magic constant and vector element - shr $0x2f,%rsi // shift right by 47 - imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 - sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above - ... - // repeats for each element with vpextract instructions - - This is tricky with AVX2 for a number of reasons: - 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there - 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate - back down to 32 bit precision later (there is in AVX512) - 3.) Full width integer multiplications aren't cheap - - We can, however, and do a relatively cheap sequence for horizontal sums. - Then, we simply do the integer modulus on the resulting 64 bit GPR, on a scalar value. It was - previously thought that casting to 64 bit precision was needed prior to the horizontal sum, but - that is simply not the case, as NMAX is defined as the maximum number of scalar sums that can be - performed on the maximum possible inputs before overflow - */ - - - /* In AVX2-land, this trip through GPRs will probably be unvoidable, as there's no cheap and easy - * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). - * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly - * what the compiler is doing to avoid integer divisions. */ - adler = partial_hsum(vs1) % BASE; - sum2 = hsum(vs2) % BASE; - - vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler)); - vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(sum2)); - } - - /* Process tail (len < 16). */ - return adler32_len_16(adler, buf, len, sum2); +Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len) { + if (buf == NULL) return 1L; + if (len == 0) return adler; + ALIGNED_(64) adler32_fold fold; + adler32_fold_reset_avx2(&fold, adler); + adler32_fold_avx2(&fold, buf, len); + return adler32_fold_final_avx2(&fold); } #endif diff --git a/arch/x86/adler32_avx2_p.h b/arch/x86/adler32_avx2_p.h new file mode 100644 index 0000000000..1c80bde057 --- /dev/null +++ b/arch/x86/adler32_avx2_p.h @@ -0,0 +1,32 @@ +/* adler32_avx2_p.h -- adler32 avx2 utility functions + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_AVX2_P_H_ +#define ADLER32_AVX2_P_H_ + +#ifdef X86_AVX2_ADLER32 + +/* 32 bit horizontal sum, adapted from Agner Fog's vector library. */ +static inline uint32_t hsum(__m256i x) { + __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(x, 1), + _mm256_castsi256_si128(x)); + __m128i sum2 = _mm_add_epi32(sum1, _mm_unpackhi_epi64(sum1, sum1)); + __m128i sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} + +static inline uint32_t partial_hsum(__m256i x) { + /* We need a permutation vector to extract every other integer. The + * rest are going to be zeros */ + const __m256i perm_vec = _mm256_setr_epi32(0, 2, 4, 6, 1, 1, 1, 1); + __m256i non_zero = _mm256_permutevar8x32_epi32(x, perm_vec); + __m128i non_zero_sse = _mm256_castsi256_si128(non_zero); + __m128i sum2 = _mm_add_epi32(non_zero_sse,_mm_unpackhi_epi64(non_zero_sse, non_zero_sse)); + __m128i sum3 = _mm_add_epi32(sum2, _mm_shuffle_epi32(sum2, 1)); + return (uint32_t)_mm_cvtsi128_si32(sum3); +} +#endif + +#endif diff --git a/arch/x86/adler32_avx2_tpl.h b/arch/x86/adler32_avx2_tpl.h new file mode 100644 index 0000000000..ff571672b4 --- /dev/null +++ b/arch/x86/adler32_avx2_tpl.h @@ -0,0 +1,143 @@ +/* adler32_avx2_tpl.h -- adler32 avx2 vectorized function templates + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_AVX2_TPL_H_ +#define ADLER32_AVX2_TPL_H_ + +#include "../../zbuild.h" +#include +#include "../../adler32_fold.h" +#include "../../adler32_p.h" +#include "../../fallback_builtins.h" +#include "adler32_avx2_p.h" + +#ifdef X86_SSE42_ADLER32 +extern void adler32_fold_copy_sse42(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); +extern void adler32_fold_sse42(adler32_fold *adler, const uint8_t *src, size_t len); +#define copy_sub32(a, b, c, d) adler32_fold_copy_sse42(a, b, c, d) +#define sub32(a, b, c) adler32_fold_sse42(a, b, c) +#else +#define copy_sub32(a, b, c, d) do { a->nsums = adler32_copy_len_16(adler0, c, b, d, adler1); } while (0) +#define sub32(a, b, c) do { a->nsums = adler32_len_16(adler0, b, c, adler1); } while (0) +#endif + +#ifdef COPY +Z_INTERNAL void adler32_fold_copy_avx2(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { +#else +Z_INTERNAL void adler32_fold_avx2(adler32_fold *adler, const uint8_t *src, size_t len) { +#endif + + uint32_t adler0, adler1; + adler1 = (adler->nsums >> 16) & 0xffff; + adler0 = adler->nsums & 0xffff; + +rem_peel: + if (len < 16) { +#ifdef COPY + adler->nsums = adler32_copy_len_16(adler0, src, dst, len, adler1); +#else + adler->nsums = adler32_len_16(adler0, src, len, adler1); +#endif + return; + } else if (len < 32) { +#ifdef COPY + copy_sub32(adler, dst, src, len); +#else + sub32(adler, src, len); +#endif + return; + } + + __m256i vs1, vs2; + + const __m256i dot2v = _mm256_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m256i dot3v = _mm256_set1_epi16(1); + const __m256i zero = _mm256_setzero_si256(); + + while (len >= 32) { + vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0)); + vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1)); + __m256i vs1_0 = vs1; + __m256i vs3 = _mm256_setzero_si256(); + + size_t k = (len < NMAX ? len : NMAX); + k -= k % 32; + len -= k; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 32 vs1 + sum( (32-i+1) c[i] ) + */ + __m256i vbuf = _mm256_loadu_si256((__m256i*)src); + src += 32; + k -= 32; + + __m256i vs1_sad = _mm256_sad_epu8(vbuf, zero); // Sum of abs diff, resulting in 2 x int32's + // +#ifdef COPY + _mm256_storeu_si256((__m256i*)dst, vbuf); + dst += 32; +#endif + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs3 = _mm256_add_epi32(vs3, vs1_0); + __m256i v_short_sum2 = _mm256_maddubs_epi16(vbuf, dot2v); // sum 32 uint8s to 16 shorts + __m256i vsum2 = _mm256_madd_epi16(v_short_sum2, dot3v); // sum 16 shorts to 8 uint32s + vs2 = _mm256_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + /* Defer the multiplication with 32 to outside of the loop */ + vs3 = _mm256_slli_epi32(vs3, 5); + vs2 = _mm256_add_epi32(vs2, vs3); + + /* The compiler is generating the following sequence for this integer modulus + * when done the scalar way, in GPRs: + + adler = (s1_unpack[0] % BASE) + (s1_unpack[1] % BASE) + (s1_unpack[2] % BASE) + (s1_unpack[3] % BASE) + + (s1_unpack[4] % BASE) + (s1_unpack[5] % BASE) + (s1_unpack[6] % BASE) + (s1_unpack[7] % BASE); + + mov $0x80078071,%edi // move magic constant into 32 bit register %edi + ... + vmovd %xmm1,%esi // move vector lane 0 to 32 bit register %esi + mov %rsi,%rax // zero-extend this value to 64 bit precision in %rax + imul %rdi,%rsi // do a signed multiplication with magic constant and vector element + shr $0x2f,%rsi // shift right by 47 + imul $0xfff1,%esi,%esi // do a signed multiplication with value truncated to 32 bits with 0xfff1 + sub %esi,%eax // subtract lower 32 bits of original vector value from modified one above + ... + // repeats for each element with vpextract instructions + + This is tricky with AVX2 for a number of reasons: + 1.) There's no 64 bit multiplication instruction, but there is a sequence to get there + 2.) There's ways to extend vectors to 64 bit precision, but no simple way to truncate + back down to 32 bit precision later (there is in AVX512) + 3.) Full width integer multiplications aren't cheap + + We can, however, and do a relatively cheap sequence for horizontal sums. + Then, we simply do the integer modulus on the resulting 64 bit GPR, on a scalar value. It was + previously thought that casting to 64 bit precision was needed prior to the horizontal sum, but + that is simply not the case, as NMAX is defined as the maximum number of scalar sums that can be + performed on the maximum possible inputs before overflow + */ + + + /* In AVX2-land, this trip through GPRs will probably be unvoidable, as there's no cheap and easy + * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). + * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly + * what the compiler is doing to avoid integer divisions. */ + adler0 = partial_hsum(vs1) % BASE; + adler1 = hsum(vs2) % BASE; + } + + adler->nsums = adler0 | (adler1 << 16); + + if (len) { + goto rem_peel; + } +} + +#endif diff --git a/cpu_features.h b/cpu_features.h index 3dfaf6ce2e..dbabb3ac9f 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -43,6 +43,10 @@ extern uint32_t adler32_fold_final_sse42(adler32_fold *adler); #endif #ifdef X86_AVX2_ADLER32 extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); +extern void adler32_fold_reset_avx2(adler32_fold *adler, uint32_t init_adler); +extern void adler32_fold_copy_avx2(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); +extern void adler32_fold_avx2(adler32_fold *adler, const uint8_t *src, size_t len); +extern uint32_t adler32_fold_final_avx2(adler32_fold *adler); #endif #ifdef X86_AVX512_ADLER32 extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len); diff --git a/functable.c b/functable.c index a2c75c9fcf..097c7b2459 100644 --- a/functable.c +++ b/functable.c @@ -204,36 +204,52 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ Z_INTERNAL void adler32_fold_reset_stub(adler32_fold *adler, uint32_t init_adler) { functable.adler32_fold_reset = &adler32_fold_reset_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX2_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) if (x86_cpu_has_sse42) functable.adler32_fold_reset = &adler32_fold_reset_sse42; +#ifdef X86_AVX2_ADLER32 + if (x86_cpu_has_avx2) + functable.adler32_fold_reset = &adler32_fold_reset_avx2; +#endif #endif functable.adler32_fold_reset(adler, init_adler); } Z_INTERNAL void adler32_fold_copy_stub(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { functable.adler32_fold_copy = &adler32_fold_copy_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX2_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) if (x86_cpu_has_sse42) functable.adler32_fold_copy = &adler32_fold_copy_sse42; +#endif +#ifdef X86_AVX2_ADLER32 + if (x86_cpu_has_avx2) + functable.adler32_fold_copy = &adler32_fold_copy_avx2; #endif functable.adler32_fold_copy(adler, dst, src, len); } Z_INTERNAL void adler32_fold_stub(adler32_fold *adler, const uint8_t *src, size_t len) { functable.adler32_fold = &adler32_fold_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX2_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) if (x86_cpu_has_sse42) functable.adler32_fold = &adler32_fold_sse42; +#endif +#ifdef X86_AVX2_ADLER32 + if (x86_cpu_has_avx2) + functable.adler32_fold = &adler32_fold_avx2; #endif functable.adler32_fold(adler, src, len); } Z_INTERNAL uint32_t adler32_fold_final_stub(adler32_fold *adler) { functable.adler32_fold_final = &adler32_fold_final_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX2_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) if (x86_cpu_has_sse42) functable.adler32_fold_final = &adler32_fold_final_sse42; +#endif +#ifdef X86_AVX2_ADLER32 + if (x86_cpu_has_avx2) + functable.adler32_fold_final = &adler32_fold_final_avx2; #endif return functable.adler32_fold_final(adler); } From b8269bb7d4702f8e694441112bb4ba7c59ff2362 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Thu, 7 Apr 2022 22:57:09 -0400 Subject: [PATCH 406/798] Added inlined AVX512 adler checksum + copy While we're here, also simplfy the "fold" signature, as reducing the number of rebases and horizontal sums did not prove to be meaningfully faster (slower in many circumstances). --- adler32_fold.c | 21 +----- adler32_fold.h | 13 +--- arch/x86/adler32_avx2.c | 16 ++--- arch/x86/adler32_avx2_tpl.h | 36 +++++----- arch/x86/adler32_avx512.c | 88 ++--------------------- arch/x86/adler32_avx512_tpl.h | 110 ++++++++++++++++++++++++++++ arch/x86/adler32_sse42.c | 113 ++++++++++++++++++++++++++--- arch/x86/adler32_sse42_tpl.h | 132 ---------------------------------- cpu_features.h | 11 +-- deflate.c | 15 ++-- deflate.h | 1 - functable.c | 50 ++----------- functable.h | 5 +- inflate.c | 12 +--- inflate.h | 1 - win32/Makefile.msc | 2 +- 16 files changed, 262 insertions(+), 364 deletions(-) create mode 100644 arch/x86/adler32_avx512_tpl.h delete mode 100644 arch/x86/adler32_sse42_tpl.h diff --git a/adler32_fold.c b/adler32_fold.c index 3f745cd9c6..688f848533 100644 --- a/adler32_fold.c +++ b/adler32_fold.c @@ -7,24 +7,7 @@ #include "functable.h" #include "adler32_fold.h" -Z_INTERNAL void adler32_fold_reset_c(adler32_fold *adler, uint32_t init_adler) { - /* So, for the "C" version, we'll just stash the value into nsums. - * This is mostly a compatibility shim, these functions in the functable - * will have more optimal versions that make use of adler and sum2. In order - * to make each implementation bisectable, each new implementation will be a - * new commit */ - adler->nsums = init_adler; -} - -Z_INTERNAL void adler32_fold_copy_c(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { - adler->nsums = functable.adler32(adler->nsums, src, len); +Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { memcpy(dst, src, len); -} - -Z_INTERNAL void adler32_fold_c(adler32_fold *adler, const uint8_t *src, size_t len) { - adler->nsums = functable.adler32(adler->nsums, src, len); -} - -Z_INTERNAL uint32_t adler32_fold_final_c(adler32_fold *adler) { - return adler->nsums; + return functable.adler32(adler, src, len); } diff --git a/adler32_fold.h b/adler32_fold.h index ec4270a7ab..ea456adc31 100644 --- a/adler32_fold.h +++ b/adler32_fold.h @@ -8,17 +8,6 @@ #include -typedef struct adler32_fold_s { - uint8_t adler[64]; // First half of component sums - uint8_t sum2[64]; // Second half of component sums - uint8_t leftover[16]; // A buffer for sub 16 sized carry over, sized for full loads and alignment - uint32_t nsums; // The number of scalar sums leftover - uint32_t bytes_leftover; // The number of leftover bytes from the previous sum -} adler32_fold; - -Z_INTERNAL void adler32_fold_reset_c(adler32_fold *adler, uint32_t init_adler); -Z_INTERNAL void adler32_fold_copy_c(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); -Z_INTERNAL void adler32_fold_c(adler32_fold *adler, const uint8_t *src, size_t len); -Z_INTERNAL uint32_t adler32_fold_final_c(adler32_fold *adler); +Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index be7bd6f038..fcca34ec53 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -10,32 +10,24 @@ #include "../../fallback_builtins.h" #include "adler32_avx2_p.h" #include "../../adler32_fold.h" +#include #include #ifdef X86_AVX2_ADLER32 -Z_INTERNAL void adler32_fold_reset_avx2(adler32_fold *adler, uint32_t init_adler) { - adler->nsums = init_adler; -} - -Z_INTERNAL uint32_t adler32_fold_final_avx2(adler32_fold *adler) { - return adler->nsums; -} - #include "adler32_avx2_tpl.h" #undef ADLER32_AVX2_TPL_H_ #define COPY #include "adler32_avx2_tpl.h" #undef COPY +/* Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len) { if (buf == NULL) return 1L; if (len == 0) return adler; - ALIGNED_(64) adler32_fold fold; - adler32_fold_reset_avx2(&fold, adler); - adler32_fold_avx2(&fold, buf, len); - return adler32_fold_final_avx2(&fold); + return adler32_fold_avx2(adler, buf, len); } +*/ #endif diff --git a/arch/x86/adler32_avx2_tpl.h b/arch/x86/adler32_avx2_tpl.h index ff571672b4..7df51d573d 100644 --- a/arch/x86/adler32_avx2_tpl.h +++ b/arch/x86/adler32_avx2_tpl.h @@ -14,40 +14,40 @@ #include "adler32_avx2_p.h" #ifdef X86_SSE42_ADLER32 -extern void adler32_fold_copy_sse42(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); -extern void adler32_fold_sse42(adler32_fold *adler, const uint8_t *src, size_t len); +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +extern uint32_t adler32_ssse3(uint32_t adler, const uint8_t *src, size_t len); #define copy_sub32(a, b, c, d) adler32_fold_copy_sse42(a, b, c, d) -#define sub32(a, b, c) adler32_fold_sse42(a, b, c) +#define sub32(a, b, c) adler32_ssse3(a, b, c) #else -#define copy_sub32(a, b, c, d) do { a->nsums = adler32_copy_len_16(adler0, c, b, d, adler1); } while (0) -#define sub32(a, b, c) do { a->nsums = adler32_len_16(adler0, b, c, adler1); } while (0) +#define copy_sub32(a, b, c, d) adler32_copy_len_16(adler0, c, b, d, adler1) +#define sub32(a, b, c) adler32_len_16(adler0, b, c, adler1) #endif #ifdef COPY -Z_INTERNAL void adler32_fold_copy_avx2(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { #else -Z_INTERNAL void adler32_fold_avx2(adler32_fold *adler, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) { #endif + if (src == NULL) return 1L; + if (len == 0) return adler; uint32_t adler0, adler1; - adler1 = (adler->nsums >> 16) & 0xffff; - adler0 = adler->nsums & 0xffff; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; rem_peel: if (len < 16) { #ifdef COPY - adler->nsums = adler32_copy_len_16(adler0, src, dst, len, adler1); + return adler32_copy_len_16(adler0, src, dst, len, adler1); #else - adler->nsums = adler32_len_16(adler0, src, len, adler1); + return adler32_len_16(adler0, src, len, adler1); #endif - return; } else if (len < 32) { #ifdef COPY - copy_sub32(adler, dst, src, len); + return copy_sub32(adler, dst, src, len); #else - sub32(adler, src, len); + return sub32(adler, src, len); #endif - return; } __m256i vs1, vs2; @@ -63,7 +63,7 @@ Z_INTERNAL void adler32_fold_avx2(adler32_fold *adler, const uint8_t *src, size_ __m256i vs1_0 = vs1; __m256i vs3 = _mm256_setzero_si256(); - size_t k = (len < NMAX ? len : NMAX); + size_t k = MIN(len, NMAX); k -= k % 32; len -= k; @@ -133,11 +133,13 @@ Z_INTERNAL void adler32_fold_avx2(adler32_fold *adler, const uint8_t *src, size_ adler1 = hsum(vs2) % BASE; } - adler->nsums = adler0 | (adler1 << 16); + adler = adler0 | (adler1 << 16); if (len) { goto rem_peel; } + + return adler; } #endif diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index 5571be45eb..e26b9cc524 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -12,90 +12,14 @@ #include "../../fallback_builtins.h" #include #include "adler32_avx512_p.h" +#include "../../adler32_fold.h" #ifdef X86_AVX512_ADLER32 -Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len) { - uint32_t sum2; - /* For impossibly tiny sizes, use the smaller width versions. We still need - * to check for compile time support for these but they are likely there */ -#ifdef X86_SSE41_ADLER32 - if (len < 32) - return adler32_sse41(adler, buf, len); -#endif - -#ifdef X86_AVX2_ADLER32 - if (len < 64) - return adler32_avx2(adler, buf, len); -#endif - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* Only capture these corner cases if we didn't compile with SSE41 and AVX2 support - * This should make for shorter compiled code */ -#if !defined(X86_AVX2_ADLER32) && !defined(X86_SSE41_ADLER32) - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) - return adler32_len_1(adler, buf, sum2); - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (UNLIKELY(buf == NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (UNLIKELY(len < 16)) - return adler32_len_16(adler, buf, len, sum2); -#endif - - __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); - __m512i vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); - - const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64); - const __m512i dot3v = _mm512_set1_epi16(1); - const __m512i zero = _mm512_setzero_si512(); - - while (len >= 64) { - __m512i vs1_0 = vs1; - __m512i vs3 = _mm512_setzero_si512(); - - int k = (len < NMAX ? (int)len : NMAX); - k -= k % 64; - len -= k; - - while (k >= 64) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) - */ - __m512i vbuf = _mm512_loadu_si512(buf); - buf += 64; - k -= 64; - - __m512i vs1_sad = _mm512_sad_epu8(vbuf, zero); - __m512i v_short_sum2 = _mm512_maddubs_epi16(vbuf, dot2v); - vs1 = _mm512_add_epi32(vs1_sad, vs1); - vs3 = _mm512_add_epi32(vs3, vs1_0); - __m512i vsum2 = _mm512_madd_epi16(v_short_sum2, dot3v); - vs2 = _mm512_add_epi32(vsum2, vs2); - vs1_0 = vs1; - } - - vs3 = _mm512_slli_epi32(vs3, 6); - vs2 = _mm512_add_epi32(vs2, vs3); - - adler = partial_hsum(vs1) % BASE; - vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); - sum2 = _mm512_reduce_add_epu32(vs2) % BASE; - vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); - } - - /* Process tail (len < 64). */ - return adler32_len_16(adler, buf, len, sum2); -} +#include "adler32_avx512_tpl.h" +#undef ADLER32_AVX512_TPL_H_ +#define COPY +#include "adler32_avx512_tpl.h" +#undef COPY #endif diff --git a/arch/x86/adler32_avx512_tpl.h b/arch/x86/adler32_avx512_tpl.h new file mode 100644 index 0000000000..df5dd3810f --- /dev/null +++ b/arch/x86/adler32_avx512_tpl.h @@ -0,0 +1,110 @@ +/* adler32_avx512_tpl.h -- adler32 avx512 vectorized function templates + * Copyright (C) 2022 Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef ADLER32_AVX512_TPL_H_ +#define ADLER32_AVX512_TPL_H_ + +#include "../../zbuild.h" +#include "../../adler32_p.h" +#include "../../cpu_features.h" +#include "../../fallback_builtins.h" +#include +#include "adler32_avx512_p.h" +#include "../../adler32_fold.h" + +#ifdef X86_AVX512_ADLER32 + +#ifdef COPY +Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { +#else +Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t len) { +#endif + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + + if (src == NULL) return 1L; + if (len == 0) return adler; + +rem_peel: + if (len < 64) { + /* This handles the remaining copies, just call normal adler checksum after this */ +#ifdef COPY + __mmask64 storemask = (0xFFFFFFFFFFFFFFFFUL >> (64 - len)); + __m512i copy_vec = _mm512_maskz_loadu_epi8(storemask, src); + _mm512_mask_storeu_epi8(dst, storemask, copy_vec); +#endif + +#ifdef X86_AVX2_ADLER32 + return adler32_avx2(adler, src, len); +#elif defined(X86_SSSE3_ADLER32) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); +#endif + } + + __m512i vbuf, vs1_0, vs3; + + const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64); + const __m512i dot3v = _mm512_set1_epi16(1); + const __m512i zero = _mm512_setzero_si512(); + size_t k; + + while (len >= 64) { + __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); + __m512i vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1)); + vs1_0 = vs1; + vs3 = _mm512_setzero_si512(); + + k = MIN(len, NMAX); + k -= k % 64; + len -= k; + + while (k >= 64) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + vbuf = _mm512_loadu_si512(src); +#ifdef COPY + _mm512_storeu_si512(dst, vbuf); + dst += 64; +#endif + src += 64; + k -= 64; + + __m512i vs1_sad = _mm512_sad_epu8(vbuf, zero); + __m512i v_short_sum2 = _mm512_maddubs_epi16(vbuf, dot2v); + vs1 = _mm512_add_epi32(vs1_sad, vs1); + vs3 = _mm512_add_epi32(vs3, vs1_0); + __m512i vsum2 = _mm512_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm512_add_epi32(vsum2, vs2); + vs1_0 = vs1; + } + + vs3 = _mm512_slli_epi32(vs3, 6); + vs2 = _mm512_add_epi32(vs2, vs3); + + adler0 = partial_hsum(vs1) % BASE; + adler1 = _mm512_reduce_add_epu32(vs2) % BASE; + } + + adler = adler0 | (adler1 << 16); + + /* Process tail (len < 64). */ + if (len) { + goto rem_peel; + } + + return adler; +} + +#endif +#endif diff --git a/arch/x86/adler32_sse42.c b/arch/x86/adler32_sse42.c index dce1550280..4f21702aaf 100644 --- a/arch/x86/adler32_sse42.c +++ b/arch/x86/adler32_sse42.c @@ -14,18 +14,109 @@ #ifdef X86_SSE42_ADLER32 -Z_INTERNAL void adler32_fold_reset_sse42(adler32_fold *adler, uint32_t init_adler) { - adler->nsums = init_adler; -} +Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { -Z_INTERNAL uint32_t adler32_fold_final_sse42(adler32_fold *adler) { - return adler->nsums; -} + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel: + if (len < 16) { + return adler32_copy_len_16(adler0, src, dst, len, adler1); + } + + __m128i vbuf, vbuf_0; + __m128i vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, + v_sad_sum2, vsum2, vsum2_0; + __m128i zero = _mm_setzero_si128(); + const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); + const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); + const __m128i dot3v = _mm_set1_epi16(1); + size_t k; + + while (len >= 16) { + + k = MIN(len, NMAX); + k -= k % 16; + len -= k; + + vs1 = _mm_cvtsi32_si128(adler0); + vs2 = _mm_cvtsi32_si128(adler1); + + vs3 = _mm_setzero_si128(); + vs2_0 = _mm_setzero_si128(); + vs1_0 = vs1; + + while (k >= 32) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_loadu_si128((__m128i*)src); + vbuf_0 = _mm_loadu_si128((__m128i*)(src + 16)); + src += 32; + k -= 32; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); + _mm_storeu_si128((__m128i*)dst, vbuf); + _mm_storeu_si128((__m128i*)(dst + 16), vbuf_0); + dst += 32; + + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); + v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); -#include "adler32_sse42_tpl.h" -#undef ADLER32_SSE42_TPL_H_ -#define COPY -#include "adler32_sse42_tpl.h" -#undef COPY + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); + vs1 = _mm_add_epi32(v_sad_sum2, vs1); + vs2 = _mm_add_epi32(vsum2, vs2); + vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); + vs1_0 = vs1; + } + + vs2 = _mm_add_epi32(vs2_0, vs2); + vs3 = _mm_slli_epi32(vs3, 5); + vs2 = _mm_add_epi32(vs3, vs2); + vs3 = _mm_setzero_si128(); + + while (k >= 16) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) + */ + vbuf = _mm_loadu_si128((__m128i*)src); + src += 16; + k -= 16; + + v_sad_sum1 = _mm_sad_epu8(vbuf, zero); + v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); + + vs1 = _mm_add_epi32(v_sad_sum1, vs1); + vs3 = _mm_add_epi32(vs1_0, vs3); + vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); + vs2 = _mm_add_epi32(vsum2, vs2); + vs1_0 = vs1; + + _mm_storeu_si128((__m128i*)dst, vbuf); + dst += 16; + } + + vs3 = _mm_slli_epi32(vs3, 4); + vs2 = _mm_add_epi32(vs2, vs3); + + adler0 = partial_hsum(vs1) % BASE; + adler1 = hsum(vs2) % BASE; + } + + /* If this is true, there's fewer than 16 elements remaining */ + if (len) { + goto rem_peel; + } + + return adler0 | (adler1 << 16); +} #endif diff --git a/arch/x86/adler32_sse42_tpl.h b/arch/x86/adler32_sse42_tpl.h deleted file mode 100644 index 71d1db818b..0000000000 --- a/arch/x86/adler32_sse42_tpl.h +++ /dev/null @@ -1,132 +0,0 @@ -/* adler32_ssse3_tpl.h -- adler32 ssse3 vectorized function templates - * Copyright (C) 2022 Adam Stylinski - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef ADLER32_SSE42_TPL_H_ -#define ADLER32_SSE42_TPL_H_ - -#include "../../zbuild.h" -#include -#include "../../adler32_fold.h" -#include "../../adler32_p.h" -#include "adler32_ssse3_p.h" - -#ifdef COPY -Z_INTERNAL void adler32_fold_copy_sse42(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { -#else -Z_INTERNAL void adler32_fold_sse42(adler32_fold *adler, const uint8_t *src, size_t len) { -#endif - - uint32_t adler0, adler1; - adler1 = (adler->nsums >> 16) & 0xffff; - adler0 = adler->nsums & 0xffff; - - if (len < 16) { -rem_peel: -#ifdef COPY - adler->nsums = adler32_copy_len_16(adler0, src, dst, len, adler1); -#else - adler->nsums = adler32_len_16(adler0, src, len, adler1); -#endif - return; - } - - __m128i vbuf, vbuf_0; - __m128i vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, - v_sad_sum2, vsum2, vsum2_0; - __m128i zero = _mm_setzero_si128(); - const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); - const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); - const __m128i dot3v = _mm_set1_epi16(1); - size_t k; - - while (len >= 16) { - - k = MIN(len, NMAX); - k -= k % 16; - len -= k; - - vs1 = _mm_cvtsi32_si128(adler0); - vs2 = _mm_cvtsi32_si128(adler1); - - vs3 = _mm_setzero_si128(); - vs2_0 = _mm_setzero_si128(); - vs1_0 = vs1; - - while (k >= 32) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - vbuf = _mm_loadu_si128((__m128i*)src); - vbuf_0 = _mm_loadu_si128((__m128i*)(src + 16)); - src += 32; - k -= 32; - - v_sad_sum1 = _mm_sad_epu8(vbuf, zero); - v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); -#ifdef COPY - _mm_storeu_si128((__m128i*)dst, vbuf); - _mm_storeu_si128((__m128i*)(dst + 16), vbuf_0); - dst += 32; -#endif - v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); - v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); - - vs1 = _mm_add_epi32(v_sad_sum1, vs1); - vs3 = _mm_add_epi32(vs1_0, vs3); - - vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); - vs1 = _mm_add_epi32(v_sad_sum2, vs1); - vs2 = _mm_add_epi32(vsum2, vs2); - vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); - vs1_0 = vs1; - } - - vs2 = _mm_add_epi32(vs2_0, vs2); - vs3 = _mm_slli_epi32(vs3, 5); - vs2 = _mm_add_epi32(vs3, vs2); - vs3 = _mm_setzero_si128(); - - while (k >= 16) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - vbuf = _mm_loadu_si128((__m128i*)src); - src += 16; - k -= 16; - - v_sad_sum1 = _mm_sad_epu8(vbuf, zero); - v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); - - vs1 = _mm_add_epi32(v_sad_sum1, vs1); - vs3 = _mm_add_epi32(vs1_0, vs3); - vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vs2 = _mm_add_epi32(vsum2, vs2); - vs1_0 = vs1; - -#ifdef COPY - _mm_storeu_si128((__m128i*)dst, vbuf); - dst += 16; -#endif - } - - vs3 = _mm_slli_epi32(vs3, 4); - vs2 = _mm_add_epi32(vs2, vs3); - - adler0 = partial_hsum(vs1) % BASE; - adler1 = hsum(vs2) % BASE; - } - - /* If this is true, there's fewer than 16 elements remaining */ - if (len) { - goto rem_peel; - } - - adler->nsums = adler0 | (adler1 << 16); -} - -#endif diff --git a/cpu_features.h b/cpu_features.h index dbabb3ac9f..9e0d5cb95d 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -36,20 +36,15 @@ extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); #endif #ifdef X86_SSE42_ADLER32 -extern void adler32_fold_reset_sse42(adler32_fold *adler, uint32_t init_adler); -extern void adler32_fold_copy_sse42(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); -extern void adler32_fold_sse42(adler32_fold *adler, const uint8_t *src, size_t len); -extern uint32_t adler32_fold_final_sse42(adler32_fold *adler); +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif #ifdef X86_AVX2_ADLER32 extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); -extern void adler32_fold_reset_avx2(adler32_fold *adler, uint32_t init_adler); -extern void adler32_fold_copy_avx2(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); -extern void adler32_fold_avx2(adler32_fold *adler, const uint8_t *src, size_t len); -extern uint32_t adler32_fold_final_avx2(adler32_fold *adler); +extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif #ifdef X86_AVX512_ADLER32 extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len); +extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif #ifdef X86_AVX512VNNI_ADLER32 extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len); diff --git a/deflate.c b/deflate.c index 6818a860a0..006803c320 100644 --- a/deflate.c +++ b/deflate.c @@ -52,6 +52,7 @@ #include "deflate.h" #include "deflate_p.h" #include "functable.h" +#include const char PREFIX(deflate_copyright)[] = " deflate 1.2.11.f Copyright 1995-2016 Jean-loup Gailly and Mark Adler "; /* @@ -444,15 +445,12 @@ int32_t Z_EXPORT PREFIX(deflateResetKeep)(PREFIX3(stream) *strm) { INIT_STATE; #ifdef GZIP - if (s->wrap == 2) + if (s->wrap == 2) { + /* Ensure that there's always a reset, regardless of "wrap" */ strm->adler = functable.crc32_fold_reset(&s->crc_fold); - else + } else #endif - //strm->adler = ADLER32_INITIAL_VALUE; - { strm->adler = ADLER32_INITIAL_VALUE; - functable.adler32_fold_reset(&s->adler_fold, ADLER32_INITIAL_VALUE); - } s->last_flush = -2; zng_tr_init(s); @@ -771,7 +769,6 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { if (s->strstart != 0) put_uint32_msb(s, strm->adler); strm->adler = ADLER32_INITIAL_VALUE; - functable.adler32_fold_reset(&s->adler_fold, ADLER32_INITIAL_VALUE); s->status = BUSY_STATE; /* Compression must start with an empty pending buffer */ @@ -979,7 +976,6 @@ int32_t Z_EXPORT PREFIX(deflate)(PREFIX3(stream) *strm, int32_t flush) { } else #endif { - strm->adler = functable.adler32_fold_final(&s->adler_fold); if (s->wrap == 1) put_uint32_msb(s, strm->adler); } @@ -1092,10 +1088,9 @@ Z_INTERNAL unsigned read_buf(PREFIX3(stream) *strm, unsigned char *buf, unsigned #endif } else { if (strm->state->wrap == 1) - functable.adler32_fold_copy(&strm->state->adler_fold, buf, strm->next_in, len); + strm->adler = functable.adler32_fold_copy(strm->adler, buf, strm->next_in, len); else memcpy(buf, strm->next_in, len); - //strm->adler = functable.adler32(strm->adler, buf, len); } strm->next_in += len; strm->total_in += len; diff --git a/deflate.h b/deflate.h index 2d34c95edf..abc87d8b8e 100644 --- a/deflate.h +++ b/deflate.h @@ -212,7 +212,6 @@ struct internal_state { int nice_match; /* Stop searching when current match exceeds this */ - struct adler32_fold_s ALIGNED_(64) adler_fold; struct crc32_fold_s ALIGNED_(16) crc_fold; /* used by trees.c: */ diff --git a/functable.c b/functable.c index 097c7b2459..8328359702 100644 --- a/functable.c +++ b/functable.c @@ -202,22 +202,9 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ return functable.adler32(adler, buf, len); } -Z_INTERNAL void adler32_fold_reset_stub(adler32_fold *adler, uint32_t init_adler) { - functable.adler32_fold_reset = &adler32_fold_reset_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) - if (x86_cpu_has_sse42) - functable.adler32_fold_reset = &adler32_fold_reset_sse42; -#ifdef X86_AVX2_ADLER32 - if (x86_cpu_has_avx2) - functable.adler32_fold_reset = &adler32_fold_reset_avx2; -#endif -#endif - functable.adler32_fold_reset(adler, init_adler); -} - -Z_INTERNAL void adler32_fold_copy_stub(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { +Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { functable.adler32_fold_copy = &adler32_fold_copy_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) +#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) if (x86_cpu_has_sse42) functable.adler32_fold_copy = &adler32_fold_copy_sse42; #endif @@ -225,33 +212,11 @@ Z_INTERNAL void adler32_fold_copy_stub(adler32_fold *adler, uint8_t *dst, const if (x86_cpu_has_avx2) functable.adler32_fold_copy = &adler32_fold_copy_avx2; #endif - functable.adler32_fold_copy(adler, dst, src, len); -} - -Z_INTERNAL void adler32_fold_stub(adler32_fold *adler, const uint8_t *src, size_t len) { - functable.adler32_fold = &adler32_fold_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) - if (x86_cpu_has_sse42) - functable.adler32_fold = &adler32_fold_sse42; -#endif -#ifdef X86_AVX2_ADLER32 - if (x86_cpu_has_avx2) - functable.adler32_fold = &adler32_fold_avx2; -#endif - functable.adler32_fold(adler, src, len); -} - -Z_INTERNAL uint32_t adler32_fold_final_stub(adler32_fold *adler) { - functable.adler32_fold_final = &adler32_fold_final_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) - if (x86_cpu_has_sse42) - functable.adler32_fold_final = &adler32_fold_final_sse42; -#endif -#ifdef X86_AVX2_ADLER32 - if (x86_cpu_has_avx2) - functable.adler32_fold_final = &adler32_fold_final_avx2; +#ifdef X86_AVX512_ADLER32 + if (x86_cpu_has_avx512) + functable.adler32_fold_copy = &adler32_fold_copy_avx512; #endif - return functable.adler32_fold_final(adler); + return functable.adler32_fold_copy(adler, dst, src, len); } Z_INTERNAL uint32_t crc32_fold_reset_stub(crc32_fold *crc) { @@ -489,10 +454,7 @@ Z_INTERNAL uint32_t compare256_stub(const uint8_t *src0, const uint8_t *src1) { /* functable init */ Z_INTERNAL Z_TLS struct functable_s functable = { adler32_stub, - adler32_fold_reset_stub, adler32_fold_copy_stub, - adler32_fold_stub, - adler32_fold_final_stub, crc32_stub, crc32_fold_reset_stub, crc32_fold_copy_stub, diff --git a/functable.h b/functable.h index 8889e74afa..da7726e45a 100644 --- a/functable.h +++ b/functable.h @@ -12,10 +12,7 @@ struct functable_s { uint32_t (* adler32) (uint32_t adler, const unsigned char *buf, size_t len); - void (* adler32_fold_reset) (adler32_fold *adler, uint32_t init_adler); - void (* adler32_fold_copy) (adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len); - void (* adler32_fold) (adler32_fold *adler, const uint8_t *src, size_t len); - uint32_t (* adler32_fold_final) (adler32_fold *adler); + uint32_t (* adler32_fold_copy) (uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); uint32_t (* crc32) (uint32_t crc, const unsigned char *buf, uint64_t len); uint32_t (* crc32_fold_reset) (crc32_fold *crc); void (* crc32_fold_copy) (crc32_fold *crc, uint8_t *dst, const uint8_t *src, size_t len); diff --git a/inflate.c b/inflate.c index 864ca8882c..8611e4bd48 100644 --- a/inflate.c +++ b/inflate.c @@ -28,9 +28,7 @@ static inline void inf_chksum_cpy(PREFIX3(stream) *strm, uint8_t *dst, } else #endif { - /*strm->adler = state->check = functable.adler32(state->check, src, copy); - memcpy(dst, src, copy);*/ - functable.adler32_fold_copy(&state->adler_fold, dst, src, copy); + strm->adler = state->check = functable.adler32_fold_copy(state->check, dst, src, copy); } } @@ -42,8 +40,7 @@ static inline void inf_chksum(PREFIX3(stream) *strm, const uint8_t *src, uint32_ } else #endif { - //strm->adler = state->check = functable.adler32(state->check, src, len); - functable.adler32_fold(&state->adler_fold, src, len); + strm->adler = state->check = functable.adler32(state->check, src, len); } } @@ -466,7 +463,6 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { state->dmax = 1U << len; state->flags = 0; /* indicate zlib header */ Tracev((stderr, "inflate: zlib header ok\n")); - functable.adler32_fold_reset(&state->adler_fold, ADLER32_INITIAL_VALUE); strm->adler = state->check = ADLER32_INITIAL_VALUE; state->mode = hold & 0x200 ? DICTID : TYPE; INITBITS(); @@ -615,7 +611,6 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { NEEDBITS(32); //strm->adler = state->check = ZSWAP32(hold); strm->adler = state->check = ZSWAP32(hold); - functable.adler32_fold_reset(&state->adler_fold, strm->adler); INITBITS(); state->mode = DICT; @@ -625,7 +620,6 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { return Z_NEED_DICT; } strm->adler = state->check = ADLER32_INITIAL_VALUE; - functable.adler32_fold_reset(&state->adler_fold, ADLER32_INITIAL_VALUE); state->mode = TYPE; case TYPE: @@ -1018,8 +1012,6 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #ifdef GUNZIP if (state->flags) strm->adler = state->check = functable.crc32_fold_final(&state->crc_fold); - else - strm->adler = state->check = functable.adler32_fold_final(&state->adler_fold); #endif } out = left; diff --git a/inflate.h b/inflate.h index 8c65f1dbe1..5761077a60 100644 --- a/inflate.h +++ b/inflate.h @@ -104,7 +104,6 @@ struct inflate_state { uint32_t wnext; /* window write index */ unsigned char *window; /* allocated sliding window, if needed */ - struct adler32_fold_s ALIGNED_(64) adler_fold; struct crc32_fold_s ALIGNED_(16) crc_fold; /* bit accumulator */ diff --git a/win32/Makefile.msc b/win32/Makefile.msc index bce5c00449..8db2633b44 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -194,7 +194,7 @@ adler32_avx2.obj: $(SRCDIR)/arch/x86/adler32_avx2.c $(SRCDIR)/zbuild.h $(SRCDIR) adler32_avx512.obj: $(SRCDIR)/arch/x86/adler32_avx512.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/arch/x86/adler32_avx512_p.h adler32_avx512_vnni.obj: $(SRCDIR)/arch/x86/adler32_avx512_vnni.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/arch/x86/adler32_avx512_p.h adler32_sse42.obj: $(SRCDIR)/arch/x86/adler32_sse42.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/adler32_fold.h \ - $(SRCDIR)/arch/x86/adler32_ssse3_p.h $(SRCDIR)/arch/x86/adler32_sse42_tpl.h + $(SRCDIR)/arch/x86/adler32_ssse3_p.h adler32_ssse3.obj: $(SRCDIR)/arch/x86/adler32_ssse3.c $(SRCDIR)/zbuild.h $(SRCDIR)/cpu_features.h $(SRCDIR)/adler32_p.h $(SRCDIR)/adler32_fold.h \ $(SRCDIR)/arch/x86/adler32_ssse3_p.h adler32_fold.obj: $(SRCDIR)/adler32_fold.c $(SRCDIR)/zbuild.h $(SRCDIR)/adler32_fold.h $(SRCDIR)/functable.h From d79984b5bcaccab15e6cd13d7d1edea32ac36977 Mon Sep 17 00:00:00 2001 From: Adam Stylinski Date: Fri, 8 Apr 2022 13:24:21 -0400 Subject: [PATCH 407/798] Adding avx512_vnni inline + copy elision Interesting revelation while benchmarking all of this is that our chunkmemset_avx seems to be slower in a lot of use cases than chunkmemset_sse. That will be an interesting function to attempt to optimize. Right now though, we're basically beating google for all PNG decode and encode benchmarks. There are some variations of flags that can basically have us trading blows, but we're about as much as 14% faster than chromium's zlib patches. While we're here, add a more direct benchmark of the folded copy method versus the explicit copy + checksum. --- adler32_fold.c | 2 +- adler32_fold.h | 2 - adler32_p.h | 16 +- arch/x86/adler32_avx2.c | 18 +- arch/x86/adler32_avx2_p.h | 6 +- arch/x86/adler32_avx2_tpl.h | 13 +- arch/x86/adler32_avx512.c | 11 +- arch/x86/adler32_avx512_tpl.h | 12 +- arch/x86/adler32_avx512_vnni.c | 191 ++++++++++++++++------ arch/x86/adler32_sse42.c | 3 +- arch/x86/adler32_ssse3_tpl.h | 188 --------------------- cpu_features.h | 21 ++- deflate.c | 2 - deflate.h | 2 +- functable.c | 6 +- inflate.c | 1 - inflate.h | 2 +- test/benchmarks/CMakeLists.txt | 1 + test/benchmarks/benchmark_adler32_copy.cc | 117 +++++++++++++ win32/Makefile.msc | 22 +-- 20 files changed, 317 insertions(+), 319 deletions(-) delete mode 100644 arch/x86/adler32_ssse3_tpl.h create mode 100644 test/benchmarks/benchmark_adler32_copy.cc diff --git a/adler32_fold.c b/adler32_fold.c index 688f848533..20fec2bd3c 100644 --- a/adler32_fold.c +++ b/adler32_fold.c @@ -1,4 +1,4 @@ -/* crc32_fold.c -- adler32 folding interface +/* adler32_fold.c -- adler32 folding interface * Copyright (C) 2022 Adam Stylinski * For conditions of distribution and use, see copyright notice in zlib.h */ diff --git a/adler32_fold.h b/adler32_fold.h index ea456adc31..20aa1c7400 100644 --- a/adler32_fold.h +++ b/adler32_fold.h @@ -6,8 +6,6 @@ #ifndef ADLER32_FOLD_H_ #define ADLER32_FOLD_H_ -#include - Z_INTERNAL uint32_t adler32_fold_copy_c(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif diff --git a/adler32_p.h b/adler32_p.h index 5a14172f73..1d2e77f49f 100644 --- a/adler32_p.h +++ b/adler32_p.h @@ -26,10 +26,10 @@ static inline uint32_t adler32_len_1(uint32_t adler, const unsigned char *buf, u return adler | (sum2 << 16); } -static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char *buf, uint8_t *dst, size_t len, uint32_t sum2) { - while (len--) { - *dst = *buf++; - adler += *dst++; +static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) { + while (len) { + --len; + adler += *buf++; sum2 += adler; } adler %= BASE; @@ -38,10 +38,10 @@ static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char * return adler | (sum2 << 16); } -static inline uint32_t adler32_len_16(uint32_t adler, const unsigned char *buf, size_t len, uint32_t sum2) { - while (len) { - --len; - adler += *buf++; +static inline uint32_t adler32_copy_len_16(uint32_t adler, const unsigned char *buf, uint8_t *dst, size_t len, uint32_t sum2) { + while (len--) { + *dst = *buf++; + adler += *dst++; sum2 += adler; } adler %= BASE; diff --git a/arch/x86/adler32_avx2.c b/arch/x86/adler32_avx2.c index fcca34ec53..dcd1166f34 100644 --- a/arch/x86/adler32_avx2.c +++ b/arch/x86/adler32_avx2.c @@ -5,29 +5,13 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include "../../zbuild.h" -#include "../../adler32_p.h" -#include "../../fallback_builtins.h" -#include "adler32_avx2_p.h" -#include "../../adler32_fold.h" -#include - #include #ifdef X86_AVX2_ADLER32 #include "adler32_avx2_tpl.h" -#undef ADLER32_AVX2_TPL_H_ + #define COPY #include "adler32_avx2_tpl.h" -#undef COPY - -/* -Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len) { - if (buf == NULL) return 1L; - if (len == 0) return adler; - return adler32_fold_avx2(adler, buf, len); -} -*/ #endif diff --git a/arch/x86/adler32_avx2_p.h b/arch/x86/adler32_avx2_p.h index 1c80bde057..f7079bf3eb 100644 --- a/arch/x86/adler32_avx2_p.h +++ b/arch/x86/adler32_avx2_p.h @@ -6,10 +6,10 @@ #ifndef ADLER32_AVX2_P_H_ #define ADLER32_AVX2_P_H_ -#ifdef X86_AVX2_ADLER32 +#if defined(X86_AVX2_ADLER32) || defined(X86_AVX512VNNI_ADLER32) /* 32 bit horizontal sum, adapted from Agner Fog's vector library. */ -static inline uint32_t hsum(__m256i x) { +static inline uint32_t hsum256(__m256i x) { __m128i sum1 = _mm_add_epi32(_mm256_extracti128_si256(x, 1), _mm256_castsi256_si128(x)); __m128i sum2 = _mm_add_epi32(sum1, _mm_unpackhi_epi64(sum1, sum1)); @@ -17,7 +17,7 @@ static inline uint32_t hsum(__m256i x) { return (uint32_t)_mm_cvtsi128_si32(sum3); } -static inline uint32_t partial_hsum(__m256i x) { +static inline uint32_t partial_hsum256(__m256i x) { /* We need a permutation vector to extract every other integer. The * rest are going to be zeros */ const __m256i perm_vec = _mm256_setr_epi32(0, 2, 4, 6, 1, 1, 1, 1); diff --git a/arch/x86/adler32_avx2_tpl.h b/arch/x86/adler32_avx2_tpl.h index 7df51d573d..59cacfa483 100644 --- a/arch/x86/adler32_avx2_tpl.h +++ b/arch/x86/adler32_avx2_tpl.h @@ -3,9 +3,6 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifndef ADLER32_AVX2_TPL_H_ -#define ADLER32_AVX2_TPL_H_ - #include "../../zbuild.h" #include #include "../../adler32_fold.h" @@ -38,9 +35,9 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) rem_peel: if (len < 16) { #ifdef COPY - return adler32_copy_len_16(adler0, src, dst, len, adler1); + return adler32_copy_len_16(adler0, src, dst, len, adler1); #else - return adler32_len_16(adler0, src, len, adler1); + return adler32_len_16(adler0, src, len, adler1); #endif } else if (len < 32) { #ifdef COPY @@ -129,8 +126,8 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) * conversion from 64 bit integer to 32 bit (needed for the inexpensive modulus with a constant). * This casting to 32 bit is cheap through GPRs (just register aliasing). See above for exactly * what the compiler is doing to avoid integer divisions. */ - adler0 = partial_hsum(vs1) % BASE; - adler1 = hsum(vs2) % BASE; + adler0 = partial_hsum256(vs1) % BASE; + adler1 = hsum256(vs2) % BASE; } adler = adler0 | (adler1 << 16); @@ -141,5 +138,3 @@ Z_INTERNAL uint32_t adler32_avx2(uint32_t adler, const uint8_t *src, size_t len) return adler; } - -#endif diff --git a/arch/x86/adler32_avx512.c b/arch/x86/adler32_avx512.c index e26b9cc524..c0bf0721f2 100644 --- a/arch/x86/adler32_avx512.c +++ b/arch/x86/adler32_avx512.c @@ -6,20 +6,11 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#include "../../zbuild.h" -#include "../../adler32_p.h" -#include "../../cpu_features.h" -#include "../../fallback_builtins.h" -#include -#include "adler32_avx512_p.h" -#include "../../adler32_fold.h" - #ifdef X86_AVX512_ADLER32 #include "adler32_avx512_tpl.h" -#undef ADLER32_AVX512_TPL_H_ + #define COPY #include "adler32_avx512_tpl.h" -#undef COPY #endif diff --git a/arch/x86/adler32_avx512_tpl.h b/arch/x86/adler32_avx512_tpl.h index df5dd3810f..d324ce9859 100644 --- a/arch/x86/adler32_avx512_tpl.h +++ b/arch/x86/adler32_avx512_tpl.h @@ -3,16 +3,13 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ -#ifndef ADLER32_AVX512_TPL_H_ -#define ADLER32_AVX512_TPL_H_ - #include "../../zbuild.h" #include "../../adler32_p.h" +#include "../../adler32_fold.h" #include "../../cpu_features.h" #include "../../fallback_builtins.h" #include #include "adler32_avx512_p.h" -#include "../../adler32_fold.h" #ifdef X86_AVX512_ADLER32 @@ -22,13 +19,13 @@ Z_INTERNAL uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t len) { #endif + if (src == NULL) return 1L; + if (len == 0) return adler; + uint32_t adler0, adler1; adler1 = (adler >> 16) & 0xffff; adler0 = adler & 0xffff; - if (src == NULL) return 1L; - if (len == 0) return adler; - rem_peel: if (len < 64) { /* This handles the remaining copies, just call normal adler checksum after this */ @@ -107,4 +104,3 @@ Z_INTERNAL uint32_t adler32_avx512(uint32_t adler, const uint8_t *src, size_t le } #endif -#endif diff --git a/arch/x86/adler32_avx512_vnni.c b/arch/x86/adler32_avx512_vnni.c index 253eed9c6a..330bfe38e7 100644 --- a/arch/x86/adler32_avx512_vnni.c +++ b/arch/x86/adler32_avx512_vnni.c @@ -7,66 +7,54 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ +#ifdef X86_AVX512VNNI_ADLER32 + #include "../../zbuild.h" #include "../../adler32_p.h" #include "../../cpu_features.h" #include "../../fallback_builtins.h" #include +#include "../../adler32_fold.h" #include "adler32_avx512_p.h" +#include "adler32_avx2_p.h" -#ifdef X86_AVX512VNNI_ADLER32 -Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len) { - uint32_t sum2; +Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const uint8_t *src, size_t len) { + if (src == NULL) return 1L; + if (len == 0) return adler; + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; - /* For impossibly tiny sizes, use the smaller width versions. We still need - * to check for compile time support for these but they are likely there */ -#ifdef X86_SSE41_ADLER32 +rem_peel: if (len < 32) - return adler32_sse41(adler, buf, len); +#if defined(X86_SSSE3_ADLER32) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); #endif -#ifdef X86_AVX2_ADLER32 if (len < 64) - return adler32_avx2(adler, buf, len); -#endif - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* Only capture these corner cases if we didn't compile with SSE41 and AVX2 support - * This should make for shorter compiled code */ -#if !defined(X86_AVX2_ADLER32) && !defined(X86_SSE41_ADLER32) - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) - return adler32_len_1(adler, buf, sum2); - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (UNLIKELY(buf == NULL)) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (UNLIKELY(len < 16)) - return adler32_len_16(adler, buf, len, sum2); +#ifdef X86_AVX2_ADLER32 + return adler32_avx2(adler, src, len); +#elif defined(X86_SSE3_ADLER32) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); #endif - /* We want to place initial adler sum at vector position 0, as it is one of the lanes that line up - * with the sum of absolute differences' reduction sum. If we do this, we can get away with a partial, - * less expensive horizontal sum for the vs1 component at the end. It also happens to be marginally better - * (by a single cycle) to do this with the ancient vmovd insruction, and simply allow the register to be - * aliased up to a 512 bit wide zmm */ - __m512i vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); - __m512i vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); - const __m512i dot2v = _mm512_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64); const __m512i zero = _mm512_setzero_si512(); + __m512i vs1, vs2; while (len >= 64) { - int k = (len < NMAX ? (int)len : NMAX); + vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler0)); + vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler1)); + size_t k = MIN(len, NMAX); k -= k % 64; len -= k; __m512i vs1_0 = vs1; @@ -77,8 +65,9 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf /* Remainder peeling */ if (k % 128) { - vbuf1 = _mm512_loadu_si512(buf); - buf += 64; + vbuf1 = _mm512_loadu_si512((__m512i*)src); + + src += 64; k -= 64; __m512i vs1_sad = _mm512_sad_epu8(vbuf1, zero); @@ -94,9 +83,9 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf vs1 = adler + sum(c[i]) vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) */ - vbuf0 = _mm512_loadu_si512(buf); - vbuf1 = _mm512_loadu_si512(buf + 64); - buf += 128; + vbuf0 = _mm512_loadu_si512((__m512i*)src); + vbuf1 = _mm512_loadu_si512((__m512i*)(src + 64)); + src += 128; k -= 128; __m512i vs1_sad = _mm512_sad_epu8(vbuf0, zero); @@ -117,14 +106,120 @@ Z_INTERNAL uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf vs2 = _mm512_add_epi32(vs2, vs3); vs2 = _mm512_add_epi32(vs2, vs2_1); - adler = partial_hsum(vs1) % BASE; - vs1 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(adler)); - sum2 = _mm512_reduce_add_epu32(vs2) % BASE; - vs2 = _mm512_zextsi128_si512(_mm_cvtsi32_si128(sum2)); + adler0 = partial_hsum(vs1) % BASE; + adler1 = _mm512_reduce_add_epu32(vs2) % BASE; + } + + adler = adler0 | (adler1 << 16); + + /* Process tail (len < 64). */ + if (len) { + goto rem_peel; + } + + return adler; +} + +Z_INTERNAL uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { + if (src == NULL) return 1L; + if (len == 0) return adler; + + uint32_t adler0, adler1; + adler1 = (adler >> 16) & 0xffff; + adler0 = adler & 0xffff; + +rem_peel_copy: + if (len < 32) { + /* This handles the remaining copies, just call normal adler checksum after this */ + __mmask32 storemask = (0xFFFFFFFFUL >> (32 - len)); + __m256i copy_vec = _mm256_maskz_loadu_epi8(storemask, src); + _mm256_mask_storeu_epi8(dst, storemask, copy_vec); + +#if defined(X86_SSSE3_ADLER32) + return adler32_ssse3(adler, src, len); +#else + return adler32_len_16(adler0, src, len, adler1); +#endif + } + + const __m256i dot2v = _mm256_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32); + + const __m256i zero = _mm256_setzero_si256(); + __m256i vs1, vs2; + + while (len >= 32) { + vs1 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler0)); + vs2 = _mm256_zextsi128_si256(_mm_cvtsi32_si128(adler1)); + size_t k = MIN(len, NMAX); + k -= k % 32; + len -= k; + __m256i vs1_0 = vs1; + __m256i vs3 = _mm256_setzero_si256(); + /* We might get a tad bit more ILP here if we sum to a second register in the loop */ + __m256i vs2_1 = _mm256_setzero_si256(); + __m256i vbuf0, vbuf1; + + /* Remainder peeling */ + if (k % 64) { + vbuf1 = _mm256_loadu_si256((__m256i*)src); + _mm256_storeu_si256((__m256i*)dst, vbuf1); + dst += 32; + + src += 32; + k -= 32; + + __m256i vs1_sad = _mm256_sad_epu8(vbuf1, zero); + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs3 = _mm256_add_epi32(vs3, vs1_0); + vs2 = _mm256_dpbusd_epi32(vs2, vbuf1, dot2v); + vs1_0 = vs1; + } + + /* Manually unrolled this loop by 2 for an decent amount of ILP */ + while (k >= 64) { + /* + vs1 = adler + sum(c[i]) + vs2 = sum2 + 64 vs1 + sum( (64-i+1) c[i] ) + */ + vbuf0 = _mm256_loadu_si256((__m256i*)src); + vbuf1 = _mm256_loadu_si256((__m256i*)(src + 32)); + _mm256_storeu_si256((__m256i*)dst, vbuf0); + _mm256_storeu_si256((__m256i*)(dst + 32), vbuf1); + dst += 64; + src += 64; + k -= 64; + + __m256i vs1_sad = _mm256_sad_epu8(vbuf0, zero); + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs3 = _mm256_add_epi32(vs3, vs1_0); + /* multiply-add, resulting in 16 ints. Fuse with sum stage from prior versions, as we now have the dp + * instructions to eliminate them */ + vs2 = _mm256_dpbusd_epi32(vs2, vbuf0, dot2v); + + vs3 = _mm256_add_epi32(vs3, vs1); + vs1_sad = _mm256_sad_epu8(vbuf1, zero); + vs1 = _mm256_add_epi32(vs1, vs1_sad); + vs2_1 = _mm256_dpbusd_epi32(vs2_1, vbuf1, dot2v); + vs1_0 = vs1; + } + + vs3 = _mm256_slli_epi32(vs3, 5); + vs2 = _mm256_add_epi32(vs2, vs3); + vs2 = _mm256_add_epi32(vs2, vs2_1); + + adler0 = partial_hsum256(vs1) % BASE; + adler1 = hsum256(vs2) % BASE; } + adler = adler0 | (adler1 << 16); + /* Process tail (len < 64). */ - return adler32_len_16(adler, buf, len, sum2); + if (len) { + goto rem_peel_copy; + } + + return adler; } #endif diff --git a/arch/x86/adler32_sse42.c b/arch/x86/adler32_sse42.c index 4f21702aaf..92efe4d8db 100644 --- a/arch/x86/adler32_sse42.c +++ b/arch/x86/adler32_sse42.c @@ -1,4 +1,4 @@ -/* adler32_sse4.c -- compute the Adler-32 checksum of a data stream +/* adler32_sse42.c -- compute the Adler-32 checksum of a data stream * Copyright (C) 1995-2011 Mark Adler * Authors: * Adam Stylinski @@ -15,7 +15,6 @@ #ifdef X86_SSE42_ADLER32 Z_INTERNAL uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { - uint32_t adler0, adler1; adler1 = (adler >> 16) & 0xffff; adler0 = adler & 0xffff; diff --git a/arch/x86/adler32_ssse3_tpl.h b/arch/x86/adler32_ssse3_tpl.h deleted file mode 100644 index aedfa81241..0000000000 --- a/arch/x86/adler32_ssse3_tpl.h +++ /dev/null @@ -1,188 +0,0 @@ -/* adler32_ssse3_tpl.h -- adler32 ssse3 vectorized function templates - * Copyright (C) 2022 Adam Stylinski - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#ifndef ADLER32_SSSE3_TPL_H_ -#define ADLER32_SSSE3_TPL_H_ - -#include "../../zbuild.h" -#include -#include "../../adler32_fold.h" -#include "../../adler32_p.h" -#include "adler32_ssse3_p.h" - -#ifdef COPY -Z_INTERNAL void adler32_fold_copy_ssse3(adler32_fold *adler, uint8_t *dst, const uint8_t *src, size_t len) { -#else -Z_INTERNAL void adler32_fold_ssse3(adler32_fold *adler, const uint8_t *src, size_t len) { -#endif - uint32_t adler0, adler1; - - /* split Adler-32 into component sums */ - adler1 = (adler->nsums >> 16) & 0xffff; - adler0 = adler->nsums & 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (UNLIKELY(len == 1)) { -#ifdef COPY - *(dst++) = *src; -#endif - adler->nsums = adler32_len_1(adler0, src, adler1); - return; - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (UNLIKELY(src == NULL)) { - adler->nsums = 1L; - return; - } - - /* in case short lengths are provided, keep it somewhat fast */ - if (UNLIKELY(len < 16)) { - goto sub16; - } - - const __m128i dot2v = _mm_setr_epi8(32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17); - const __m128i dot2v_0 = _mm_setr_epi8(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1); - const __m128i dot3v = _mm_set1_epi16(1); - const __m128i zero = _mm_setzero_si128(); - - __m128i vbuf, vs1_0, vs3, vs1, vs2, vs2_0, v_sad_sum1, v_short_sum2, v_short_sum2_0, - vbuf_0, v_sad_sum2, vsum2, vsum2_0; - - /* If our buffer is unaligned (likely), make the determination whether - * or not there's enough of a buffer to consume to make the scalar, aligning - * additions worthwhile or if it's worth it to just eat the cost of an unaligned - * load. This is a pretty simple test, just test if 16 - the remainder + len is - * < 16 */ - size_t max_iters = NMAX; - size_t rem = (uintptr_t)src & 15; - size_t align_offset = 16 - rem; - size_t k = 0; - if (rem) { - if (len < 16 + align_offset) { - /* Let's eat the cost of this one unaligned load so that - * we don't completely skip over the vectorization. Doing - * 16 bytes at a time unaligned is is better than 16 + <= 15 - * sums */ - vbuf = _mm_loadu_si128((__m128i*)src); - len -= 16; - src += 16; -#ifdef COPY - _mm_storeu_si128((__m128i*)dst, vbuf); - dst += 16; -#endif - vs1 = _mm_cvtsi32_si128(adler0); - vs2 = _mm_cvtsi32_si128(adler1); - vs3 = _mm_setzero_si128(); - vs1_0 = vs1; - goto unaligned_jmp; - } - -#ifdef COPY - memcpy(dst, src, align_offset); - dst += align_offset; -#endif - for (size_t i = 0; i < align_offset; ++i) { - adler0 += *(src++); - adler1 += adler0; - } - - /* lop off the max number of sums based on the scalar sums done - * above */ - len -= align_offset; - max_iters -= align_offset; - } - - - while (len >= 16) { - vs1 = _mm_cvtsi32_si128(adler0); - vs2 = _mm_cvtsi32_si128(adler1); - vs3 = _mm_setzero_si128(); - vs2_0 = _mm_setzero_si128(); - vs1_0 = vs1; - - k = (len < max_iters ? len : max_iters); - k -= k % 16; - len -= k; - - while (k >= 32) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - vbuf = _mm_load_si128((__m128i*)src); - vbuf_0 = _mm_load_si128((__m128i*)(src + 16)); - src += 32; - k -= 32; - - v_sad_sum1 = _mm_sad_epu8(vbuf, zero); - v_sad_sum2 = _mm_sad_epu8(vbuf_0, zero); -#ifdef COPY - _mm_storeu_si128((__m128i*)dst, vbuf); - _mm_storeu_si128((__m128i*)(dst + 16), vbuf_0); - dst += 32; -#endif - vs1 = _mm_add_epi32(v_sad_sum1, vs1); - vs3 = _mm_add_epi32(vs1_0, vs3); - - vs1 = _mm_add_epi32(v_sad_sum2, vs1); - v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v); - vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - v_short_sum2_0 = _mm_maddubs_epi16(vbuf_0, dot2v_0); - vs2 = _mm_add_epi32(vsum2, vs2); - vsum2_0 = _mm_madd_epi16(v_short_sum2_0, dot3v); - vs2_0 = _mm_add_epi32(vsum2_0, vs2_0); - vs1_0 = vs1; - } - - vs2 = _mm_add_epi32(vs2_0, vs2); - vs3 = _mm_slli_epi32(vs3, 5); - vs2 = _mm_add_epi32(vs3, vs2); - vs3 = _mm_setzero_si128(); - - while (k >= 16) { - /* - vs1 = adler + sum(c[i]) - vs2 = sum2 + 16 vs1 + sum( (16-i+1) c[i] ) - */ - vbuf = _mm_load_si128((__m128i*)src); - src += 16; - k -= 16; - -unaligned_jmp: - v_sad_sum1 = _mm_sad_epu8(vbuf, zero); -#ifdef COPY - _mm_storeu_si128((__m128i*)dst, vbuf); - dst += 16; -#endif - vs1 = _mm_add_epi32(v_sad_sum1, vs1); - vs3 = _mm_add_epi32(vs1_0, vs3); - v_short_sum2 = _mm_maddubs_epi16(vbuf, dot2v_0); - vsum2 = _mm_madd_epi16(v_short_sum2, dot3v); - vs2 = _mm_add_epi32(vsum2, vs2); - vs1_0 = vs1; - } - - vs3 = _mm_slli_epi32(vs3, 4); - vs2 = _mm_add_epi32(vs2, vs3); - - /* We don't actually need to do a full horizontal sum, since psadbw is actually doing - * a partial reduction sum implicitly and only summing to integers in vector positions - * 0 and 2. This saves us some contention on the shuffle port(s) */ - adler0 = partial_hsum(vs1) % BASE; - adler1 = hsum(vs2) % BASE; - max_iters = NMAX; - } - -sub16: -#ifdef COPY - adler->nsums = adler32_copy_len_16(adler0, src, dst, len, adler1); -#else - /* Process tail (len < 16). */ - adler->nsums = adler32_len_16(adler0, src, len, adler1); -#endif -} - -#endif diff --git a/cpu_features.h b/cpu_features.h index 9e0d5cb95d..fc1b5d7339 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -6,8 +6,8 @@ #ifndef CPU_FEATURES_H_ #define CPU_FEATURES_H_ -#include "crc32_fold.h" #include "adler32_fold.h" +#include "crc32_fold.h" #if defined(X86_FEATURES) # include "arch/x86/x86_features.h" @@ -35,16 +35,11 @@ extern uint32_t adler32_vmx(uint32_t adler, const unsigned char *buf, size_t len #ifdef X86_SSSE3_ADLER32 extern uint32_t adler32_ssse3(uint32_t adler, const unsigned char *buf, size_t len); #endif -#ifdef X86_SSE42_ADLER32 -extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); -#endif #ifdef X86_AVX2_ADLER32 extern uint32_t adler32_avx2(uint32_t adler, const unsigned char *buf, size_t len); -extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif #ifdef X86_AVX512_ADLER32 extern uint32_t adler32_avx512(uint32_t adler, const unsigned char *buf, size_t len); -extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); #endif #ifdef X86_AVX512VNNI_ADLER32 extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, size_t len); @@ -53,6 +48,20 @@ extern uint32_t adler32_avx512_vnni(uint32_t adler, const unsigned char *buf, si extern uint32_t adler32_power8(uint32_t adler, const unsigned char* buf, size_t len); #endif +/* adler32 folding */ +#ifdef X86_SSE42_ADLER32 +extern uint32_t adler32_fold_copy_sse42(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif +#ifdef X86_AVX2_ADLER32 +extern uint32_t adler32_fold_copy_avx2(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif +#ifdef X86_AVX512_ADLER32 +extern uint32_t adler32_fold_copy_avx512(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif +#ifdef X86_AVX512VNNI_ADLER32 +extern uint32_t adler32_fold_copy_avx512_vnni(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len); +#endif + /* CRC32 folding */ #ifdef X86_PCLMULQDQ_CRC extern uint32_t crc32_fold_reset_pclmulqdq(crc32_fold *crc); diff --git a/deflate.c b/deflate.c index 006803c320..c2700f2b5f 100644 --- a/deflate.c +++ b/deflate.c @@ -52,7 +52,6 @@ #include "deflate.h" #include "deflate_p.h" #include "functable.h" -#include const char PREFIX(deflate_copyright)[] = " deflate 1.2.11.f Copyright 1995-2016 Jean-loup Gailly and Mark Adler "; /* @@ -446,7 +445,6 @@ int32_t Z_EXPORT PREFIX(deflateResetKeep)(PREFIX3(stream) *strm) { #ifdef GZIP if (s->wrap == 2) { - /* Ensure that there's always a reset, regardless of "wrap" */ strm->adler = functable.crc32_fold_reset(&s->crc_fold); } else #endif diff --git a/deflate.h b/deflate.h index abc87d8b8e..1b59c7539d 100644 --- a/deflate.h +++ b/deflate.h @@ -10,9 +10,9 @@ subject to change. Applications should only use zlib.h. */ -#include "adler32_fold.h" #include "zutil.h" #include "zendian.h" +#include "adler32_fold.h" #include "crc32_fold.h" /* define NO_GZIP when compiling if you want to disable gzip header and diff --git a/functable.c b/functable.c index 8328359702..3945323125 100644 --- a/functable.c +++ b/functable.c @@ -204,7 +204,7 @@ Z_INTERNAL uint32_t adler32_stub(uint32_t adler, const unsigned char *buf, size_ Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) { functable.adler32_fold_copy = &adler32_fold_copy_c; -#if (defined X86_SSE42_ADLER32) && !defined(X86_AVX512VNNI_ADLER32) +#if (defined X86_SSE42_ADLER32) if (x86_cpu_has_sse42) functable.adler32_fold_copy = &adler32_fold_copy_sse42; #endif @@ -215,6 +215,10 @@ Z_INTERNAL uint32_t adler32_fold_copy_stub(uint32_t adler, uint8_t *dst, const u #ifdef X86_AVX512_ADLER32 if (x86_cpu_has_avx512) functable.adler32_fold_copy = &adler32_fold_copy_avx512; +#endif +#ifdef X86_AVX512VNNI_ADLER32 + if (x86_cpu_has_avx512vnni) + functable.adler32_fold_copy = &adler32_fold_copy_avx512_vnni; #endif return functable.adler32_fold_copy(adler, dst, src, len); } diff --git a/inflate.c b/inflate.c index 8611e4bd48..b9c3aa7973 100644 --- a/inflate.c +++ b/inflate.c @@ -609,7 +609,6 @@ int32_t Z_EXPORT PREFIX(inflate)(PREFIX3(stream) *strm, int32_t flush) { #endif case DICTID: NEEDBITS(32); - //strm->adler = state->check = ZSWAP32(hold); strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; diff --git a/inflate.h b/inflate.h index 5761077a60..941e8b0a28 100644 --- a/inflate.h +++ b/inflate.h @@ -11,8 +11,8 @@ #ifndef INFLATE_H_ #define INFLATE_H_ -#include "crc32_fold.h" #include "adler32_fold.h" +#include "crc32_fold.h" /* define NO_GZIP when compiling if you want to disable gzip header and trailer decoding by inflate(). NO_GZIP would be used to avoid linking in the crc code when it is not needed. diff --git a/test/benchmarks/CMakeLists.txt b/test/benchmarks/CMakeLists.txt index df1df49731..19762fc738 100644 --- a/test/benchmarks/CMakeLists.txt +++ b/test/benchmarks/CMakeLists.txt @@ -24,6 +24,7 @@ endif() add_executable(benchmark_zlib benchmark_adler32.cc + benchmark_adler32_copy.cc benchmark_compare256.cc benchmark_crc32.cc benchmark_main.cc diff --git a/test/benchmarks/benchmark_adler32_copy.cc b/test/benchmarks/benchmark_adler32_copy.cc new file mode 100644 index 0000000000..fac4c7f1cd --- /dev/null +++ b/test/benchmarks/benchmark_adler32_copy.cc @@ -0,0 +1,117 @@ +/* benchmark_adler32_copy.cc -- benchmark adler32 (elided copy) variants + * Copyright (C) 2022 Nathan Moinvaziri, Adam Stylinski + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include +#include +#include + +#include + +extern "C" { +# include "zbuild.h" +# include "zutil_p.h" +# include "cpu_features.h" +} + +#define MAX_RANDOM_INTS (1024 * 1024) +#define MAX_RANDOM_INTS_SIZE (MAX_RANDOM_INTS * sizeof(uint32_t)) + +typedef uint32_t (*adler32_cpy_func)(uint32_t adler, unsigned char *dst, const unsigned char *buf, size_t len); + +class adler32_copy: public benchmark::Fixture { +private: + uint32_t *random_ints_src; + uint32_t *random_ints_dst; + +public: + void SetUp(const ::benchmark::State& state) { + /* Control the alignment so that we have the best case scenario for loads. With + * AVX512, unaligned loads can mean we're crossing a cacheline boundary at every load. + * And while this is a realistic scenario, it makes it difficult to compare benchmark + * to benchmark because one allocation could have been aligned perfectly for the loads + * while the subsequent one happened to not be. This is not to be advantageous to AVX512 + * (indeed, all lesser SIMD implementations benefit from this aligned allocation), but to + * control the _consistency_ of the results */ + random_ints_src = (uint32_t *)zng_alloc(MAX_RANDOM_INTS_SIZE); + random_ints_dst = (uint32_t *)zng_alloc(MAX_RANDOM_INTS_SIZE); + assert(random_ints != NULL); + + for (int32_t i = 0; i < MAX_RANDOM_INTS; i++) { + random_ints_src[i] = rand(); + } + } + + void Bench(benchmark::State& state, adler32_cpy_func adler32_func) { + uint32_t hash = 0; + + for (auto _ : state) { + hash = adler32_func(hash, (unsigned char *)random_ints_dst, + (const unsigned char*)random_ints_src, state.range(0)); + } + + benchmark::DoNotOptimize(hash); + } + + void TearDown(const ::benchmark::State& state) { + zng_free(random_ints_src); + zng_free(random_ints_dst); + } +}; + +#define BENCHMARK_ADLER32_COPY(name, fptr, support_flag) \ + BENCHMARK_DEFINE_F(adler32_copy, name)(benchmark::State& state) { \ + if (!support_flag) { \ + state.SkipWithError("CPU does not support " #name); \ + } \ + Bench(state, fptr); \ + } \ + BENCHMARK_REGISTER_F(adler32_copy, name)->Range(8192, MAX_RANDOM_INTS_SIZE); + +#define BENCHMARK_ADLER32_BASELINE_COPY(name, fptr, support_flag) \ + BENCHMARK_DEFINE_F(adler32_copy, name)(benchmark::State& state) { \ + if (!support_flag) { \ + state.SkipWithError("CPU does not support " #name); \ + } \ + Bench(state, [](uint32_t init_sum, unsigned char *dst, \ + const unsigned char *buf, size_t len) -> uint32_t { \ + memcpy(dst, buf, len); \ + return fptr(init_sum, buf, len); \ + }); \ + } \ + BENCHMARK_REGISTER_F(adler32_copy, name)->Range(8192, MAX_RANDOM_INTS_SIZE); + +BENCHMARK_ADLER32_BASELINE_COPY(c, adler32_c, 1); + +#ifdef ARM_NEON_ADLER32 +/* If we inline this copy for neon, the function would go here */ +//BENCHMARK_ADLER32_COPY(neon, adler32_neon, arm_cpu_has_neon); +BENCHMARK_ADLER32_BASELINE_COPY(neon_copy_baseline, adler32_neon, arm_cpu_has_neon); +#endif + +#ifdef PPC_VMX_ADLER32 +//BENCHMARK_ADLER32_COPY(vmx_inline_copy, adler32_fold_copy_vmx, power_cpu_has_altivec); +BENCHMARK_ADLER32_BASELINE_COPY(vmx_copy_baseline, adler32_vmx, power_cpu_has_altivec); +#endif +#ifdef POWER8_VSX_ADLER32 +//BENCHMARK_ADLER32_COPY(power8_inline_copy, adler32_fold_copy_power8, power_cpu_has_arch_2_07); +BENCHMARK_ADLER32_BASELINE_COPY(power8, adler32_power8, power_cpu_has_arch_2_07); +#endif + +#ifdef X86_SSE42_ADLER32 +BENCHMARK_ADLER32_BASELINE_COPY(sse42_baseline, adler32_ssse3, x86_cpu_has_ssse3); +BENCHMARK_ADLER32_COPY(sse42, adler32_fold_copy_sse42, x86_cpu_has_sse42); +#endif +#ifdef X86_AVX2_ADLER32 +BENCHMARK_ADLER32_BASELINE_COPY(avx2_baseline, adler32_avx2, x86_cpu_has_avx2); +BENCHMARK_ADLER32_COPY(avx2, adler32_fold_copy_avx2, x86_cpu_has_avx2); +#endif +#ifdef X86_AVX512_ADLER32 +BENCHMARK_ADLER32_BASELINE_COPY(avx512_baseline, adler32_avx512, x86_cpu_has_avx512); +BENCHMARK_ADLER32_COPY(avx512, adler32_fold_copy_avx512, x86_cpu_has_avx512); +#endif +#ifdef X86_AVX512VNNI_ADLER32 +BENCHMARK_ADLER32_BASELINE_COPY(avx512_vnni_baseline, adler32_avx512_vnni, x86_cpu_has_avx512vnni); +BENCHMARK_ADLER32_COPY(avx512_vnni, adler32_fold_copy_avx512_vnni, x86_cpu_has_avx512vnni); +#endif diff --git a/win32/Makefile.msc b/win32/Makefile.msc index 8db2633b44..8a398e4993 100644 --- a/win32/Makefile.msc +++ b/win32/Makefile.msc @@ -30,15 +30,15 @@ WFLAGS = \ -DX86_FEATURES \ -DX86_PCLMULQDQ_CRC \ -DX86_SSE2 \ - -DX86_SSE42_ADLER32 \ + -DX86_SSE42_ADLER32 \ -DX86_SSE42_CRC_INTRIN \ -DX86_SSE42_CRC_HASH \ - -DX86_SSSE3_ADLER32 \ + -DX86_SSSE3_ADLER32 \ -DX86_AVX2 \ - -DX86_AVX2_ADLER32 \ + -DX86_AVX2_ADLER32 \ -DX86_AVX_CHUNKSET \ - -DX86_SSE2_CHUNKSET \ - # + -DX86_SSE2_CHUNKSET + LDFLAGS = -nologo -debug -incremental:no -opt:ref -manifest ARFLAGS = -nologo RCFLAGS = /dWIN32 /r @@ -51,12 +51,12 @@ SUFFIX = OBJS = \ adler32.obj \ - adler32_avx2.obj \ - adler32_avx512.obj \ - adler32_avx512_vnni.obj \ - adler32_sse42.obj \ - adler32_ssse3.obj \ - adler32_fold.obj \ + adler32_avx2.obj \ + adler32_avx512.obj \ + adler32_avx512_vnni.obj \ + adler32_sse42.obj \ + adler32_ssse3.obj \ + adler32_fold.obj \ chunkset.obj \ chunkset_avx.obj \ chunkset_sse2.obj \ From a6155234a2aa34b4562570dbd359a2a505962a01 Mon Sep 17 00:00:00 2001 From: Nathan Moinvaziri Date: Tue, 24 May 2022 11:44:20 -0700 Subject: [PATCH 408/798] Speed up software CRC-32 computation by a factor of 1.5 to 3. Use the interleaved method of Kadatch and Jenkins in order to make use of pipelined instructions through multiple ALUs in a single core. This also speeds up and simplifies the combination of CRCs, and updates the functions to pre-calculate and use an operator for CRC combination. Co-authored-by: Nathan Moinvaziri --- CMakeLists.txt | 25 +- Makefile.in | 8 +- arch/power/crc32_power8.c | 4 +- arch/s390/crc32-vx.c | 8 +- arch/x86/crc32_fold_pclmulqdq.c | 6 +- cpu_features.h | 2 +- crc32.c | 113 - crc32_braid.c | 267 + crc32_braid_comb.c | 63 + crc32_braid_comb_p.h | 41 + crc32_braid_p.h | 50 + crc32_braid_tbl.h | 9446 ++++++++++++++++++++++++++++ crc32_comb.c | 110 - crc32_comb_tbl.h | 300 - crc32_p.h | 24 - crc32_tbl.h | 444 -- doc/crc-doc.1.0.pdf | Bin 0 -> 776142 bytes functable.c | 4 +- test/benchmarks/benchmark_crc32.cc | 2 +- test/fuzz/fuzzer_checksum.c | 6 +- test/test_crc32.cc | 2 +- tools/makecrct.c | 321 +- win32/Makefile.a64 | 8 +- win32/Makefile.arm | 8 +- win32/Makefile.msc | 8 +- zlib-ng.h.in | 11 +- zlib.h.in | 21 +- 27 files changed, 10120 insertions(+), 1182 deletions(-) delete mode 100644 crc32.c create mode 100644 crc32_braid.c create mode 100644 crc32_braid_comb.c create mode 100644 crc32_braid_comb_p.h create mode 100644 crc32_braid_p.h create mode 100644 crc32_braid_tbl.h delete mode 100644 crc32_comb.c delete mode 100644 crc32_comb_tbl.h delete mode 100644 crc32_p.h delete mode 100644 crc32_tbl.h create mode 100644 doc/crc-doc.1.0.pdf diff --git a/CMakeLists.txt b/CMakeLists.txt index 9719468bf3..a62a95ed18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -928,9 +928,9 @@ set(ZLIB_PRIVATE_HDRS adler32_p.h chunkset_tpl.h cpu_features.h - crc32_p.h - crc32_tbl.h - crc32_comb_tbl.h + crc32_braid_p.h + crc32_braid_comb_p.h + crc32_braid_tbl.h crc32_fold.h deflate.h deflate_p.h @@ -956,8 +956,8 @@ set(ZLIB_SRCS compare256.c compress.c cpu_features.c - crc32.c - crc32_comb.c + crc32_braid.c + crc32_braid_comb.c crc32_fold.c deflate.c deflate_fast.c @@ -1275,20 +1275,11 @@ if(ZLIB_ENABLE_TESTS) "$") set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $) - add_test(NAME makecrct-crc32 + add_test(NAME makecrct COMMAND ${CMAKE_COMMAND} "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/crc32_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_tbl.h - -DIGNORE_LINE_ENDINGS=ON - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) - - set(MAKECRCT_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $ -c) - add_test(NAME makecrct-crc32-combine - COMMAND ${CMAKE_COMMAND} - "-DCOMMAND=${MAKECRCT_COMMAND}" - -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/crc32_comb_tbl._h - -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_comb_tbl.h + -DOUTPUT=${CMAKE_CURRENT_BINARY_DIR}/Testing/Temporary/crc32_braid_tbl._h + -DCOMPARE=${CMAKE_CURRENT_SOURCE_DIR}/crc32_braid_tbl.h -DIGNORE_LINE_ENDINGS=ON -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-compare.cmake) diff --git a/Makefile.in b/Makefile.in index 10decf5d7b..4e25ef9962 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,8 +80,8 @@ OBJZ = \ compare256.o \ compress.o \ cpu_features.o \ - crc32.o \ - crc32_comb.o \ + crc32_braid.o \ + crc32_braid_comb.o \ crc32_fold.o \ deflate.o \ deflate_fast.o \ @@ -118,8 +118,8 @@ PIC_OBJZ = \ compare256.lo \ compress.lo \ cpu_features.lo \ - crc32.lo \ - crc32_comb.lo \ + crc32_braid.lo \ + crc32_braid_comb.lo \ crc32_fold.lo \ deflate.lo \ deflate_fast.lo \ diff --git a/arch/power/crc32_power8.c b/arch/power/crc32_power8.c index c418ed4f48..fbb64721e6 100644 --- a/arch/power/crc32_power8.c +++ b/arch/power/crc32_power8.c @@ -30,7 +30,7 @@ #include "zbuild.h" #include "crc32_constants.h" -#include "crc32_tbl.h" +#include "crc32_braid_tbl.h" #if defined (__clang__) #include "fallback_builtins.h" @@ -42,7 +42,7 @@ static unsigned int crc32_align(unsigned int crc, const unsigned char *p, unsigned long len) { while (len--) - crc = crc_table[0][(crc ^ *p++) & 0xff] ^ (crc >> 8); + crc = crc_table[(crc ^ *p++) & 0xff] ^ (crc >> 8); return crc; } diff --git a/arch/s390/crc32-vx.c b/arch/s390/crc32-vx.c index 3477743ddb..d0df83cce7 100644 --- a/arch/s390/crc32-vx.c +++ b/arch/s390/crc32-vx.c @@ -13,7 +13,7 @@ */ #include "../../zbuild.h" -#include "crc32_p.h" +#include "crc32_braid_p.h" #include @@ -202,12 +202,12 @@ uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf uint64_t prealign, aligned, remaining; if (len < VX_MIN_LEN + VX_ALIGN_MASK) - return crc32_byfour(crc, buf, len); + return crc32_braid(crc, buf, len); if ((uintptr_t)buf & VX_ALIGN_MASK) { prealign = VX_ALIGNMENT - ((uintptr_t)buf & VX_ALIGN_MASK); len -= prealign; - crc = crc32_byfour(crc, buf, prealign); + crc = crc32_braid(crc, buf, prealign); buf += prealign; } aligned = len & ~VX_ALIGN_MASK; @@ -216,7 +216,7 @@ uint32_t Z_INTERNAL PREFIX(s390_crc32_vx)(uint32_t crc, const unsigned char *buf crc = crc32_le_vgfm_16(crc ^ 0xffffffff, buf, (size_t)aligned) ^ 0xffffffff; if (remaining) - crc = crc32_byfour(crc, buf + aligned, remaining); + crc = crc32_braid(crc, buf + aligned, remaining); return crc; } diff --git a/arch/x86/crc32_fold_pclmulqdq.c b/arch/x86/crc32_fold_pclmulqdq.c index 800e3d1766..6bb2c985cc 100644 --- a/arch/x86/crc32_fold_pclmulqdq.c +++ b/arch/x86/crc32_fold_pclmulqdq.c @@ -28,7 +28,7 @@ #include "cpu_features.h" #include "../../crc32_fold.h" -#include "../../crc32_p.h" +#include "../../crc32_braid_p.h" #include #ifdef X86_VPCLMULQDQ_CRC @@ -594,10 +594,10 @@ Z_INTERNAL uint32_t crc32_fold_final_pclmulqdq(crc32_fold *crc) { } uint32_t crc32_pclmulqdq(uint32_t crc32, const unsigned char* buf, uint64_t len) { - /* For lens < 64, crc32_byfour method is faster. The CRC32 instruction for + /* For lens < 64, crc32_braid method is faster. The CRC32 instruction for * these short lengths might also prove to be effective */ if (len < 64) - return crc32_byfour(crc32, buf, len); + return crc32_braid(crc32, buf, len); crc32_fold ALIGNED_(16) crc_state; crc32_fold_reset_pclmulqdq(&crc_state); diff --git a/cpu_features.h b/cpu_features.h index fc1b5d7339..ca1465d5d2 100644 --- a/cpu_features.h +++ b/cpu_features.h @@ -118,7 +118,7 @@ extern uint8_t* chunkmemset_safe_power8(uint8_t *out, unsigned dist, unsigned le /* CRC32 */ typedef uint32_t (*crc32_func)(uint32_t crc32, const unsigned char * buf, uint64_t len); -extern uint32_t crc32_byfour(uint32_t crc, const unsigned char *buf, uint64_t len); +extern uint32_t crc32_braid(uint32_t crc, const unsigned char *buf, uint64_t len); #ifdef ARM_ACLE_CRC_HASH extern uint32_t crc32_acle(uint32_t crc, const unsigned char *buf, uint64_t len); #elif defined(POWER8_VSX_CRC32) diff --git a/crc32.c b/crc32.c deleted file mode 100644 index 493c00c9d4..0000000000 --- a/crc32.c +++ /dev/null @@ -1,113 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -#include "zbuild.h" -#include "zendian.h" -#include "deflate.h" -#include "functable.h" -#include "crc32_tbl.h" - -/* ========================================================================= */ -const uint32_t * Z_EXPORT PREFIX(get_crc_table)(void) { - return (const uint32_t *)crc_table; -} - -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(crc32_z)(unsigned long crc, const unsigned char *buf, size_t len) { - if (buf == NULL) return 0; - - return (unsigned long)functable.crc32((uint32_t)crc, buf, len); -} -#else -uint32_t Z_EXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t len) { - if (buf == NULL) return 0; - - return functable.crc32(crc, buf, len); -} -#endif - -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(crc32)(unsigned long crc, const unsigned char *buf, unsigned int len) { - return (unsigned long)PREFIX(crc32_z)((uint32_t)crc, buf, len); -} -#else -uint32_t Z_EXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t len) { - return PREFIX(crc32_z)(crc, buf, len); -} -#endif - -/* ========================================================================= */ - -/* - This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit - integer pointer type. This violates the strict aliasing rule, where a - compiler can assume, for optimization purposes, that two pointers to - fundamentally different types won't ever point to the same memory. This can - manifest as a problem only if one of the pointers is written to. This code - only reads from those pointers. So long as this code remains isolated in - this compilation unit, there won't be a problem. For this reason, this code - should not be copied and pasted into a compilation unit in which other code - writes to the buffer that is passed to these routines. - */ - -/* ========================================================================= */ -#if BYTE_ORDER == LITTLE_ENDIAN -#define DOSWAP(crc) (crc) -#define DO1 \ - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8) -#define DO4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#elif BYTE_ORDER == BIG_ENDIAN -#define DOSWAP(crc) ZSWAP32(crc) -#define DO1 \ - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8) -#define DO4 c ^= *buf4++; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#else -# error "No endian defined" -#endif -#define DO32 DO4; DO4; DO4; DO4; DO4; DO4; DO4; DO4 - -/* ========================================================================= */ -Z_INTERNAL uint32_t crc32_byfour(uint32_t crc, const unsigned char *buf, uint64_t len) { - Z_REGISTER uint32_t c; - Z_REGISTER const uint32_t *buf4; - - c = DOSWAP(crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - DO1; - len--; - } - - buf4 = (const uint32_t *)(const void *)buf; - -#ifdef UNROLL_MORE - while (len >= 32) { - DO32; - len -= 32; - } -#endif - - while (len >= 4) { - DO4; - len -= 4; - } - buf = (const unsigned char *)buf4; - - if (len) do { - DO1; - } while (--len); - c = ~c; - return DOSWAP(c); -} diff --git a/crc32_braid.c b/crc32_braid.c new file mode 100644 index 0000000000..3c3cedffbd --- /dev/null +++ b/crc32_braid.c @@ -0,0 +1,267 @@ +/* crc32_braid.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * This interleaved implementation of a CRC makes use of pipelined multiple + * arithmetic-logic units, commonly found in modern CPU cores. It is due to + * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. + */ + +#include "zbuild.h" +#include "zutil.h" +#include "functable.h" +#include "crc32_braid_p.h" +#include "crc32_braid_tbl.h" + +/* ========================================================================= */ + +const uint32_t * Z_EXPORT PREFIX(get_crc_table)(void) { + return (const uint32_t *)crc_table; +} + +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(crc32_z)(unsigned long crc, const unsigned char *buf, size_t len) { + if (buf == NULL) return 0; + + return (unsigned long)functable.crc32((uint32_t)crc, buf, len); +} +#else +uint32_t Z_EXPORT PREFIX(crc32_z)(uint32_t crc, const unsigned char *buf, size_t len) { + if (buf == NULL) return 0; + + return functable.crc32(crc, buf, len); +} +#endif + +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(crc32)(unsigned long crc, const unsigned char *buf, unsigned int len) { + return (unsigned long)PREFIX(crc32_z)((uint32_t)crc, buf, len); +} +#else +uint32_t Z_EXPORT PREFIX(crc32)(uint32_t crc, const unsigned char *buf, uint32_t len) { + return PREFIX(crc32_z)(crc, buf, len); +} +#endif + +/* ========================================================================= */ + +/* + A CRC of a message is computed on N braids of words in the message, where + each word consists of W bytes (4 or 8). If N is 3, for example, then three + running sparse CRCs are calculated respectively on each braid, at these + indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ... + This is done starting at a word boundary, and continues until as many blocks + of N * W bytes as are available have been processed. The results are combined + into a single CRC at the end. For this code, N must be in the range 1..6 and + W must be 4 or 8. The upper limit on N can be increased if desired by adding + more #if blocks, extending the patterns apparent in the code. In addition, + crc32 tables would need to be regenerated, if the maximum N value is increased. + + N and W are chosen empirically by benchmarking the execution time on a given + processor. The choices for N and W below were based on testing on Intel Kaby + Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64 + Octeon II processors. The Intel, AMD, and ARM processors were all fastest + with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4. + They were all tested with either gcc or clang, all using the -O3 optimization + level. Your mileage may vary. +*/ + +/* ========================================================================= */ + +#if BYTE_ORDER == LITTLE_ENDIAN +# define ZSWAPWORD(word) (word) +# define BRAID_TABLE crc_braid_table +#elif BYTE_ORDER == BIG_ENDIAN +# if W == 8 +# define ZSWAPWORD(word) ZSWAP64(word) +# elif W == 4 +# define ZSWAPWORD(word) ZSWAP32(word) +# endif +# define BRAID_TABLE crc_braid_big_table +#else +# error "No endian defined" +#endif +#define DO1 c = crc_table[(c ^ *buf++) & 0xff] ^ (c >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +#ifdef W +/* + Return the CRC of the W bytes in the word_t data, taking the + least-significant byte of the word as the first byte of data, without any pre + or post conditioning. This is used to combine the CRCs of each braid. + */ +#if BYTE_ORDER == LITTLE_ENDIAN +static uint32_t crc_word(z_word_t data) { + int k; + for (k = 0; k < W; k++) + data = (data >> 8) ^ crc_table[data & 0xff]; + return (uint32_t)data; +} +#elif BYTE_ORDER == BIG_ENDIAN +static z_word_t crc_word(z_word_t data) { + int k; + for (k = 0; k < W; k++) + data = (data << 8) ^ + crc_big_table[(data >> ((W - 1) << 3)) & 0xff]; + return data; +} +#endif /* BYTE_ORDER */ + +#endif /* W */ + +/* ========================================================================= */ +Z_INTERNAL uint32_t crc32_braid(uint32_t crc, const unsigned char *buf, uint64_t len) { + Z_REGISTER uint32_t c = crc; + + /* Pre-condition the CRC */ + c ^= 0xffffffff; + +#ifdef W + /* If provided enough bytes, do a braided CRC calculation. */ + if (len >= N * W + W - 1) { + uint64_t blks; + z_word_t const *words; + int k; + + /* Compute the CRC up to a z_word_t boundary. */ + while (len && ((z_size_t)buf & (W - 1)) != 0) { + len--; + DO1; + } + + /* Compute the CRC on as many N z_word_t blocks as are available. */ + blks = len / (N * W); + len -= blks * N * W; + words = (z_word_t const *)buf; + + z_word_t crc0, word0, comb; +#if N > 1 + z_word_t crc1, word1; +#if N > 2 + z_word_t crc2, word2; +#if N > 3 + z_word_t crc3, word3; +#if N > 4 + z_word_t crc4, word4; +#if N > 5 + z_word_t crc5, word5; +#endif +#endif +#endif +#endif +#endif + /* Initialize the CRC for each braid. */ + crc0 = ZSWAPWORD(c); +#if N > 1 + crc1 = 0; +#if N > 2 + crc2 = 0; +#if N > 3 + crc3 = 0; +#if N > 4 + crc4 = 0; +#if N > 5 + crc5 = 0; +#endif +#endif +#endif +#endif +#endif + /* Process the first blks-1 blocks, computing the CRCs on each braid independently. */ + while (--blks) { + /* Load the word for each braid into registers. */ + word0 = crc0 ^ words[0]; +#if N > 1 + word1 = crc1 ^ words[1]; +#if N > 2 + word2 = crc2 ^ words[2]; +#if N > 3 + word3 = crc3 ^ words[3]; +#if N > 4 + word4 = crc4 ^ words[4]; +#if N > 5 + word5 = crc5 ^ words[5]; +#endif +#endif +#endif +#endif +#endif + words += N; + + /* Compute and update the CRC for each word. The loop should get unrolled. */ + crc0 = BRAID_TABLE[0][word0 & 0xff]; +#if N > 1 + crc1 = BRAID_TABLE[0][word1 & 0xff]; +#if N > 2 + crc2 = BRAID_TABLE[0][word2 & 0xff]; +#if N > 3 + crc3 = BRAID_TABLE[0][word3 & 0xff]; +#if N > 4 + crc4 = BRAID_TABLE[0][word4 & 0xff]; +#if N > 5 + crc5 = BRAID_TABLE[0][word5 & 0xff]; +#endif +#endif +#endif +#endif +#endif + for (k = 1; k < W; k++) { + crc0 ^= BRAID_TABLE[k][(word0 >> (k << 3)) & 0xff]; +#if N > 1 + crc1 ^= BRAID_TABLE[k][(word1 >> (k << 3)) & 0xff]; +#if N > 2 + crc2 ^= BRAID_TABLE[k][(word2 >> (k << 3)) & 0xff]; +#if N > 3 + crc3 ^= BRAID_TABLE[k][(word3 >> (k << 3)) & 0xff]; +#if N > 4 + crc4 ^= BRAID_TABLE[k][(word4 >> (k << 3)) & 0xff]; +#if N > 5 + crc5 ^= BRAID_TABLE[k][(word5 >> (k << 3)) & 0xff]; +#endif +#endif +#endif +#endif +#endif + } + } + + /* Process the last block, combining the CRCs of the N braids at the same time. */ + comb = crc_word(crc0 ^ words[0]); +#if N > 1 + comb = crc_word(crc1 ^ words[1] ^ comb); +#if N > 2 + comb = crc_word(crc2 ^ words[2] ^ comb); +#if N > 3 + comb = crc_word(crc3 ^ words[3] ^ comb); +#if N > 4 + comb = crc_word(crc4 ^ words[4] ^ comb); +#if N > 5 + comb = crc_word(crc5 ^ words[5] ^ comb); +#endif +#endif +#endif +#endif +#endif + words += N; + c = ZSWAPWORD(comb); + + /* Update the pointer to the remaining bytes to process. */ + buf = (const unsigned char *)words; + } + +#endif /* W */ + + /* Complete the computation of the CRC on any remaining bytes. */ + while (len >= 8) { + len -= 8; + DO8; + } + while (len) { + len--; + DO1; + } + + /* Return the CRC, post-conditioned. */ + return c ^ 0xffffffff; +} diff --git a/crc32_braid_comb.c b/crc32_braid_comb.c new file mode 100644 index 0000000000..51ebf9d009 --- /dev/null +++ b/crc32_braid_comb.c @@ -0,0 +1,63 @@ +/* crc32_braid_comb.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * This interleaved implementation of a CRC makes use of pipelined multiple + * arithmetic-logic units, commonly found in modern CPU cores. It is due to + * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution. + */ + +#include "zbuild.h" +#include "zutil.h" +#include "crc32_braid_p.h" +#include "crc32_braid_tbl.h" +#include "crc32_braid_comb_p.h" + +/* ========================================================================= */ +static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) { + return multmodp(x2nmodp(len2, 3), crc1) ^ crc2; +} + +/* ========================================================================= */ +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off_t len2) { + return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); +} + +unsigned long Z_EXPORT PREFIX4(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off64_t len2) { + return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); +} +#else +uint32_t Z_EXPORT PREFIX4(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off64_t len2) { + return crc32_combine_(crc1, crc2, len2); +} +#endif + +/* ========================================================================= */ + +static uint32_t crc32_combine_gen_(z_off64_t len2) { + return x2nmodp(len2, 3); +} + +/* ========================================================================= */ + +#ifdef ZLIB_COMPAT +unsigned long Z_EXPORT PREFIX(crc32_combine_gen)(z_off_t len2) { + return crc32_combine_gen_(len2); +} +unsigned long Z_EXPORT PREFIX4(crc32_combine_gen)(z_off64_t len2) { + return crc32_combine_gen_(len2); +} +unsigned long Z_EXPORT PREFIX(crc32_combine_op)(unsigned long crc1, unsigned long crc2, const unsigned long op) { + return multmodp(op, crc1) ^ crc2; +} +#else +uint32_t Z_EXPORT PREFIX(crc32_combine_gen)(z_off64_t len2) { + return crc32_combine_gen_(len2); +} +uint32_t Z_EXPORT PREFIX(crc32_combine_op)(uint32_t crc1, uint32_t crc2, const uint32_t op) { + return multmodp(op, crc1) ^ crc2; +} +#endif + +/* ========================================================================= */ diff --git a/crc32_braid_comb_p.h b/crc32_braid_comb_p.h new file mode 100644 index 0000000000..8a00cfa778 --- /dev/null +++ b/crc32_braid_comb_p.h @@ -0,0 +1,41 @@ +#ifndef CRC32_BRAID_COMB_P_H_ +#define CRC32_BRAID_COMB_P_H_ + +/* + Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial, + reflected. For speed, this requires that a not be zero. + */ +static uint32_t multmodp(uint32_t a, uint32_t b) { + uint32_t m, p; + + m = (uint32_t)1 << 31; + p = 0; + for (;;) { + if (a & m) { + p ^= b; + if ((a & (m - 1)) == 0) + break; + } + m >>= 1; + b = b & 1 ? (b >> 1) ^ POLY : b >> 1; + } + return p; +} + +/* + Return x^(n+k) modulo p(x). Requires that x2n_table[] has been initialized. + */ +static uint32_t x2nmodp(z_off64_t n, unsigned k) { + uint32_t p; + + p = (uint32_t)1 << 31; /* x^0 == 1 */ + while (n) { + if (n & 1) + p = multmodp(x2n_table[k & 31], p); + n >>= 1; + k++; + } + return p; +} + +#endif /* CRC32_BRAID_COMB_P_H_ */ diff --git a/crc32_braid_p.h b/crc32_braid_p.h new file mode 100644 index 0000000000..28a8a9e7a9 --- /dev/null +++ b/crc32_braid_p.h @@ -0,0 +1,50 @@ +#ifndef CRC32_BRAID_P_H_ +#define CRC32_BRAID_P_H_ + +#include "zbuild.h" +#include "zendian.h" + +/* Define N */ +#ifdef Z_TESTN +# define N Z_TESTN +#else +# define N 5 +#endif +#if N < 1 || N > 6 +# error N must be in 1..6 +#endif + +/* + Define W and the associated z_word_t type. If W is not defined, then a + braided calculation is not used, and the associated tables and code are not + compiled. + */ +#ifdef Z_TESTW +# if Z_TESTW-1 != -1 +# define W Z_TESTW +# endif +#else +# ifndef W +# if defined(__x86_64__) || defined(__aarch64__) +# define W 8 +# else +# define W 4 +# endif +# endif +#endif +#ifdef W +# if W == 8 + typedef uint64_t z_word_t; +# else +# undef W +# define W 4 + typedef uint32_t z_word_t; +# endif +#endif + +/* CRC polynomial. */ +#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */ + +extern uint32_t crc32_braid(uint32_t crc, const unsigned char *buf, uint64_t len); + +#endif /* CRC32_BRAID_P_H_ */ diff --git a/crc32_braid_tbl.h b/crc32_braid_tbl.h new file mode 100644 index 0000000000..84d79a69e7 --- /dev/null +++ b/crc32_braid_tbl.h @@ -0,0 +1,9446 @@ +#ifndef CRC32_BRAID_TBL_H_ +#define CRC32_BRAID_TBL_H_ + +/* crc32_braid_tbl.h -- tables for braided CRC calculation + * Generated automatically by makecrct.c + */ + +static const uint32_t crc_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}; + +#ifdef W + +#if W == 8 + +static const z_word_t crc_big_table[] = { + 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}; + +#else /* W == 4 */ + +static const z_word_t crc_big_table[] = { + 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}; + +#endif + +#endif /* W */ + +#if N == 1 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}, + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000, + 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000, + 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000, + 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000, + 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000, + 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000, + 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000, + 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000, + 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000, + 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000, + 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000, + 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000, + 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000, + 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000, + 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000, + 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000, + 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000, + 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000, + 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000, + 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000, + 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000, + 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000, + 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000, + 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000, + 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000, + 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000, + 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000, + 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000, + 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000, + 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000, + 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000, + 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000, + 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000, + 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000, + 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000, + 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000, + 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000, + 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000, + 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000, + 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000, + 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000, + 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000, + 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000, + 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000, + 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000, + 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000, + 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000, + 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000, + 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000, + 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000, + 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000, + 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000, + 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000, + 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000, + 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000, + 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000, + 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000, + 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000, + 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000, + 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000, + 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000, + 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000, + 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000, + 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000, + 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000, + 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000, + 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000, + 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000, + 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000, + 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000, + 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000, + 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000, + 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000, + 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000, + 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000, + 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000, + 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000, + 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000, + 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000, + 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000, + 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000, + 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000, + 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000, + 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000, + 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000, + 0x8def022d00000000}, + {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000, + 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000, + 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000, + 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000, + 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000, + 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000, + 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000, + 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000, + 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000, + 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000, + 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000, + 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000, + 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000, + 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000, + 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000, + 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000, + 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000, + 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000, + 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000, + 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000, + 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000, + 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000, + 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000, + 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000, + 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000, + 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000, + 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000, + 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000, + 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000, + 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000, + 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000, + 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000, + 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000, + 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000, + 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000, + 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000, + 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000, + 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000, + 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000, + 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000, + 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000, + 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000, + 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000, + 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000, + 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000, + 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000, + 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000, + 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000, + 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000, + 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000, + 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000, + 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000, + 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000, + 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000, + 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000, + 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000, + 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000, + 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000, + 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000, + 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000, + 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000, + 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000, + 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000, + 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000, + 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000, + 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000, + 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000, + 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000, + 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000, + 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000, + 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000, + 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000, + 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000, + 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000, + 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000, + 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000, + 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000, + 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000, + 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000, + 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000, + 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000, + 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000, + 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000, + 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000, + 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000, + 0x72fd249300000000}, + {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000, + 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000, + 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000, + 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000, + 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000, + 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000, + 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000, + 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000, + 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000, + 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000, + 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000, + 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000, + 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000, + 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000, + 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000, + 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000, + 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000, + 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000, + 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000, + 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000, + 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000, + 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000, + 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000, + 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000, + 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000, + 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000, + 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000, + 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000, + 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000, + 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000, + 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000, + 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000, + 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000, + 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000, + 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000, + 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000, + 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000, + 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000, + 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000, + 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000, + 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000, + 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000, + 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000, + 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000, + 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000, + 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000, + 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000, + 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000, + 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000, + 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000, + 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000, + 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000, + 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000, + 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000, + 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000, + 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000, + 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000, + 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000, + 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000, + 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000, + 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000, + 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000, + 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000, + 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000, + 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000, + 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000, + 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000, + 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000, + 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000, + 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000, + 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000, + 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000, + 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000, + 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000, + 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000, + 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000, + 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000, + 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000, + 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000, + 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000, + 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000, + 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000, + 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000, + 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000, + 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000, + 0xed3498be00000000}, + {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000, + 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000, + 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000, + 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000, + 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000, + 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000, + 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000, + 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000, + 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000, + 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000, + 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000, + 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000, + 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000, + 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000, + 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000, + 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000, + 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000, + 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000, + 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000, + 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000, + 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000, + 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000, + 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000, + 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000, + 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000, + 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000, + 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000, + 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000, + 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000, + 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000, + 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000, + 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000, + 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000, + 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000, + 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000, + 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000, + 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000, + 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000, + 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000, + 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000, + 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000, + 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000, + 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000, + 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000, + 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000, + 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000, + 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000, + 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000, + 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000, + 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000, + 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000, + 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000, + 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000, + 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000, + 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000, + 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000, + 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000, + 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000, + 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000, + 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000, + 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000, + 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000, + 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000, + 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000, + 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000, + 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000, + 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000, + 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000, + 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000, + 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000, + 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000, + 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000, + 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000, + 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000, + 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000, + 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000, + 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000, + 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000, + 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000, + 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000, + 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000, + 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000, + 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000, + 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000, + 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000, + 0xf10605de00000000}, + {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000, + 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000, + 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000, + 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000, + 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000, + 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000, + 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000, + 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000, + 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000, + 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000, + 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000, + 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000, + 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000, + 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000, + 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000, + 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000, + 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000, + 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000, + 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000, + 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000, + 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000, + 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000, + 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000, + 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000, + 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000, + 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000, + 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000, + 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000, + 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000, + 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000, + 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000, + 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000, + 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000, + 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000, + 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000, + 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000, + 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000, + 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000, + 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000, + 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000, + 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000, + 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000, + 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000, + 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000, + 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000, + 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000, + 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000, + 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000, + 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000, + 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000, + 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000, + 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000, + 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000, + 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000, + 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000, + 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000, + 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000, + 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000, + 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000, + 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000, + 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000, + 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000, + 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000, + 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000, + 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000, + 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000, + 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000, + 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000, + 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000, + 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000, + 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000, + 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000, + 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000, + 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000, + 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000, + 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000, + 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000, + 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000, + 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000, + 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000, + 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000, + 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000, + 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000, + 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000, + 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000, + 0x8cc764ca00000000}, + {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000, + 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000, + 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000, + 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000, + 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000, + 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000, + 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000, + 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000, + 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000, + 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000, + 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000, + 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000, + 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000, + 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000, + 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000, + 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000, + 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000, + 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000, + 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000, + 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000, + 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000, + 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000, + 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000, + 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000, + 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000, + 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000, + 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000, + 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000, + 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000, + 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000, + 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000, + 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000, + 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000, + 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000, + 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000, + 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000, + 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000, + 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000, + 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000, + 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000, + 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000, + 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000, + 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000, + 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000, + 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000, + 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000, + 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000, + 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000, + 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000, + 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000, + 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000, + 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000, + 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000, + 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000, + 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000, + 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000, + 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000, + 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000, + 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000, + 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000, + 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000, + 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000, + 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000, + 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000, + 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000, + 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000, + 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000, + 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000, + 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000, + 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000, + 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000, + 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000, + 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000, + 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000, + 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000, + 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000, + 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000, + 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000, + 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000, + 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000, + 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000, + 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000, + 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000, + 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000, + 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000, + 0xccabc4e400000000}, + {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000, + 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000, + 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000, + 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000, + 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000, + 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000, + 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000, + 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000, + 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000, + 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000, + 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000, + 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000, + 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000, + 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000, + 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000, + 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000, + 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000, + 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000, + 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000, + 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000, + 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000, + 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000, + 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000, + 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000, + 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000, + 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000, + 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000, + 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000, + 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000, + 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000, + 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000, + 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000, + 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000, + 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000, + 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000, + 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000, + 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000, + 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000, + 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000, + 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000, + 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000, + 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000, + 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000, + 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000, + 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000, + 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000, + 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000, + 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000, + 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000, + 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000, + 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000, + 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000, + 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000, + 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000, + 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000, + 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000, + 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000, + 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000, + 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000, + 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000, + 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000, + 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000, + 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000, + 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000, + 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000, + 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000, + 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000, + 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000, + 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000, + 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000, + 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000, + 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000, + 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000, + 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000, + 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000, + 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000, + 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000, + 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000, + 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000, + 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000, + 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000, + 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000, + 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000, + 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000, + 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000, + 0x304a369200000000}, + {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000, + 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000, + 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000, + 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000, + 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000, + 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000, + 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000, + 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000, + 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000, + 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000, + 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000, + 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000, + 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000, + 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000, + 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000, + 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000, + 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000, + 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000, + 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000, + 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000, + 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000, + 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000, + 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000, + 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000, + 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000, + 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000, + 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000, + 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000, + 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000, + 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000, + 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000, + 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000, + 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000, + 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000, + 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000, + 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000, + 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000, + 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000, + 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000, + 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000, + 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000, + 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000, + 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000, + 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000, + 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000, + 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000, + 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000, + 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000, + 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000, + 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000, + 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000, + 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000, + 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000, + 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000, + 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000, + 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000, + 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000, + 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000, + 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000, + 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000, + 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000, + 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000, + 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000, + 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000, + 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000, + 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000, + 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000, + 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000, + 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000, + 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000, + 0x6171384400000000, 0xff71928800000000, 0xe678578200000000, + 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000, + 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000, + 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000, + 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000, + 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000, + 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000, + 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000, + 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000, + 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000, + 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000, + 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000, + 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000, + 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000, + 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000, + 0xe6064b2600000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, + 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, + 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, + 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, + 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, + 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, + 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, + 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, + 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, + 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, + 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, + 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, + 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, + 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, + 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, + 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, + 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, + 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, + 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, + 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, + 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, + 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, + 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, + 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, + 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, + 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, + 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, + 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, + 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, + 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, + 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, + 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, + 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, + 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, + 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, + 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, + 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, + 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, + 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, + 0xde0506f1}, + {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, + 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, + 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, + 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, + 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, + 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, + 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, + 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, + 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, + 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, + 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, + 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, + 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, + 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, + 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, + 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, + 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, + 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, + 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, + 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, + 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, + 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, + 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, + 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, + 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, + 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, + 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, + 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, + 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, + 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, + 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, + 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, + 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, + 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, + 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, + 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, + 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, + 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, + 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, + 0xbe9834ed}, + {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, + 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, + 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, + 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, + 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, + 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, + 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, + 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, + 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, + 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, + 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, + 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, + 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, + 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, + 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, + 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, + 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, + 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, + 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, + 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, + 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, + 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, + 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, + 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, + 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, + 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, + 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, + 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, + 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, + 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, + 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, + 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, + 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, + 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, + 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, + 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, + 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, + 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, + 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, + 0x9324fd72}, + {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, + 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, + 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, + 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, + 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, + 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, + 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, + 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, + 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, + 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, + 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, + 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, + 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, + 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, + 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, + 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, + 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, + 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, + 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, + 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, + 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, + 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, + 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, + 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, + 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, + 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, + 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, + 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, + 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, + 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, + 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, + 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, + 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, + 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, + 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, + 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, + 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, + 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, + 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, + 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, + 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, + 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, + 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, + 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, + 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, + 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, + 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, + 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, + 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, + 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, + 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, + 0x8def022d}, + {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, + 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, + 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, + 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, + 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, + 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, + 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, + 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, + 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, + 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, + 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, + 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, + 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, + 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, + 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, + 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, + 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, + 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, + 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, + 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, + 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, + 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, + 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, + 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, + 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, + 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, + 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, + 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, + 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, + 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, + 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, + 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, + 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, + 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, + 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, + 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, + 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, + 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, + 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, + 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, + 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, + 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, + 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, + 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, + 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, + 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, + 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, + 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, + 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, + 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, + 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, + 0x72fd2493}, + {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, + 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, + 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, + 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, + 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, + 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, + 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, + 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, + 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, + 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, + 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, + 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, + 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, + 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, + 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, + 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, + 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, + 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, + 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, + 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, + 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, + 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, + 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, + 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, + 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, + 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, + 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, + 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, + 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, + 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, + 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, + 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, + 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, + 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, + 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, + 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, + 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, + 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, + 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, + 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, + 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, + 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, + 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, + 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, + 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, + 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, + 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, + 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, + 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, + 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, + 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, + 0xed3498be}, + {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, + 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, + 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, + 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, + 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, + 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, + 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, + 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, + 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, + 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, + 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, + 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, + 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, + 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, + 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, + 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, + 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, + 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, + 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, + 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, + 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, + 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, + 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, + 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, + 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, + 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, + 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, + 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, + 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, + 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, + 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, + 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, + 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, + 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, + 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, + 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, + 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, + 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, + 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, + 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, + 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, + 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, + 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, + 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, + 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, + 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, + 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, + 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, + 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, + 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, + 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, + 0xf10605de}}; + +#endif /* W */ + +#endif /* N == 1 */ +#if N == 2 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}, + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000, + 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000, + 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000, + 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000, + 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000, + 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000, + 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000, + 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000, + 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000, + 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000, + 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000, + 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000, + 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000, + 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000, + 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000, + 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000, + 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000, + 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000, + 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000, + 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000, + 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000, + 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000, + 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000, + 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000, + 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000, + 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000, + 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000, + 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000, + 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000, + 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000, + 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000, + 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000, + 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000, + 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000, + 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000, + 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000, + 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000, + 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000, + 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000, + 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000, + 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000, + 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000, + 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000, + 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000, + 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000, + 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000, + 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000, + 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000, + 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000, + 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000, + 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000, + 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000, + 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000, + 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000, + 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000, + 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000, + 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000, + 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000, + 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000, + 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000, + 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000, + 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000, + 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000, + 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000, + 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000, + 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000, + 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000, + 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000, + 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000, + 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000, + 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000, + 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000, + 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000, + 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000, + 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000, + 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000, + 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000, + 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000, + 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000, + 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000, + 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000, + 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000, + 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000, + 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000, + 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000, + 0x4b0c4f4900000000}, + {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000, + 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000, + 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000, + 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000, + 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000, + 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000, + 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000, + 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000, + 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000, + 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000, + 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000, + 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000, + 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000, + 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000, + 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000, + 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000, + 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000, + 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000, + 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000, + 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000, + 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000, + 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000, + 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000, + 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000, + 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000, + 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000, + 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000, + 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000, + 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000, + 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000, + 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000, + 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000, + 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000, + 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000, + 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000, + 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000, + 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000, + 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000, + 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000, + 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000, + 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000, + 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000, + 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000, + 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000, + 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000, + 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000, + 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000, + 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000, + 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000, + 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000, + 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000, + 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000, + 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000, + 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000, + 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000, + 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000, + 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000, + 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000, + 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000, + 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000, + 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000, + 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000, + 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000, + 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000, + 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000, + 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000, + 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000, + 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000, + 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000, + 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000, + 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000, + 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000, + 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000, + 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000, + 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000, + 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000, + 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000, + 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000, + 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000, + 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000, + 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000, + 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000, + 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000, + 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000, + 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000, + 0x14d747e100000000}, + {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000, + 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000, + 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000, + 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000, + 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000, + 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000, + 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000, + 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000, + 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000, + 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000, + 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000, + 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000, + 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000, + 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000, + 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000, + 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000, + 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000, + 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000, + 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000, + 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000, + 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000, + 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000, + 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000, + 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000, + 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000, + 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000, + 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000, + 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000, + 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000, + 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000, + 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000, + 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000, + 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000, + 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000, + 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000, + 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000, + 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000, + 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000, + 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000, + 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000, + 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000, + 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000, + 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000, + 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000, + 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000, + 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000, + 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000, + 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000, + 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000, + 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000, + 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000, + 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000, + 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000, + 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000, + 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000, + 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000, + 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000, + 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000, + 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000, + 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000, + 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000, + 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000, + 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000, + 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000, + 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000, + 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000, + 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000, + 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000, + 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000, + 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000, + 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000, + 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000, + 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000, + 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000, + 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000, + 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000, + 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000, + 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000, + 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000, + 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000, + 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000, + 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000, + 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000, + 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000, + 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000, + 0xaa933b1a00000000}, + {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000, + 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000, + 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000, + 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000, + 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000, + 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000, + 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000, + 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000, + 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000, + 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000, + 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000, + 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000, + 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000, + 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000, + 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000, + 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000, + 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000, + 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000, + 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000, + 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000, + 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000, + 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000, + 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000, + 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000, + 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000, + 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000, + 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000, + 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000, + 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000, + 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000, + 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000, + 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000, + 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000, + 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000, + 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000, + 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000, + 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000, + 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000, + 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000, + 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000, + 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000, + 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000, + 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000, + 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000, + 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000, + 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000, + 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000, + 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000, + 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000, + 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000, + 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000, + 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000, + 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000, + 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000, + 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000, + 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000, + 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000, + 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000, + 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000, + 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000, + 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000, + 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000, + 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000, + 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000, + 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000, + 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000, + 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000, + 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000, + 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000, + 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000, + 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000, + 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000, + 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000, + 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000, + 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000, + 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000, + 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000, + 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000, + 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000, + 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000, + 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000, + 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000, + 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000, + 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000, + 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000, + 0x6571193600000000}, + {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000, + 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000, + 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000, + 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000, + 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000, + 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000, + 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000, + 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000, + 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000, + 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000, + 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000, + 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000, + 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000, + 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000, + 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000, + 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000, + 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000, + 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000, + 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000, + 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000, + 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000, + 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000, + 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000, + 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000, + 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000, + 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000, + 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000, + 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000, + 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000, + 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000, + 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000, + 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000, + 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000, + 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000, + 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000, + 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000, + 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000, + 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000, + 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000, + 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000, + 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000, + 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000, + 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000, + 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000, + 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000, + 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000, + 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000, + 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000, + 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000, + 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000, + 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000, + 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000, + 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000, + 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000, + 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000, + 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000, + 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000, + 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000, + 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000, + 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000, + 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000, + 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000, + 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000, + 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000, + 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000, + 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000, + 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000, + 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000, + 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000, + 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000, + 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000, + 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000, + 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000, + 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000, + 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000, + 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000, + 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000, + 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000, + 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000, + 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000, + 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000, + 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000, + 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000, + 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000, + 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000, + 0xa68cee3d00000000}, + {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000, + 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000, + 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000, + 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000, + 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000, + 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000, + 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000, + 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000, + 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000, + 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000, + 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000, + 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000, + 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000, + 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000, + 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000, + 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000, + 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000, + 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000, + 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000, + 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000, + 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000, + 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000, + 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000, + 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000, + 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000, + 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000, + 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000, + 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000, + 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000, + 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000, + 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000, + 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000, + 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000, + 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000, + 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000, + 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000, + 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000, + 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000, + 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000, + 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000, + 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000, + 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000, + 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000, + 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000, + 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000, + 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000, + 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000, + 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000, + 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000, + 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000, + 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000, + 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000, + 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000, + 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000, + 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000, + 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000, + 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000, + 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000, + 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000, + 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000, + 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000, + 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000, + 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000, + 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000, + 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000, + 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000, + 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000, + 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000, + 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000, + 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000, + 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000, + 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000, + 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000, + 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000, + 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000, + 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000, + 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000, + 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000, + 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000, + 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000, + 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000, + 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000, + 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000, + 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000, + 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000, + 0x51e8883f00000000}, + {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000, + 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000, + 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000, + 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000, + 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000, + 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000, + 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000, + 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000, + 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000, + 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000, + 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000, + 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000, + 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000, + 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000, + 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000, + 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000, + 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000, + 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000, + 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000, + 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000, + 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000, + 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000, + 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000, + 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000, + 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000, + 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000, + 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000, + 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000, + 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000, + 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000, + 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000, + 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000, + 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000, + 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000, + 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000, + 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000, + 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000, + 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000, + 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000, + 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000, + 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000, + 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000, + 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000, + 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000, + 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000, + 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000, + 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000, + 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000, + 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000, + 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000, + 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000, + 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000, + 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000, + 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000, + 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000, + 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000, + 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000, + 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000, + 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000, + 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000, + 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000, + 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000, + 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000, + 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000, + 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000, + 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000, + 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000, + 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000, + 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000, + 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000, + 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000, + 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000, + 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000, + 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000, + 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000, + 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000, + 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000, + 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000, + 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000, + 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000, + 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000, + 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000, + 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000, + 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000, + 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000, + 0x8ae9531c00000000}, + {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000, + 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000, + 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000, + 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000, + 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000, + 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000, + 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000, + 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000, + 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000, + 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000, + 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000, + 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000, + 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000, + 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000, + 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000, + 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000, + 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000, + 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000, + 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000, + 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000, + 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000, + 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000, + 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000, + 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000, + 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000, + 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000, + 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000, + 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000, + 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000, + 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000, + 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000, + 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000, + 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000, + 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000, + 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000, + 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000, + 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000, + 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000, + 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000, + 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000, + 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000, + 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000, + 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000, + 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000, + 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000, + 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000, + 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000, + 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000, + 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000, + 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000, + 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000, + 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000, + 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000, + 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000, + 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000, + 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000, + 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000, + 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000, + 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000, + 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000, + 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000, + 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000, + 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000, + 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000, + 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000, + 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000, + 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000, + 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000, + 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000, + 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000, + 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000, + 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000, + 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000, + 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000, + 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000, + 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000, + 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000, + 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000, + 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000, + 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000, + 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000, + 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000, + 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000, + 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000, + 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000, + 0xd739710d00000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, + 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, + 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232, + 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8, + 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e, + 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, + 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, + 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f, + 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719, + 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3, + 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa, + 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, + 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, + 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89, + 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25, + 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041, + 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c, + 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, + 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, + 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758, + 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e, + 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a, + 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed, + 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, + 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, + 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544, + 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d, + 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c, + 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1, + 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, + 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, + 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, + 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976, + 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7, + 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be, + 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, + 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, + 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, + 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a, + 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e, + 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278, + 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, + 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, + 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a, + 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561, + 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05, + 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9, + 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, + 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, + 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, + 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678, + 0x264b06e6}, + {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, + 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3, + 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d, + 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653, + 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9, + 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, + 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, + 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712, + 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8, + 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6, + 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068, + 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, + 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, + 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade, + 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37, + 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590, + 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4, + 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, + 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, + 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678, + 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282, + 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25, + 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102, + 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, + 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, + 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146, + 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8, + 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08, + 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c, + 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, + 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, + 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5, + 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d, + 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd, + 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833, + 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, + 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, + 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60, + 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2, + 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105, + 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff, + 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, + 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, + 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, + 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617, + 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0, + 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959, + 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, + 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, + 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a, + 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184, + 0x92364a30}, + {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, + 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8, + 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170, + 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035, + 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6, + 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, + 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, + 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e, + 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d, + 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408, + 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0, + 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, + 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, + 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf, + 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a, + 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9, + 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1, + 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, + 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, + 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4, + 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37, + 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84, + 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca, + 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, + 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, + 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, + 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5, + 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b, + 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643, + 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, + 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, + 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496, + 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8, + 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026, + 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e, + 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, + 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, + 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab, + 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf, + 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c, + 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf, + 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, + 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, + 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec, + 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82, + 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31, + 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4, + 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, + 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, + 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1, + 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869, + 0xe4c4abcc}, + {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, + 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271, + 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61, + 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52, + 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43, + 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, + 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, + 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314, + 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205, + 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136, + 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26, + 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, + 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, + 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739, + 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8, + 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98, + 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b, + 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, + 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, + 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d, + 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c, + 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc, + 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af, + 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, + 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, + 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922, + 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532, + 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183, + 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710, + 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, + 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, + 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1, + 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956, + 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7, + 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7, + 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, + 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, + 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5, + 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb, + 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb, + 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da, + 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, + 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, + 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48, + 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df, + 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af, + 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e, + 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, + 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, + 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c, + 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c, + 0xca64c78c}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5, + 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d, + 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf, + 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027, + 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050, + 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098, + 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb, + 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173, + 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104, + 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c, + 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e, + 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6, + 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358, + 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390, + 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312, + 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da, + 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd, + 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335, + 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387, + 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de, + 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9, + 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261, + 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283, + 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b, + 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c, + 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c, + 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e, + 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6, + 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1, + 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619, + 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b, + 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653, + 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785, + 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d, + 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf, + 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757, + 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720, + 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8, + 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593, + 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b, + 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c, + 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4, + 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506, + 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe, + 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428, + 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0, + 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462, + 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa, + 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd, + 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445, + 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7, + 0x8cc764ca}, + {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b, + 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27, + 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a, + 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285, + 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef, + 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf, + 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a, + 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a, + 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70, + 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf, + 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2, + 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e, + 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f, + 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f, + 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae, + 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe, + 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97, + 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b, + 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436, + 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e, + 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4, + 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4, + 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46, + 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716, + 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c, + 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5, + 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8, + 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774, + 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d, + 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d, + 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc, + 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec, + 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82, + 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e, + 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623, + 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c, + 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6, + 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6, + 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c, + 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c, + 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66, + 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9, + 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4, + 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978, + 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416, + 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946, + 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7, + 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7, + 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e, + 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32, + 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f, + 0xccabc4e4}, + {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4, + 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895, + 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50, + 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656, + 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154, + 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906, + 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258, + 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a, + 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08, + 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e, + 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb, + 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa, + 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44, + 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316, + 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0, + 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2, + 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7, + 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6, + 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73, + 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba, + 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8, + 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea, + 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b, + 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29, + 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b, + 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e, + 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb, + 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a, + 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef, + 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd, + 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b, + 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019, + 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3, + 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2, + 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417, + 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11, + 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13, + 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241, + 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b, + 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09, + 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b, + 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d, + 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8, + 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9, + 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003, + 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851, + 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7, + 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5, + 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190, + 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1, + 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134, + 0x304a3692}, + {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84, + 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f, + 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15, + 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2, + 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf, + 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7, + 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb, + 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3, + 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae, + 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749, + 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243, + 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8, + 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29, + 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61, + 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8, + 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0, + 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1, + 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a, + 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40, + 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e, + 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03, + 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b, + 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee, + 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6, + 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb, + 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f, + 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495, + 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e, + 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f, + 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067, + 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be, + 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6, + 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e, + 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5, + 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf, + 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958, + 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305, + 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d, + 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338, + 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370, + 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d, + 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca, + 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0, + 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b, + 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083, + 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb, + 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012, + 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a, + 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b, + 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0, + 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea, + 0xe6064b26}}; + +#endif /* W */ + +#endif /* N == 2 */ +#if N == 3 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}, + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000, + 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000, + 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000, + 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000, + 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000, + 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000, + 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000, + 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000, + 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000, + 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000, + 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000, + 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000, + 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000, + 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000, + 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000, + 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000, + 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000, + 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000, + 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000, + 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000, + 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000, + 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000, + 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000, + 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000, + 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000, + 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000, + 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000, + 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000, + 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000, + 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000, + 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000, + 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000, + 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000, + 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000, + 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000, + 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000, + 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000, + 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000, + 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000, + 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000, + 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000, + 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000, + 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000, + 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000, + 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000, + 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000, + 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000, + 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000, + 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000, + 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000, + 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000, + 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000, + 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000, + 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000, + 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000, + 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000, + 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000, + 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000, + 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000, + 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000, + 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000, + 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000, + 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000, + 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000, + 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000, + 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000, + 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000, + 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000, + 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000, + 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000, + 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000, + 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000, + 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000, + 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000, + 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000, + 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000, + 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000, + 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000, + 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000, + 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000, + 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000, + 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000, + 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000, + 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000, + 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000, + 0x4e36ba1800000000}, + {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000, + 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000, + 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000, + 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000, + 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000, + 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000, + 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000, + 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000, + 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000, + 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000, + 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000, + 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000, + 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000, + 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000, + 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000, + 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000, + 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000, + 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000, + 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000, + 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000, + 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000, + 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000, + 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000, + 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000, + 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000, + 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000, + 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000, + 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000, + 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000, + 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000, + 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000, + 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000, + 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000, + 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000, + 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000, + 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000, + 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000, + 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000, + 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000, + 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000, + 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000, + 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000, + 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000, + 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000, + 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000, + 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000, + 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000, + 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000, + 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000, + 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000, + 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000, + 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000, + 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000, + 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000, + 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000, + 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000, + 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000, + 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000, + 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000, + 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000, + 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000, + 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000, + 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000, + 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000, + 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000, + 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000, + 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000, + 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000, + 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000, + 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000, + 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000, + 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000, + 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000, + 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000, + 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000, + 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000, + 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000, + 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000, + 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000, + 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000, + 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000, + 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000, + 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000, + 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000, + 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000, + 0xa1d67c9100000000}, + {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000, + 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000, + 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000, + 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000, + 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000, + 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000, + 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000, + 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000, + 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000, + 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000, + 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000, + 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000, + 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000, + 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000, + 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000, + 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000, + 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000, + 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000, + 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000, + 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000, + 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000, + 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000, + 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000, + 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000, + 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000, + 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000, + 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000, + 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000, + 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000, + 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000, + 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000, + 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000, + 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000, + 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000, + 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000, + 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000, + 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000, + 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000, + 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000, + 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000, + 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000, + 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000, + 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000, + 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000, + 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000, + 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000, + 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000, + 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000, + 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000, + 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000, + 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000, + 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000, + 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000, + 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000, + 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000, + 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000, + 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000, + 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000, + 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000, + 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000, + 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000, + 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000, + 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000, + 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000, + 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000, + 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000, + 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000, + 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000, + 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000, + 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000, + 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000, + 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000, + 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000, + 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000, + 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000, + 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000, + 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000, + 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000, + 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000, + 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000, + 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000, + 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000, + 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000, + 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000, + 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000, + 0xa8ef40a100000000}, + {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000, + 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000, + 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000, + 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000, + 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000, + 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000, + 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000, + 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000, + 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000, + 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000, + 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000, + 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000, + 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000, + 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000, + 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000, + 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000, + 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000, + 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000, + 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000, + 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000, + 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000, + 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000, + 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000, + 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000, + 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000, + 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000, + 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000, + 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000, + 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000, + 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000, + 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000, + 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000, + 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000, + 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000, + 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000, + 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000, + 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000, + 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000, + 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000, + 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000, + 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000, + 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000, + 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000, + 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000, + 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000, + 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000, + 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000, + 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000, + 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000, + 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000, + 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000, + 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000, + 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000, + 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000, + 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000, + 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000, + 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000, + 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000, + 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000, + 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000, + 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000, + 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000, + 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000, + 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000, + 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000, + 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000, + 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000, + 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000, + 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000, + 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000, + 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000, + 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000, + 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000, + 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000, + 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000, + 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000, + 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000, + 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000, + 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000, + 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000, + 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000, + 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000, + 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000, + 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000, + 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000, + 0x356bacd800000000}, + {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000, + 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000, + 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000, + 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000, + 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000, + 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000, + 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000, + 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000, + 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000, + 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000, + 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000, + 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000, + 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000, + 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000, + 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000, + 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000, + 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000, + 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000, + 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000, + 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000, + 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000, + 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000, + 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000, + 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000, + 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000, + 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000, + 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000, + 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000, + 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000, + 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000, + 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000, + 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000, + 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000, + 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000, + 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000, + 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000, + 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000, + 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000, + 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000, + 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000, + 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000, + 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000, + 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000, + 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000, + 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000, + 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000, + 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000, + 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000, + 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000, + 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000, + 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000, + 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000, + 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000, + 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000, + 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000, + 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000, + 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000, + 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000, + 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000, + 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000, + 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000, + 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000, + 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000, + 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000, + 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000, + 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000, + 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000, + 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000, + 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000, + 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000, + 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000, + 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000, + 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000, + 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000, + 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000, + 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000, + 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000, + 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000, + 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000, + 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000, + 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000, + 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000, + 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000, + 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000, + 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000, + 0x48686b5600000000}, + {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000, + 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000, + 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000, + 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000, + 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000, + 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000, + 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000, + 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000, + 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000, + 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000, + 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000, + 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000, + 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000, + 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000, + 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000, + 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000, + 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000, + 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000, + 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000, + 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000, + 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000, + 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000, + 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000, + 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000, + 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000, + 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000, + 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000, + 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000, + 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000, + 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000, + 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000, + 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000, + 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000, + 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000, + 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000, + 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000, + 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000, + 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000, + 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000, + 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000, + 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000, + 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000, + 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000, + 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000, + 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000, + 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000, + 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000, + 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000, + 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000, + 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000, + 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000, + 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000, + 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000, + 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000, + 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000, + 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000, + 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000, + 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000, + 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000, + 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000, + 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000, + 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000, + 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000, + 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000, + 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000, + 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000, + 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000, + 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000, + 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000, + 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000, + 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000, + 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000, + 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000, + 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000, + 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000, + 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000, + 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000, + 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000, + 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000, + 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000, + 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000, + 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000, + 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000, + 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000, + 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000, + 0xcaa2517800000000}, + {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000, + 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000, + 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000, + 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000, + 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000, + 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000, + 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000, + 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000, + 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000, + 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000, + 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000, + 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000, + 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000, + 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000, + 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000, + 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000, + 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000, + 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000, + 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000, + 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000, + 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000, + 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000, + 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000, + 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000, + 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000, + 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000, + 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000, + 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000, + 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000, + 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000, + 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000, + 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000, + 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000, + 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000, + 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000, + 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000, + 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000, + 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000, + 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000, + 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000, + 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000, + 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000, + 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000, + 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000, + 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000, + 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000, + 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000, + 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000, + 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000, + 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000, + 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000, + 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000, + 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000, + 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000, + 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000, + 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000, + 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000, + 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000, + 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000, + 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000, + 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000, + 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000, + 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000, + 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000, + 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000, + 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000, + 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000, + 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000, + 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000, + 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000, + 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000, + 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000, + 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000, + 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000, + 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000, + 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000, + 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000, + 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000, + 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000, + 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000, + 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000, + 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000, + 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000, + 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000, + 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000, + 0x0c7ac97b00000000}, + {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000, + 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000, + 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000, + 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000, + 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000, + 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000, + 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000, + 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000, + 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000, + 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000, + 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000, + 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000, + 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000, + 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000, + 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000, + 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000, + 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000, + 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000, + 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000, + 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000, + 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000, + 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000, + 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000, + 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000, + 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000, + 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000, + 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000, + 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000, + 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000, + 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000, + 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000, + 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000, + 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000, + 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000, + 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000, + 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000, + 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000, + 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000, + 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000, + 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000, + 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000, + 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000, + 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000, + 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000, + 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000, + 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000, + 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000, + 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000, + 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000, + 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000, + 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000, + 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000, + 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000, + 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000, + 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000, + 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000, + 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000, + 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000, + 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000, + 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000, + 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000, + 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000, + 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000, + 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000, + 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000, + 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000, + 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000, + 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000, + 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000, + 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000, + 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000, + 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000, + 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000, + 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000, + 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000, + 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000, + 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000, + 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000, + 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000, + 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000, + 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000, + 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000, + 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000, + 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000, + 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000, + 0x5185cd0900000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f, + 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91, + 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e, + 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c, + 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02, + 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12, + 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567, + 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277, + 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679, + 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b, + 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4, + 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a, + 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0, + 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0, + 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91, + 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881, + 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173, + 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d, + 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912, + 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8, + 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6, + 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6, + 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b, + 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b, + 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75, + 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f, + 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00, + 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee, + 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c, + 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c, + 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d, + 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d, + 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67, + 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89, + 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706, + 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14, + 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a, + 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a, + 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f, + 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f, + 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591, + 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983, + 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c, + 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2, + 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8, + 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8, + 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89, + 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99, + 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b, + 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485, + 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a, + 0x36197165}, + {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382, + 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85, + 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06, + 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca, + 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e, + 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc, + 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616, + 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54, + 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10, + 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc, + 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f, + 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58, + 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef, + 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad, + 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b, + 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29, + 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6, + 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1, + 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622, + 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039, + 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d, + 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f, + 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32, + 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770, + 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034, + 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f, + 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc, + 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db, + 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154, + 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16, + 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0, + 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592, + 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca, + 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd, + 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e, + 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882, + 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6, + 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384, + 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1, + 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3, + 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7, + 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b, + 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8, + 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff, + 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7, + 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5, + 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23, + 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761, + 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee, + 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9, + 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a, + 0x1a3b93aa}, + {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a, + 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca, + 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3, + 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb, + 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c, + 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58, + 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed, + 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9, + 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e, + 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906, + 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f, + 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf, + 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0, + 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4, + 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769, + 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d, + 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632, + 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82, + 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb, + 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73, + 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484, + 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0, + 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5, + 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1, + 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516, + 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f, + 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946, + 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6, + 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9, + 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad, + 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820, + 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364, + 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab, + 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b, + 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62, + 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a, + 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd, + 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089, + 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c, + 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8, + 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f, + 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477, + 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e, + 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be, + 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71, + 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635, + 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8, + 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc, + 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3, + 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753, + 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a, + 0xe147d714}, + {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c, + 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b, + 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92, + 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4, + 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069, + 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526, + 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25, + 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a, + 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7, + 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491, + 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958, + 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f, + 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307, + 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648, + 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999, + 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6, + 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a, + 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d, + 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4, + 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61, + 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc, + 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3, + 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53, + 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c, + 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1, + 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c, + 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5, + 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92, + 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e, + 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771, + 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0, + 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def, + 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0, + 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7, + 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e, + 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58, + 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285, + 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca, + 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce, + 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81, + 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c, + 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a, + 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3, + 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4, + 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb, + 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4, + 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75, + 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a, + 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296, + 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1, + 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808, + 0x494f0c4b}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d, + 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac, + 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8, + 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95, + 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817, + 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d, + 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac, + 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6, + 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564, + 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39, + 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d, + 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac, + 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de, + 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594, + 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b, + 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01, + 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f, + 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de, + 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba, + 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65, + 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7, + 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad, + 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de, + 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294, + 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716, + 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71, + 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15, + 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4, + 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca, + 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280, + 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f, + 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15, + 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9, + 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748, + 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c, + 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971, + 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3, + 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9, + 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196, + 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc, + 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e, + 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03, + 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67, + 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296, + 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a, + 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170, + 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af, + 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5, + 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb, + 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a, + 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e, + 0x4b0c4f49}, + {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09, + 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc, + 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e, + 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc, + 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934, + 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2, + 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b, + 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad, + 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155, + 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187, + 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65, + 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390, + 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e, + 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378, + 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889, + 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f, + 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0, + 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145, + 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7, + 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a, + 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2, + 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924, + 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2, + 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514, + 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec, + 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709, + 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb, + 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e, + 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1, + 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227, + 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6, + 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030, + 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0, + 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55, + 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7, + 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165, + 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d, + 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b, + 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c, + 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a, + 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362, + 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0, + 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52, + 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7, + 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237, + 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1, + 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020, + 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6, + 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719, + 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec, + 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e, + 0x14d747e1}, + {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0, + 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b, + 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652, + 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437, + 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514, + 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265, + 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de, + 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af, + 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c, + 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9, + 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0, + 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b, + 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6, + 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7, + 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734, + 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045, + 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8, + 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303, + 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a, + 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9, + 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea, + 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b, + 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6, + 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7, + 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4, + 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6, + 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f, + 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054, + 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9, + 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8, + 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b, + 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a, + 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441, + 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a, + 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3, + 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6, + 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5, + 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94, + 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9, + 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288, + 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab, + 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce, + 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7, + 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c, + 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527, + 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256, + 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5, + 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4, + 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39, + 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2, + 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db, + 0xaa933b1a}, + {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603, + 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d, + 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9, + 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b, + 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a, + 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792, + 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4, + 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c, + 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d, + 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f, + 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb, + 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65, + 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330, + 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8, + 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da, + 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742, + 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f, + 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1, + 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5, + 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f, + 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e, + 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6, + 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8, + 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250, + 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021, + 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb, + 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f, + 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511, + 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c, + 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4, + 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886, + 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e, + 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b, + 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5, + 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791, + 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003, + 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272, + 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea, + 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc, + 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24, + 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55, + 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7, + 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3, + 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d, + 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548, + 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0, + 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2, + 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a, + 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47, + 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9, + 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad, + 0x65711936}}; + +#endif /* W */ + +#endif /* N == 3 */ +#if N == 4 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a, + 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe, + 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b, + 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656, + 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd, + 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d, + 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7, + 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47, + 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac, + 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691, + 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404, + 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0, + 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4, + 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424, + 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5, + 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65, + 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67, + 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3, + 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626, + 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9, + 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222, + 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2, + 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a, + 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a, + 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1, + 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2, + 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077, + 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3, + 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1, + 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621, + 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0, + 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60, + 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0, + 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64, + 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1, + 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc, + 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027, + 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7, + 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9, + 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79, + 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292, + 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af, + 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a, + 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee, + 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e, + 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe, + 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f, + 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff, + 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd, + 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29, + 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc, + 0xe3c45916}, + {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344, + 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59, + 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e, + 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463, + 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98, + 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d, + 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3, + 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656, + 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad, + 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0, + 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397, + 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a, + 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2, + 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357, + 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8, + 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d, + 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696, + 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b, + 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc, + 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0, + 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b, + 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be, + 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811, + 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384, + 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f, + 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955, + 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362, + 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f, + 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94, + 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701, + 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe, + 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b, + 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1, + 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc, + 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b, + 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986, + 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d, + 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8, + 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4, + 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371, + 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a, + 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87, + 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0, + 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad, + 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527, + 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2, + 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d, + 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998, + 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73, + 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e, + 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59, + 0xa7520488}, + {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20, + 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09, + 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431, + 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a, + 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203, + 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b, + 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14, + 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c, + 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25, + 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e, + 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36, + 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f, + 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649, + 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961, + 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58, + 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170, + 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b, + 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742, + 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a, + 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55, + 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c, + 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64, + 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f, + 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77, + 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e, + 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a, + 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2, + 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b, + 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090, + 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8, + 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881, + 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9, + 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6, + 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f, + 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7, + 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c, + 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695, + 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd, + 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb, + 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3, + 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa, + 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1, + 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9, + 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0, + 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df, + 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7, + 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace, + 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6, + 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd, + 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4, + 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec, + 0x3522e9e4}, + {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1, + 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86, + 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b, + 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669, + 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7, + 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352, + 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03, + 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6, + 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38, + 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a, + 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7, + 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80, + 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7, + 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522, + 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d, + 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8, + 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103, + 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54, + 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9, + 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0, + 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e, + 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb, + 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1, + 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624, + 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea, + 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a, + 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37, + 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360, + 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab, + 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e, + 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741, + 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4, + 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334, + 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63, + 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de, + 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c, + 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942, + 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7, + 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131, + 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4, + 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a, + 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758, + 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5, + 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2, + 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32, + 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7, + 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8, + 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d, + 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6, + 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1, + 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c, + 0x97411e28}, + {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474, + 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5, + 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6, + 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7, + 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938, + 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051, + 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a, + 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3, + 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c, + 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d, + 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e, + 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf, + 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740, + 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29, + 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592, + 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb, + 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4, + 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365, + 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036, + 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7, + 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08, + 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561, + 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a, + 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663, + 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac, + 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d, + 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce, + 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f, + 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50, + 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639, + 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82, + 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb, + 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954, + 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5, + 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86, + 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7, + 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418, + 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71, + 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa, + 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93, + 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c, + 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d, + 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e, + 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df, + 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60, + 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309, + 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2, + 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db, + 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4, + 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45, + 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16, + 0x93c7a00b}, + {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45, + 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb, + 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d, + 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696, + 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf, + 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb, + 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028, + 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c, + 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65, + 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be, + 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038, + 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6, + 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15, + 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11, + 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d, + 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19, + 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05, + 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b, + 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d, + 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c, + 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35, + 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31, + 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068, + 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c, + 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25, + 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a, + 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac, + 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22, + 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e, + 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a, + 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36, + 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32, + 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84, + 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a, + 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c, + 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057, + 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e, + 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a, + 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc, + 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8, + 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1, + 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a, + 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec, + 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62, + 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4, + 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0, + 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc, + 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8, + 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4, + 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a, + 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc, + 0xce5f968d}, + {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de, + 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b, + 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d, + 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680, + 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4, + 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d, + 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde, + 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97, + 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3, + 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e, + 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678, + 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d, + 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723, + 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a, + 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0, + 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9, + 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85, + 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770, + 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56, + 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a, + 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e, + 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67, + 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785, + 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc, + 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788, + 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90, + 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6, + 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843, + 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f, + 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336, + 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac, + 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5, + 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68, + 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d, + 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb, + 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36, + 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72, + 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b, + 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b, + 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402, + 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446, + 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb, + 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed, + 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418, + 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95, + 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc, + 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946, + 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f, + 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233, + 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6, + 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0, + 0x3e721277}, + {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb, + 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9, + 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11, + 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d, + 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9, + 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c, + 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881, + 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274, + 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790, + 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc, + 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514, + 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56, + 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9, + 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c, + 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13, + 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6, + 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c, + 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e, + 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386, + 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376, + 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692, + 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67, + 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416, + 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3, + 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07, + 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd, + 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15, + 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457, + 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd, + 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28, + 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337, + 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2, + 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594, + 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6, + 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e, + 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52, + 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6, + 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143, + 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17, + 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2, + 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306, + 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a, + 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182, + 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0, + 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496, + 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63, + 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c, + 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89, + 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903, + 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041, + 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9, + 0x1c65ace7}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000, + 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000, + 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000, + 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000, + 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000, + 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000, + 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000, + 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000, + 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000, + 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000, + 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000, + 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000, + 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000, + 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000, + 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000, + 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000, + 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000, + 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000, + 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000, + 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000, + 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000, + 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000, + 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000, + 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000, + 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000, + 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000, + 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000, + 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000, + 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000, + 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000, + 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000, + 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000, + 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000, + 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000, + 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000, + 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000, + 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000, + 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000, + 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000, + 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000, + 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000, + 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000, + 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000, + 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000, + 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000, + 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000, + 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000, + 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000, + 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000, + 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000, + 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000, + 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000, + 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000, + 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000, + 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000, + 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000, + 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000, + 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000, + 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000, + 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000, + 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000, + 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000, + 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000, + 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000, + 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000, + 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000, + 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000, + 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000, + 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000, + 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000, + 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000, + 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000, + 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000, + 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000, + 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000, + 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000, + 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000, + 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000, + 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000, + 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000, + 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000, + 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000, + 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000, + 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000, + 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000, + 0xe7ac651c00000000}, + {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000, + 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000, + 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000, + 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000, + 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000, + 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000, + 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000, + 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000, + 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000, + 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000, + 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000, + 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000, + 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000, + 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000, + 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000, + 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000, + 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000, + 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000, + 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000, + 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000, + 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000, + 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000, + 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000, + 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000, + 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000, + 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000, + 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000, + 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000, + 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000, + 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000, + 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000, + 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000, + 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000, + 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000, + 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000, + 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000, + 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000, + 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000, + 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000, + 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000, + 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000, + 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000, + 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000, + 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000, + 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000, + 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000, + 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000, + 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000, + 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000, + 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000, + 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000, + 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000, + 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000, + 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000, + 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000, + 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000, + 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000, + 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000, + 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000, + 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000, + 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000, + 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000, + 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000, + 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000, + 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000, + 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000, + 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000, + 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000, + 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000, + 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000, + 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000, + 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000, + 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000, + 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000, + 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000, + 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000, + 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000, + 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000, + 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000, + 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000, + 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000, + 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000, + 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000, + 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000, + 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000, + 0x7712723e00000000}, + {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000, + 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000, + 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000, + 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000, + 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000, + 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000, + 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000, + 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000, + 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000, + 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000, + 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000, + 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000, + 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000, + 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000, + 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000, + 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000, + 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000, + 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000, + 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000, + 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000, + 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000, + 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000, + 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000, + 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000, + 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000, + 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000, + 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000, + 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000, + 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000, + 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000, + 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000, + 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000, + 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000, + 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000, + 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000, + 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000, + 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000, + 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000, + 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000, + 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000, + 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000, + 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000, + 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000, + 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000, + 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000, + 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000, + 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000, + 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000, + 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000, + 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000, + 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000, + 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000, + 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000, + 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000, + 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000, + 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000, + 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000, + 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000, + 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000, + 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000, + 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000, + 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000, + 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000, + 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000, + 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000, + 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000, + 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000, + 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000, + 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000, + 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000, + 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000, + 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000, + 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000, + 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000, + 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000, + 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000, + 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000, + 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000, + 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000, + 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000, + 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000, + 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000, + 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000, + 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000, + 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000, + 0x8d965fce00000000}, + {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000, + 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000, + 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000, + 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000, + 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000, + 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000, + 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000, + 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000, + 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000, + 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000, + 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000, + 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000, + 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000, + 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000, + 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000, + 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000, + 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000, + 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000, + 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000, + 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000, + 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000, + 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000, + 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000, + 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000, + 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000, + 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000, + 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000, + 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000, + 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000, + 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000, + 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000, + 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000, + 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000, + 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000, + 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000, + 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000, + 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000, + 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000, + 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000, + 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000, + 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000, + 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000, + 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000, + 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000, + 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000, + 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000, + 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000, + 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000, + 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000, + 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000, + 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000, + 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000, + 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000, + 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000, + 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000, + 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000, + 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000, + 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000, + 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000, + 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000, + 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000, + 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000, + 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000, + 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000, + 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000, + 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000, + 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000, + 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000, + 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000, + 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000, + 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000, + 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000, + 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000, + 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000, + 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000, + 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000, + 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000, + 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000, + 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000, + 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000, + 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000, + 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000, + 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000, + 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000, + 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000, + 0x0ba0c79300000000}, + {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000, + 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000, + 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000, + 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000, + 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000, + 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000, + 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000, + 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000, + 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000, + 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000, + 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000, + 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000, + 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000, + 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000, + 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000, + 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000, + 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000, + 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000, + 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000, + 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000, + 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000, + 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000, + 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000, + 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000, + 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000, + 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000, + 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000, + 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000, + 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000, + 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000, + 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000, + 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000, + 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000, + 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000, + 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000, + 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000, + 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000, + 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000, + 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000, + 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000, + 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000, + 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000, + 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000, + 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000, + 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000, + 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000, + 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000, + 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000, + 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000, + 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000, + 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000, + 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000, + 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000, + 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000, + 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000, + 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000, + 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000, + 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000, + 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000, + 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000, + 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000, + 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000, + 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000, + 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000, + 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000, + 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000, + 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000, + 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000, + 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000, + 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000, + 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000, + 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000, + 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000, + 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000, + 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000, + 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000, + 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000, + 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000, + 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000, + 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000, + 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000, + 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000, + 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000, + 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000, + 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000, + 0x281e419700000000}, + {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000, + 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000, + 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000, + 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000, + 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000, + 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000, + 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000, + 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000, + 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000, + 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000, + 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000, + 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000, + 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000, + 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000, + 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000, + 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000, + 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000, + 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000, + 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000, + 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000, + 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000, + 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000, + 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000, + 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000, + 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000, + 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000, + 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000, + 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000, + 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000, + 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000, + 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000, + 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000, + 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000, + 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000, + 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000, + 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000, + 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000, + 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000, + 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000, + 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000, + 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000, + 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000, + 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000, + 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000, + 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000, + 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000, + 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000, + 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000, + 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000, + 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000, + 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000, + 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000, + 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000, + 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000, + 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000, + 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000, + 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000, + 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000, + 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000, + 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000, + 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000, + 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000, + 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000, + 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000, + 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000, + 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000, + 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000, + 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000, + 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000, + 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000, + 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000, + 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000, + 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000, + 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000, + 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000, + 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000, + 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000, + 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000, + 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000, + 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000, + 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000, + 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000, + 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000, + 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000, + 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000, + 0xe4e9223500000000}, + {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000, + 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000, + 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000, + 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000, + 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000, + 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000, + 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000, + 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000, + 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000, + 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000, + 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000, + 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000, + 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000, + 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000, + 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000, + 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000, + 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000, + 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000, + 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000, + 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000, + 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000, + 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000, + 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000, + 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000, + 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000, + 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000, + 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000, + 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000, + 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000, + 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000, + 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000, + 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000, + 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000, + 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000, + 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000, + 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000, + 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000, + 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000, + 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000, + 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000, + 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000, + 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000, + 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000, + 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000, + 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000, + 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000, + 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000, + 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000, + 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000, + 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000, + 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000, + 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000, + 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000, + 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000, + 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000, + 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000, + 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000, + 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000, + 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000, + 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000, + 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000, + 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000, + 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000, + 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000, + 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000, + 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000, + 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000, + 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000, + 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000, + 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000, + 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000, + 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000, + 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000, + 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000, + 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000, + 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000, + 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000, + 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000, + 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000, + 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000, + 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000, + 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000, + 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000, + 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000, + 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000, + 0x880452a700000000}, + {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000, + 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000, + 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000, + 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000, + 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000, + 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000, + 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000, + 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000, + 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000, + 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000, + 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000, + 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000, + 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000, + 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000, + 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000, + 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000, + 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000, + 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000, + 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000, + 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000, + 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000, + 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000, + 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000, + 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000, + 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000, + 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000, + 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000, + 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000, + 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000, + 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000, + 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000, + 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000, + 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000, + 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000, + 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000, + 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000, + 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000, + 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000, + 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000, + 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000, + 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000, + 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000, + 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000, + 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000, + 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000, + 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000, + 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000, + 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000, + 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000, + 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000, + 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000, + 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000, + 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000, + 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000, + 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000, + 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000, + 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000, + 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000, + 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000, + 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000, + 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000, + 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000, + 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000, + 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000, + 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000, + 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000, + 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000, + 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000, + 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000, + 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000, + 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000, + 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000, + 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000, + 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000, + 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000, + 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000, + 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000, + 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000, + 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000, + 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000, + 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000, + 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000, + 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000, + 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000, + 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000, + 0x1659c4e300000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87, + 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede, + 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab, + 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c, + 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1, + 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7, + 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e, + 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308, + 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5, + 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472, + 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07, + 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e, + 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa, + 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec, + 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6, + 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0, + 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3, + 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba, + 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf, + 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975, + 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8, + 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde, + 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a, + 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c, + 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1, + 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65, + 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410, + 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649, + 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a, + 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c, + 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946, + 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450, + 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e, + 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857, + 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022, + 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5, + 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758, + 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e, + 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d, + 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b, + 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6, + 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401, + 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74, + 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d, + 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073, + 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65, + 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f, + 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749, + 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a, + 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033, + 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846, + 0x0d7139d7}, + {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563, + 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f, + 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875, + 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536, + 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8, + 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43, + 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f, + 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184, + 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a, + 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39, + 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523, + 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f, + 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d, + 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6, + 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b, + 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0, + 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151, + 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d, + 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47, + 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a, + 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964, + 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef, + 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d, + 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6, + 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348, + 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53, + 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449, + 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645, + 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4, + 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f, + 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2, + 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69, + 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46, + 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a, + 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650, + 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13, + 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded, + 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366, + 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57, + 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc, + 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222, + 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61, + 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b, + 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277, + 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558, + 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3, + 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e, + 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5, + 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74, + 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78, + 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262, + 0x1c53e98a}, + {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b, + 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40, + 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580, + 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7, + 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a, + 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37, + 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75, + 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218, + 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5, + 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2, + 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02, + 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59, + 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1, + 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c, + 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a, + 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307, + 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486, + 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd, + 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d, + 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2, + 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f, + 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72, + 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8, + 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985, + 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268, + 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94, + 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454, + 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f, + 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e, + 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3, + 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915, + 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778, + 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821, + 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a, + 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba, + 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d, + 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560, + 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d, + 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe, + 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3, + 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e, + 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509, + 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9, + 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92, + 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb, + 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6, + 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50, + 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d, + 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc, + 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7, + 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927, + 0x3f88e851}, + {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96, + 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8, + 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0, + 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14, + 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7, + 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4, + 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe, + 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad, + 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e, + 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa, + 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2, + 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c, + 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab, + 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8, + 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d, + 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e, + 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7, + 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99, + 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1, + 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690, + 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933, + 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20, + 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf, + 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc, + 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f, + 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92, + 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca, + 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4, + 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd, + 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de, + 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb, + 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8, + 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474, + 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a, + 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252, + 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6, + 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55, + 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846, + 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7, + 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4, + 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47, + 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3, + 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb, + 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5, + 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49, + 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a, + 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f, + 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c, + 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305, + 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b, + 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523, + 0x3dee8ca6}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0, + 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587, + 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa, + 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09, + 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee, + 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3, + 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3, + 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce, + 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429, + 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda, + 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7, + 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0, + 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd, + 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0, + 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287, + 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a, + 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9, + 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e, + 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3, + 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3, + 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054, + 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49, + 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da, + 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7, + 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20, + 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d, + 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00, + 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347, + 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14, + 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209, + 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e, + 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33, + 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3, + 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194, + 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9, + 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a, + 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd, + 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0, + 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d, + 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460, + 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87, + 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674, + 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509, + 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e, + 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae, + 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3, + 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694, + 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989, + 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da, + 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d, + 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0, + 0xa68cee3d}, + {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19, + 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae, + 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb, + 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a, + 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55, + 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1, + 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c, + 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8, + 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7, + 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936, + 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453, + 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4, + 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941, + 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5, + 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93, + 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17, + 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e, + 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89, + 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec, + 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0, + 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf, + 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b, + 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b, + 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f, + 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0, + 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e, + 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b, + 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc, + 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5, + 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261, + 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637, + 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3, + 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57, + 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0, + 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85, + 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454, + 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b, + 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f, + 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423, + 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7, + 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8, + 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739, + 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c, + 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb, + 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f, + 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b, + 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd, + 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59, + 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070, + 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7, + 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2, + 0x51e8883f}, + {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a, + 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276, + 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed, + 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55, + 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b, + 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8, + 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320, + 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413, + 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd, + 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75, + 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee, + 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312, + 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca, + 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9, + 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad, + 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e, + 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504, + 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8, + 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63, + 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353, + 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d, + 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be, + 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae, + 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d, + 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943, + 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7, + 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c, + 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390, + 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a, + 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239, + 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d, + 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e, + 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c, + 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0, + 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b, + 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93, + 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d, + 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e, + 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c, + 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f, + 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1, + 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579, + 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2, + 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e, + 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c, + 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f, + 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b, + 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158, + 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2, + 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e, + 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5, + 0x8ae9531c}, + {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4, + 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd, + 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220, + 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf, + 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495, + 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def, + 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90, + 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea, + 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0, + 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f, + 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2, + 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab, + 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e, + 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754, + 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda, + 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0, + 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c, + 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215, + 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8, + 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910, + 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a, + 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30, + 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658, + 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22, + 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478, + 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2, + 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f, + 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606, + 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba, + 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0, + 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e, + 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034, + 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f, + 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996, + 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b, + 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84, + 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de, + 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4, + 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5, + 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f, + 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5, + 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a, + 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7, + 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce, + 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65, + 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f, + 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91, + 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb, + 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57, + 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e, + 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3, + 0xd739710d}}; + +#endif /* W */ + +#endif /* N == 4 */ +#if N == 5 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df, + 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8, + 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef, + 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376, + 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201, + 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399, + 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372, + 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea, + 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d, + 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004, + 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353, + 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334, + 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a, + 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2, + 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a, + 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2, + 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b, + 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c, + 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b, + 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f, + 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338, + 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0, + 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6, + 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e, + 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319, + 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3, + 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4, + 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783, + 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a, + 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492, + 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a, + 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2, + 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496, + 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1, + 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6, + 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f, + 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548, + 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0, + 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741, + 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9, + 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae, + 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437, + 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760, + 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707, + 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433, + 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab, + 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703, + 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b, + 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412, + 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475, + 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722, + 0xe9947565}, + {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5, + 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22, + 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c, + 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed, + 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d, + 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1, + 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e, + 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32, + 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142, + 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93, + 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d, + 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a, + 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58, + 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14, + 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81, + 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd, + 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab, + 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c, + 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72, + 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f, + 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff, + 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3, + 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30, + 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c, + 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c, + 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558, + 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146, + 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581, + 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7, + 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab, + 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e, + 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272, + 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838, + 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff, + 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1, + 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330, + 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840, + 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c, + 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb, + 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7, + 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7, + 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616, + 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208, + 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf, + 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85, + 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9, + 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c, + 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10, + 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76, + 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1, + 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf, + 0xf7d05006}, + {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b, + 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774, + 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58, + 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a, + 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb, + 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952, + 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e, + 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7, + 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746, + 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14, + 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338, + 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907, + 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777, + 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de, + 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064, + 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd, + 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951, + 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e, + 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42, + 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b, + 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a, + 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3, + 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904, + 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad, + 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c, + 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d, + 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861, + 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e, + 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2, + 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b, + 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1, + 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78, + 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f, + 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40, + 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c, + 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e, + 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf, + 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166, + 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d, + 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4, + 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805, + 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157, + 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b, + 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644, + 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43, + 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea, + 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850, + 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9, + 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165, + 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a, + 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676, + 0xb2075b94}, + {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf, + 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61, + 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be, + 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd, + 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3, + 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063, + 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105, + 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5, + 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb, + 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8, + 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07, + 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9, + 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5, + 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515, + 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4, + 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014, + 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7, + 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269, + 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6, + 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af, + 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1, + 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111, + 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d, + 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad, + 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3, + 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75, + 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa, + 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74, + 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7, + 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477, + 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6, + 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176, + 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af, + 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71, + 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae, + 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd, + 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3, + 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073, + 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0, + 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400, + 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e, + 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d, + 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2, + 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c, + 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5, + 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505, + 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4, + 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004, + 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7, + 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279, + 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6, + 0xba50bcb9}, + {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897, + 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb, + 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2, + 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2, + 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372, + 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70, + 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92, + 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190, + 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40, + 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430, + 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759, + 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75, + 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2, + 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0, + 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7, + 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5, + 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39, + 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215, + 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c, + 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5, + 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625, + 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27, + 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c, + 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e, + 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee, + 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71, + 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18, + 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134, + 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8, + 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba, + 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd, + 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff, + 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a, + 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6, + 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf, + 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf, + 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f, + 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d, + 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d, + 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f, + 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af, + 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df, + 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6, + 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a, + 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef, + 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed, + 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa, + 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8, + 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624, + 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08, + 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861, + 0x808abcf4}, + {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2, + 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd, + 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76, + 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52, + 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e, + 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124, + 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147, + 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d, + 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31, + 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15, + 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae, + 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1, + 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d, + 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307, + 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9, + 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3, + 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084, + 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb, + 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850, + 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2, + 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe, + 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94, + 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261, + 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b, + 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917, + 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53, + 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8, + 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787, + 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0, + 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba, + 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404, + 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e, + 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af, + 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0, + 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b, + 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f, + 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543, + 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129, + 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627, + 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d, + 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51, + 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75, + 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce, + 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1, + 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760, + 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a, + 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4, + 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde, + 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089, + 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6, + 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d, + 0xefdb3f95}, + {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8, + 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7, + 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945, + 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9, + 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652, + 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc, + 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a, + 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4, + 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f, + 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3, + 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51, + 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e, + 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c, + 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362, + 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11, + 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff, + 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7, + 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8, + 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a, + 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690, + 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b, + 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5, + 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05, + 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb, + 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740, + 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f, + 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded, + 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2, + 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa, + 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714, + 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67, + 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89, + 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7, + 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8, + 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a, + 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6, + 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d, + 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3, + 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9, + 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57, + 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc, + 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540, + 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2, + 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd, + 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93, + 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d, + 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e, + 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0, + 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8, + 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7, + 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75, + 0x0e2fbf43}, + {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc, + 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a, + 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3, + 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7, + 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b, + 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154, + 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3, + 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc, + 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330, + 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264, + 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd, + 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b, + 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a, + 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175, + 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275, + 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a, + 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234, + 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2, + 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b, + 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a, + 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6, + 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189, + 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b, + 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204, + 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8, + 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226, + 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff, + 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219, + 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167, + 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258, + 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158, + 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267, + 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c, + 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da, + 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003, + 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157, + 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b, + 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4, + 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179, + 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246, + 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a, + 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de, + 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107, + 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1, + 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba, + 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285, + 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185, + 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba, + 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4, + 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322, + 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb, + 0xf4377108}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000, + 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000, + 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000, + 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000, + 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000, + 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000, + 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000, + 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000, + 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000, + 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000, + 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000, + 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000, + 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000, + 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000, + 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000, + 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000, + 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000, + 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000, + 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000, + 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000, + 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000, + 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000, + 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000, + 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000, + 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000, + 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000, + 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000, + 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000, + 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000, + 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000, + 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000, + 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000, + 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000, + 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000, + 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000, + 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000, + 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000, + 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000, + 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000, + 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000, + 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000, + 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000, + 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000, + 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000, + 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000, + 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000, + 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000, + 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000, + 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000, + 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000, + 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000, + 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000, + 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000, + 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000, + 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000, + 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000, + 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000, + 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000, + 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000, + 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000, + 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000, + 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000, + 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000, + 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000, + 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000, + 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000, + 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000, + 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000, + 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000, + 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000, + 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000, + 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000, + 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000, + 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000, + 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000, + 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000, + 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000, + 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000, + 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000, + 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000, + 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000, + 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000, + 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000, + 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000, + 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000, + 0x087137f400000000}, + {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000, + 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000, + 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000, + 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000, + 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000, + 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000, + 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000, + 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000, + 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000, + 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000, + 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000, + 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000, + 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000, + 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000, + 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000, + 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000, + 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000, + 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000, + 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000, + 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000, + 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000, + 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000, + 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000, + 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000, + 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000, + 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000, + 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000, + 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000, + 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000, + 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000, + 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000, + 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000, + 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000, + 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000, + 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000, + 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000, + 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000, + 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000, + 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000, + 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000, + 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000, + 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000, + 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000, + 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000, + 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000, + 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000, + 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000, + 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000, + 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000, + 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000, + 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000, + 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000, + 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000, + 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000, + 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000, + 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000, + 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000, + 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000, + 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000, + 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000, + 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000, + 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000, + 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000, + 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000, + 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000, + 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000, + 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000, + 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000, + 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000, + 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000, + 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000, + 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000, + 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000, + 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000, + 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000, + 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000, + 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000, + 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000, + 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000, + 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000, + 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000, + 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000, + 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000, + 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000, + 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000, + 0x43bf2f0e00000000}, + {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000, + 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000, + 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000, + 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000, + 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000, + 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000, + 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000, + 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000, + 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000, + 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000, + 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000, + 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000, + 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000, + 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000, + 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000, + 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000, + 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000, + 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000, + 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000, + 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000, + 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000, + 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000, + 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000, + 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000, + 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000, + 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000, + 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000, + 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000, + 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000, + 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000, + 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000, + 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000, + 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000, + 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000, + 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000, + 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000, + 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000, + 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000, + 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000, + 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000, + 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000, + 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000, + 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000, + 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000, + 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000, + 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000, + 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000, + 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000, + 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000, + 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000, + 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000, + 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000, + 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000, + 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000, + 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000, + 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000, + 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000, + 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000, + 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000, + 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000, + 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000, + 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000, + 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000, + 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000, + 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000, + 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000, + 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000, + 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000, + 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000, + 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000, + 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000, + 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000, + 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000, + 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000, + 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000, + 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000, + 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000, + 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000, + 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000, + 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000, + 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000, + 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000, + 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000, + 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000, + 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000, + 0x953fdbef00000000}, + {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000, + 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000, + 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000, + 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000, + 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000, + 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000, + 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000, + 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000, + 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000, + 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000, + 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000, + 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000, + 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000, + 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000, + 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000, + 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000, + 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000, + 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000, + 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000, + 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000, + 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000, + 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000, + 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000, + 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000, + 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000, + 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000, + 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000, + 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000, + 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000, + 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000, + 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000, + 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000, + 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000, + 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000, + 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000, + 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000, + 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000, + 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000, + 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000, + 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000, + 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000, + 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000, + 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000, + 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000, + 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000, + 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000, + 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000, + 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000, + 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000, + 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000, + 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000, + 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000, + 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000, + 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000, + 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000, + 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000, + 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000, + 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000, + 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000, + 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000, + 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000, + 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000, + 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000, + 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000, + 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000, + 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000, + 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000, + 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000, + 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000, + 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000, + 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000, + 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000, + 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000, + 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000, + 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000, + 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000, + 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000, + 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000, + 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000, + 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000, + 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000, + 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000, + 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000, + 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000, + 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000, + 0xf4bc8a8000000000}, + {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000, + 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000, + 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000, + 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000, + 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000, + 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000, + 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000, + 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000, + 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000, + 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000, + 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000, + 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000, + 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000, + 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000, + 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000, + 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000, + 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000, + 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000, + 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000, + 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000, + 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000, + 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000, + 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000, + 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000, + 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000, + 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000, + 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000, + 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000, + 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000, + 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000, + 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000, + 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000, + 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000, + 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000, + 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000, + 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000, + 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000, + 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000, + 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000, + 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000, + 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000, + 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000, + 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000, + 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000, + 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000, + 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000, + 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000, + 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000, + 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000, + 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000, + 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000, + 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000, + 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000, + 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000, + 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000, + 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000, + 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000, + 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000, + 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000, + 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000, + 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000, + 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000, + 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000, + 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000, + 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000, + 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000, + 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000, + 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000, + 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000, + 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000, + 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000, + 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000, + 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000, + 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000, + 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000, + 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000, + 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000, + 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000, + 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000, + 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000, + 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000, + 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000, + 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000, + 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000, + 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000, + 0xb9bc50ba00000000}, + {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000, + 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000, + 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000, + 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000, + 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000, + 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000, + 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000, + 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000, + 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000, + 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000, + 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000, + 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000, + 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000, + 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000, + 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000, + 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000, + 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000, + 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000, + 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000, + 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000, + 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000, + 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000, + 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000, + 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000, + 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000, + 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000, + 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000, + 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000, + 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000, + 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000, + 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000, + 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000, + 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000, + 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000, + 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000, + 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000, + 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000, + 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000, + 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000, + 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000, + 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000, + 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000, + 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000, + 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000, + 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000, + 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000, + 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000, + 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000, + 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000, + 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000, + 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000, + 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000, + 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000, + 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000, + 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000, + 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000, + 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000, + 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000, + 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000, + 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000, + 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000, + 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000, + 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000, + 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000, + 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000, + 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000, + 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000, + 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000, + 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000, + 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000, + 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000, + 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000, + 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000, + 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000, + 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000, + 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000, + 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000, + 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000, + 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000, + 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000, + 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000, + 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000, + 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000, + 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000, + 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000, + 0x945b07b200000000}, + {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000, + 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000, + 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000, + 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000, + 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000, + 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000, + 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000, + 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000, + 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000, + 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000, + 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000, + 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000, + 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000, + 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000, + 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000, + 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000, + 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000, + 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000, + 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000, + 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000, + 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000, + 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000, + 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000, + 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000, + 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000, + 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000, + 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000, + 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000, + 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000, + 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000, + 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000, + 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000, + 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000, + 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000, + 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000, + 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000, + 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000, + 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000, + 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000, + 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000, + 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000, + 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000, + 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000, + 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000, + 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000, + 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000, + 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000, + 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000, + 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000, + 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000, + 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000, + 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000, + 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000, + 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000, + 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000, + 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000, + 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000, + 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000, + 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000, + 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000, + 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000, + 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000, + 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000, + 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000, + 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000, + 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000, + 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000, + 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000, + 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000, + 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000, + 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000, + 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000, + 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000, + 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000, + 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000, + 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000, + 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000, + 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000, + 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000, + 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000, + 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000, + 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000, + 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000, + 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000, + 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000, + 0x0650d0f700000000}, + {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000, + 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000, + 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000, + 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000, + 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000, + 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000, + 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000, + 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000, + 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000, + 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000, + 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000, + 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000, + 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000, + 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000, + 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000, + 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000, + 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000, + 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000, + 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000, + 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000, + 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000, + 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000, + 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000, + 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000, + 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000, + 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000, + 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000, + 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000, + 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000, + 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000, + 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000, + 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000, + 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000, + 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000, + 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000, + 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000, + 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000, + 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000, + 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000, + 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000, + 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000, + 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000, + 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000, + 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000, + 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000, + 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000, + 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000, + 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000, + 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000, + 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000, + 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000, + 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000, + 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000, + 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000, + 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000, + 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000, + 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000, + 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000, + 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000, + 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000, + 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000, + 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000, + 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000, + 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000, + 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000, + 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000, + 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000, + 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000, + 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000, + 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000, + 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000, + 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000, + 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000, + 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000, + 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000, + 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000, + 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000, + 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000, + 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000, + 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000, + 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000, + 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000, + 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000, + 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000, + 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000, + 0x657594e900000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59, + 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4, + 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67, + 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef, + 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97, + 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88, + 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687, + 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698, + 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0, + 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068, + 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb, + 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056, + 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016, + 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009, + 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028, + 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037, + 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a, + 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7, + 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054, + 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7, + 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af, + 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0, + 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4, + 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab, + 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3, + 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a, + 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9, + 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54, + 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09, + 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16, + 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37, + 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28, + 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e, + 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3, + 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40, + 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8, + 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0, + 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf, + 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6, + 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9, + 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1, + 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059, + 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca, + 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067, + 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031, + 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e, + 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f, + 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010, + 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d, + 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0, + 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073, + 0xd8ac6b35}, + {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2, + 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd, + 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696, + 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3, + 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f, + 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35, + 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5, + 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f, + 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673, + 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46, + 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d, + 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632, + 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28, + 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192, + 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c, + 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6, + 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0, + 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff, + 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4, + 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95, + 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9, + 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03, + 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7, + 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d, + 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151, + 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808, + 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343, + 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c, + 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a, + 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0, + 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e, + 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594, + 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6, + 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399, + 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2, + 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7, + 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb, + 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571, + 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289, + 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33, + 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f, + 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a, + 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461, + 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e, + 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c, + 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6, + 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918, + 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2, + 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484, + 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb, + 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0, + 0xa140efa8}, + {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706, + 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed, + 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289, + 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a, + 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214, + 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3, + 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3, + 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254, + 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a, + 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9, + 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad, + 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746, + 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060, + 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187, + 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef, + 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408, + 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e, + 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495, + 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1, + 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532, + 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c, + 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb, + 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb, + 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c, + 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42, + 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060, + 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04, + 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef, + 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99, + 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e, + 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16, + 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1, + 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7, + 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c, + 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38, + 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb, + 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5, + 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42, + 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62, + 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85, + 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb, + 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18, + 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c, + 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997, + 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1, + 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36, + 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e, + 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9, + 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf, + 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24, + 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040, + 0x917cd6a1}, + {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf, + 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd, + 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896, + 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9, + 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3, + 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f, + 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d, + 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1, + 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab, + 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4, + 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f, + 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d, + 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4, + 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978, + 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad, + 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621, + 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46, + 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854, + 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f, + 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a, + 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890, + 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c, + 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4, + 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238, + 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622, + 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab, + 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0, + 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2, + 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295, + 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19, + 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc, + 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140, + 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd, + 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf, + 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184, + 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb, + 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1, + 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d, + 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb, + 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257, + 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d, + 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22, + 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069, + 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b, + 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6, + 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a, + 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf, + 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33, + 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254, + 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146, + 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d, + 0x18ba364e}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873, + 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661, + 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441, + 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44, + 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1, + 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05, + 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa, + 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e, + 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb, + 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be, + 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e, + 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c, + 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d, + 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9, + 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f, + 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b, + 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39, + 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b, + 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b, + 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20, + 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595, + 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61, + 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0, + 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644, + 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1, + 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d, + 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d, + 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f, + 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad, + 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359, + 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f, + 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b, + 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7, + 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5, + 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5, + 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0, + 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65, + 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091, + 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633, + 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7, + 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272, + 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77, + 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57, + 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145, + 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9, + 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d, + 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb, + 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f, + 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad, + 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf, + 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f, + 0x4e36ba18}, + {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b, + 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8, + 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19, + 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4, + 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239, + 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd, + 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258, + 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc, + 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41, + 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c, + 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d, + 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e, + 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba, + 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e, + 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8, + 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c, + 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f, + 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c, + 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d, + 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d, + 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0, + 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014, + 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc, + 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628, + 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5, + 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941, + 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0, + 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53, + 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880, + 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264, + 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92, + 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776, + 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8, + 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b, + 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea, + 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837, + 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca, + 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e, + 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211, + 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5, + 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08, + 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5, + 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934, + 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7, + 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049, + 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad, + 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b, + 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf, + 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c, + 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f, + 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e, + 0xa1d67c91}, + {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9, + 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de, + 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94, + 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0, + 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a, + 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924, + 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052, + 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c, + 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6, + 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2, + 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8, + 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f, + 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d, + 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273, + 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30, + 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e, + 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7, + 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980, + 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca, + 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8, + 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62, + 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c, + 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c, + 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032, + 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798, + 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d, + 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07, + 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630, + 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389, + 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7, + 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4, + 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca, + 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55, + 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662, + 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828, + 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c, + 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6, + 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98, + 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3, + 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d, + 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037, + 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913, + 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759, + 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e, + 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1, + 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf, + 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c, + 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2, + 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b, + 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c, + 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276, + 0xa8ef40a1}, + {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e, + 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8, + 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819, + 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f, + 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d, + 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756, + 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0, + 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb, + 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9, + 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f, + 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e, + 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8, + 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835, + 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e, + 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62, + 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749, + 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b, + 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d, + 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc, + 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80, + 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2, + 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599, + 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05, + 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e, + 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c, + 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e, + 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef, + 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359, + 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b, + 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0, + 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc, + 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7, + 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f, + 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189, + 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568, + 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e, + 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c, + 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27, + 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794, + 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf, + 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d, + 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db, + 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a, + 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c, + 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544, + 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f, + 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013, + 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38, + 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea, + 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c, + 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd, + 0x356bacd8}}; + +#endif /* W */ + +#endif /* N == 5 */ +#if N == 6 + +#if W == 8 + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370, + 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d, + 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69, + 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426, + 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3, + 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f, + 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c, + 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490, + 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155, + 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a, + 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e, + 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603, + 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349, + 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5, + 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50, + 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc, + 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b, + 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76, + 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862, + 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9, + 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c, + 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0, + 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937, + 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b, + 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e, + 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e, + 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a, + 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357, + 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0, + 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c, + 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9, + 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165, + 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766, + 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b, + 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f, + 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030, + 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5, + 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59, + 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63, + 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf, + 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a, + 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845, + 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51, + 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c, + 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f, + 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3, + 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46, + 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea, + 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d, + 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60, + 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74, + 0x8568a0a8}, + {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5, + 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf, + 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5, + 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba, + 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf, + 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f, + 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0, + 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450, + 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55, + 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a, + 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620, + 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a, + 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454, + 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4, + 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534, + 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584, + 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694, + 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e, + 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4, + 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1, + 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4, + 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164, + 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1, + 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911, + 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314, + 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c, + 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6, + 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec, + 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc, + 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c, + 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c, + 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c, + 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716, + 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c, + 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676, + 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879, + 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c, + 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc, + 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77, + 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7, + 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2, + 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd, + 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7, + 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad, + 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897, + 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827, + 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7, + 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947, + 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57, + 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d, + 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37, + 0x0d907052}, + {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d, + 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89, + 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31, + 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81, + 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e, + 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0, + 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f, + 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291, + 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e, + 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e, + 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936, + 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2, + 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13, + 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d, + 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f, + 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1, + 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a, + 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae, + 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516, + 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f, + 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20, + 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe, + 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28, + 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6, + 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419, + 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5, + 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d, + 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889, + 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412, + 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c, + 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e, + 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0, + 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02, + 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986, + 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e, + 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e, + 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221, + 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf, + 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913, + 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d, + 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622, + 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592, + 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a, + 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae, + 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c, + 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82, + 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20, + 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe, + 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025, + 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1, + 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719, + 0xfd1a6c8a}, + {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3, + 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb, + 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d, + 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb, + 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9, + 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156, + 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045, + 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa, + 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8, + 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e, + 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8, + 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0, + 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38, + 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87, + 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46, + 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9, + 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585, + 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d, + 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb, + 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531, + 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03, + 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc, + 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33, + 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c, + 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be, + 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d, + 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b, + 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303, + 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f, + 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0, + 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801, + 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe, + 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e, + 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346, + 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620, + 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776, + 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844, + 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb, + 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0, + 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f, + 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d, + 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b, + 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d, + 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75, + 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795, + 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a, + 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb, + 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354, + 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28, + 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30, + 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856, + 0x7895f01a}, + {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188, + 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33, + 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d, + 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445, + 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2, + 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058, + 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43, + 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9, + 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e, + 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06, + 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228, + 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93, + 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e, + 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4, + 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b, + 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371, + 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265, + 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede, + 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0, + 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f, + 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8, + 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32, + 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae, + 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544, + 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3, + 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f, + 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911, + 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa, + 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be, + 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54, + 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b, + 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1, + 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652, + 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9, + 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7, + 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f, + 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68, + 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782, + 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797, + 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d, + 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a, + 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2, + 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc, + 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647, + 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4, + 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e, + 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41, + 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab, + 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf, + 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904, + 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a, + 0x9239b848}, + {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad, + 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0, + 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40, + 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b, + 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d, + 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b, + 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb, + 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d, + 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b, + 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0, + 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840, + 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d, + 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b, + 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d, + 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6, + 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0, + 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580, + 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd, + 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d, + 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b, + 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d, + 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b, + 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6, + 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0, + 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6, + 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c, + 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c, + 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461, + 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841, + 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317, + 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac, + 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa, + 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7, + 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba, + 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a, + 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161, + 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777, + 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21, + 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a, + 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc, + 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da, + 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1, + 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01, + 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c, + 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241, + 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917, + 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac, + 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa, + 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da, + 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397, + 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537, + 0xeb36d3cc}, + {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b, + 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059, + 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251, + 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d, + 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9, + 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c, + 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41, + 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4, + 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10, + 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c, + 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54, + 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476, + 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8, + 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d, + 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92, + 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307, + 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad, + 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f, + 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87, + 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17, + 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3, + 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46, + 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197, + 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02, + 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6, + 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e, + 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96, + 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4, + 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e, + 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b, + 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934, + 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1, + 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7, + 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5, + 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd, + 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1, + 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475, + 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0, + 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155, + 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0, + 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304, + 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348, + 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140, + 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862, + 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14, + 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181, + 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e, + 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab, + 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01, + 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523, + 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b, + 0x38e5f3c5}, + {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06, + 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad, + 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509, + 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba, + 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414, + 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3, + 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733, + 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994, + 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a, + 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889, + 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d, + 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386, + 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621, + 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886, + 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e, + 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389, + 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f, + 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294, + 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30, + 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3, + 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d, + 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba, + 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a, + 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad, + 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03, + 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2, + 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306, + 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad, + 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b, + 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc, + 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914, + 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3, + 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435, + 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e, + 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a, + 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589, + 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27, + 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080, + 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21, + 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586, + 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28, + 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b, + 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f, + 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94, + 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12, + 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5, + 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d, + 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba, + 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c, + 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7, + 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103, + 0x3d3101a2}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000, + 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000, + 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000, + 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000, + 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000, + 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000, + 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000, + 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000, + 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000, + 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000, + 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000, + 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000, + 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000, + 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000, + 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000, + 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000, + 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000, + 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000, + 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000, + 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000, + 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000, + 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000, + 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000, + 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000, + 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000, + 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000, + 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000, + 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000, + 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000, + 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000, + 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000, + 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000, + 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000, + 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000, + 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000, + 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000, + 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000, + 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000, + 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000, + 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000, + 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000, + 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000, + 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000, + 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000, + 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000, + 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000, + 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000, + 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000, + 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000, + 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000, + 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000, + 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000, + 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000, + 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000, + 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000, + 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000, + 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000, + 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000, + 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000, + 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000, + 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000, + 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000, + 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000, + 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000, + 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000, + 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000, + 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000, + 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000, + 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000, + 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000, + 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000, + 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000, + 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000, + 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000, + 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000, + 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000, + 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000, + 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000, + 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000, + 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000, + 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000, + 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000, + 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000, + 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000, + 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000, + 0xa201313d00000000}, + {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000, + 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000, + 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000, + 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000, + 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000, + 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000, + 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000, + 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000, + 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000, + 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000, + 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000, + 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000, + 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000, + 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000, + 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000, + 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000, + 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000, + 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000, + 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000, + 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000, + 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000, + 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000, + 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000, + 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000, + 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000, + 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000, + 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000, + 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000, + 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000, + 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000, + 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000, + 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000, + 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000, + 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000, + 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000, + 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000, + 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000, + 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000, + 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000, + 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000, + 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000, + 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000, + 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000, + 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000, + 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000, + 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000, + 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000, + 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000, + 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000, + 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000, + 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000, + 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000, + 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000, + 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000, + 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000, + 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000, + 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000, + 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000, + 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000, + 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000, + 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000, + 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000, + 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000, + 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000, + 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000, + 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000, + 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000, + 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000, + 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000, + 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000, + 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000, + 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000, + 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000, + 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000, + 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000, + 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000, + 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000, + 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000, + 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000, + 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000, + 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000, + 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000, + 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000, + 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000, + 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000, + 0xc5f3e53800000000}, + {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000, + 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000, + 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000, + 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000, + 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000, + 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000, + 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000, + 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000, + 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000, + 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000, + 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000, + 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000, + 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000, + 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000, + 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000, + 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000, + 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000, + 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000, + 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000, + 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000, + 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000, + 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000, + 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000, + 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000, + 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000, + 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000, + 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000, + 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000, + 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000, + 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000, + 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000, + 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000, + 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000, + 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000, + 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000, + 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000, + 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000, + 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000, + 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000, + 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000, + 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000, + 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000, + 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000, + 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000, + 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000, + 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000, + 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000, + 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000, + 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000, + 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000, + 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000, + 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000, + 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000, + 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000, + 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000, + 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000, + 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000, + 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000, + 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000, + 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000, + 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000, + 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000, + 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000, + 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000, + 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000, + 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000, + 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000, + 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000, + 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000, + 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000, + 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000, + 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000, + 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000, + 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000, + 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000, + 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000, + 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000, + 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000, + 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000, + 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000, + 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000, + 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000, + 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000, + 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000, + 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000, + 0xccd336eb00000000}, + {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000, + 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000, + 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000, + 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000, + 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000, + 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000, + 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000, + 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000, + 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000, + 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000, + 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000, + 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000, + 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000, + 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000, + 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000, + 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000, + 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000, + 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000, + 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000, + 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000, + 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000, + 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000, + 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000, + 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000, + 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000, + 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000, + 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000, + 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000, + 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000, + 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000, + 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000, + 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000, + 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000, + 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000, + 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000, + 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000, + 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000, + 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000, + 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000, + 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000, + 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000, + 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000, + 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000, + 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000, + 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000, + 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000, + 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000, + 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000, + 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000, + 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000, + 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000, + 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000, + 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000, + 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000, + 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000, + 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000, + 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000, + 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000, + 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000, + 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000, + 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000, + 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000, + 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000, + 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000, + 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000, + 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000, + 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000, + 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000, + 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000, + 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000, + 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000, + 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000, + 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000, + 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000, + 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000, + 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000, + 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000, + 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000, + 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000, + 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000, + 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000, + 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000, + 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000, + 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000, + 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000, + 0x48b8399200000000}, + {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000, + 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000, + 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000, + 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000, + 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000, + 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000, + 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000, + 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000, + 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000, + 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000, + 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000, + 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000, + 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000, + 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000, + 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000, + 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000, + 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000, + 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000, + 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000, + 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000, + 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000, + 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000, + 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000, + 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000, + 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000, + 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000, + 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000, + 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000, + 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000, + 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000, + 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000, + 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000, + 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000, + 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000, + 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000, + 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000, + 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000, + 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000, + 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000, + 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000, + 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000, + 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000, + 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000, + 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000, + 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000, + 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000, + 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000, + 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000, + 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000, + 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000, + 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000, + 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000, + 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000, + 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000, + 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000, + 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000, + 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000, + 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000, + 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000, + 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000, + 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000, + 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000, + 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000, + 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000, + 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000, + 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000, + 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000, + 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000, + 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000, + 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000, + 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000, + 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000, + 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000, + 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000, + 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000, + 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000, + 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000, + 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000, + 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000, + 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000, + 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000, + 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000, + 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000, + 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000, + 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000, + 0x1af0957800000000}, + {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000, + 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000, + 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000, + 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000, + 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000, + 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000, + 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000, + 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000, + 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000, + 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000, + 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000, + 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000, + 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000, + 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000, + 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000, + 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000, + 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000, + 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000, + 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000, + 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000, + 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000, + 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000, + 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000, + 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000, + 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000, + 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000, + 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000, + 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000, + 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000, + 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000, + 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000, + 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000, + 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000, + 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000, + 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000, + 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000, + 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000, + 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000, + 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000, + 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000, + 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000, + 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000, + 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000, + 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000, + 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000, + 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000, + 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000, + 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000, + 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000, + 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000, + 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000, + 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000, + 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000, + 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000, + 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000, + 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000, + 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000, + 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000, + 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000, + 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000, + 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000, + 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000, + 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000, + 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000, + 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000, + 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000, + 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000, + 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000, + 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000, + 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000, + 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000, + 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000, + 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000, + 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000, + 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000, + 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000, + 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000, + 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000, + 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000, + 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000, + 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000, + 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000, + 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000, + 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000, + 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000, + 0x8a6c1afd00000000}, + {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000, + 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000, + 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000, + 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000, + 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000, + 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000, + 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000, + 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000, + 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000, + 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000, + 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000, + 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000, + 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000, + 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000, + 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000, + 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000, + 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000, + 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000, + 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000, + 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000, + 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000, + 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000, + 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000, + 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000, + 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000, + 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000, + 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000, + 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000, + 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000, + 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000, + 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000, + 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000, + 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000, + 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000, + 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000, + 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000, + 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000, + 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000, + 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000, + 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000, + 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000, + 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000, + 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000, + 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000, + 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000, + 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000, + 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000, + 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000, + 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000, + 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000, + 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000, + 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000, + 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000, + 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000, + 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000, + 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000, + 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000, + 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000, + 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000, + 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000, + 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000, + 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000, + 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000, + 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000, + 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000, + 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000, + 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000, + 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000, + 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000, + 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000, + 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000, + 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000, + 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000, + 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000, + 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000, + 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000, + 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000, + 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000, + 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000, + 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000, + 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000, + 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000, + 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000, + 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000, + 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000, + 0x5270900d00000000}, + {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000, + 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000, + 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000, + 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000, + 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000, + 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000, + 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000, + 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000, + 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000, + 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000, + 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000, + 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000, + 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000, + 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000, + 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000, + 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000, + 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000, + 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000, + 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000, + 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000, + 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000, + 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000, + 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000, + 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000, + 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000, + 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000, + 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000, + 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000, + 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000, + 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000, + 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000, + 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000, + 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000, + 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000, + 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000, + 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000, + 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000, + 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000, + 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000, + 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000, + 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000, + 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000, + 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000, + 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000, + 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000, + 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000, + 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000, + 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000, + 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000, + 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000, + 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000, + 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000, + 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000, + 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000, + 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000, + 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000, + 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000, + 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000, + 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000, + 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000, + 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000, + 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000, + 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000, + 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000, + 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000, + 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000, + 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000, + 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000, + 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000, + 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000, + 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000, + 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000, + 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000, + 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000, + 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000, + 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000, + 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000, + 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000, + 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000, + 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000, + 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000, + 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000, + 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000, + 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000, + 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000, + 0xa8a0688500000000}}; + +#else /* W == 4 */ + +static const uint32_t crc_braid_table[][256] = { + {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f, + 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999, + 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee, + 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615, + 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383, + 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb, + 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275, + 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d, + 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b, + 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460, + 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317, + 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1, + 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5, + 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd, + 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04, + 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c, + 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7, + 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11, + 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66, + 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7, + 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871, + 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309, + 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd, + 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85, + 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913, + 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d, + 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a, + 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc, + 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57, + 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f, + 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6, + 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e, + 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f, + 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289, + 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe, + 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05, + 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893, + 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb, + 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0, + 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8, + 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e, + 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5, + 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2, + 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574, + 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5, + 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add, + 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114, + 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c, + 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7, + 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701, + 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076, + 0x09cd8551}, + {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193, + 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2, + 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c, + 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71, + 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a, + 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d, + 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71, + 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436, + 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d, + 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000, + 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae, + 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf, + 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930, + 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277, + 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff, + 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8, + 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef, + 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e, + 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20, + 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95, + 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e, + 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9, + 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d, + 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a, + 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151, + 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4, + 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a, + 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b, + 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c, + 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b, + 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3, + 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4, + 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b, + 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a, + 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4, + 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189, + 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92, + 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5, + 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9, + 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe, + 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5, + 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8, + 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66, + 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707, + 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8, + 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f, + 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707, + 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40, + 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017, + 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876, + 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8, + 0x7bc97a0c}, + {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300, + 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0, + 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80, + 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701, + 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41, + 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81, + 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43, + 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83, + 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3, + 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42, + 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202, + 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2, + 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7, + 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407, + 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47, + 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87, + 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86, + 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46, + 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506, + 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44, + 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704, + 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4, + 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5, + 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505, + 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45, + 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f, + 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f, + 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f, + 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e, + 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e, + 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e, + 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce, + 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c, + 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc, + 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c, + 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d, + 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d, + 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d, + 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88, + 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48, + 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708, + 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89, + 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9, + 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309, + 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb, + 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b, + 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b, + 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b, + 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a, + 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a, + 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a, + 0x7851a2ca}, + {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb, + 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8, + 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0, + 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f, + 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a, + 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf, + 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5, + 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380, + 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815, + 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa, + 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2, + 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1, + 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1, + 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4, + 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa, + 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df, + 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6, + 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5, + 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad, + 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca, + 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f, + 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a, + 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8, + 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d, + 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708, + 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d, + 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865, + 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636, + 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f, + 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a, + 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744, + 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061, + 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0, + 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293, + 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb, + 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874, + 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1, + 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4, + 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f, + 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a, + 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f, + 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120, + 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778, + 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b, + 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a, + 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af, + 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81, + 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4, + 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd, + 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e, + 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6, + 0x566b6848}}; + +static const z_word_t crc_braid_big_table[][256] = { + {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912, + 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba, + 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3, + 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30, + 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e, + 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3, + 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73, + 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe, + 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0, + 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643, + 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a, + 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082, + 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4, + 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279, + 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735, + 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8, + 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad, + 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05, + 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c, + 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718, + 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46, + 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb, + 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc, + 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41, + 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f, + 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad, + 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4, + 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c, + 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779, + 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4, + 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8, + 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235, + 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7, + 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f, + 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476, + 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195, + 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb, + 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46, + 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622, + 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af, + 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1, + 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12, + 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b, + 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3, + 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51, + 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc, + 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90, + 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d, + 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708, + 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0, + 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9, + 0x48686b56}, + {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c, + 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae, + 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb, + 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90, + 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410, + 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b, + 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6, + 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed, + 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d, + 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036, + 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953, + 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1, + 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca, + 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781, + 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d, + 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416, + 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f, + 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd, + 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8, + 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b, + 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb, + 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0, + 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5, + 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e, + 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e, + 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558, + 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d, + 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf, + 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6, + 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad, + 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971, + 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a, + 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b, + 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969, + 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c, + 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57, + 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7, + 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c, + 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab, + 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0, + 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160, + 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b, + 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e, + 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac, + 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d, + 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546, + 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a, + 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1, + 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8, + 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a, + 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f, + 0xcaa25178}, + {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00, + 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b, + 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed, + 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777, + 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01, + 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a, + 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef, + 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74, + 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002, + 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498, + 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee, + 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75, + 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05, + 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e, + 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8, + 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73, + 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404, + 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f, + 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9, + 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71, + 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607, + 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c, + 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb, + 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470, + 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806, + 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790, + 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6, + 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d, + 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a, + 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991, + 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7, + 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c, + 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09, + 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92, + 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4, + 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e, + 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08, + 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593, + 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3, + 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778, + 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e, + 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94, + 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2, + 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079, + 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c, + 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497, + 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1, + 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a, + 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d, + 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396, + 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0, + 0x0c7ac97b}, + {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669, + 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853, + 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062, + 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527, + 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad, + 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545, + 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27, + 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf, + 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45, + 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800, + 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031, + 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b, + 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26, + 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce, + 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d, + 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5, + 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130, + 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a, + 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b, + 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480, + 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a, + 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2, + 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e, + 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996, + 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c, + 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc, + 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd, + 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7, + 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232, + 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da, + 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439, + 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1, + 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da, + 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0, + 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1, + 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94, + 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e, + 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6, + 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2, + 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a, + 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0, + 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95, + 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4, + 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e, + 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395, + 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d, + 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e, + 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676, + 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83, + 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9, + 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888, + 0x5185cd09}}; + +#endif /* W */ + +#endif /* N == 6 */ + +static const uint32_t x2n_table[] = { + 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000, + 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467, + 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0, + 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169, + 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37, + 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a, + 0xc40ba6d0, 0xc4e22c3c}; + +#endif /* CRC32_BRAID_TBL_H_ */ diff --git a/crc32_comb.c b/crc32_comb.c deleted file mode 100644 index 832dbbbc22..0000000000 --- a/crc32_comb.c +++ /dev/null @@ -1,110 +0,0 @@ -/* crc32_comb.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016, 2018 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -#include "zbuild.h" -#include "deflate.h" -#include "crc32_p.h" -#include "crc32_comb_tbl.h" - - -/* Local functions for crc concatenation */ -static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2); -static void crc32_combine_gen_(uint32_t op[GF2_DIM], z_off64_t len2); - -/* ========================================================================= */ -static uint32_t crc32_combine_(uint32_t crc1, uint32_t crc2, z_off64_t len2) { - int n; - - if (len2 > 0) - /* operator for 2^n zeros repeats every GF2_DIM n values */ - for (n = 0; len2; n = (n + 1) % GF2_DIM, len2 >>= 1) - if (len2 & 1) - crc1 = gf2_matrix_times(crc_comb[n], crc1); - return crc1 ^ crc2; -} - -/* ========================================================================= */ -#ifdef ZLIB_COMPAT -unsigned long Z_EXPORT PREFIX(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off_t len2) { - return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); -} - -unsigned long Z_EXPORT PREFIX4(crc32_combine)(unsigned long crc1, unsigned long crc2, z_off64_t len2) { - return (unsigned long)crc32_combine_((uint32_t)crc1, (uint32_t)crc2, len2); -} -#else -uint32_t Z_EXPORT PREFIX4(crc32_combine)(uint32_t crc1, uint32_t crc2, z_off64_t len2) { - return crc32_combine_(crc1, crc2, len2); -} -#endif - -/* ========================================================================= */ - -static void crc32_combine_gen_(uint32_t op[GF2_DIM], z_off64_t len2) { - uint32_t row; - int j; - unsigned i; - - /* if len2 is zero or negative, return the identity matrix */ - if (len2 <= 0) { - row = 1; - for (j = 0; j < GF2_DIM; j++) { - op[j] = row; - row <<= 1; - } - return; - } - - /* at least one bit in len2 is set -- find it, and copy the operator - corresponding to that position into op */ - i = 0; - for (;;) { - if (len2 & 1) { - for (j = 0; j < GF2_DIM; j++) - op[j] = crc_comb[i][j]; - break; - } - len2 >>= 1; - i = (i + 1) % GF2_DIM; - } - - /* for each remaining bit set in len2 (if any), multiply op by the operator - corresponding to that position */ - for (;;) { - len2 >>= 1; - i = (i + 1) % GF2_DIM; - if (len2 == 0) - break; - if (len2 & 1) - for (j = 0; j < GF2_DIM; j++) - op[j] = gf2_matrix_times(crc_comb[i], op[j]); - } -} - -/* ========================================================================= */ - -#ifdef ZLIB_COMPAT -void Z_EXPORT PREFIX(crc32_combine_gen)(uint32_t *op, z_off_t len2) { - crc32_combine_gen_(op, len2); -} -void Z_EXPORT PREFIX4(crc32_combine_gen)(uint32_t *op, z_off64_t len2) { - crc32_combine_gen_(op, len2); -} -#else -void Z_EXPORT PREFIX4(crc32_combine_gen)(uint32_t op[GF2_DIM], z_off64_t len2) { - crc32_combine_gen_(op, len2); -} -#endif - -/* ========================================================================= */ -uint32_t Z_EXPORT PREFIX(crc32_combine_op)(uint32_t crc1, uint32_t crc2, const uint32_t *op) { - return gf2_matrix_times(op, crc1) ^ crc2; -} diff --git a/crc32_comb_tbl.h b/crc32_comb_tbl.h deleted file mode 100644 index 43818c3e03..0000000000 --- a/crc32_comb_tbl.h +++ /dev/null @@ -1,300 +0,0 @@ -#ifndef CRC32_COMB_TBL_H_ -#define CRC32_COMB_TBL_H_ - -/* crc32_comb_tbl.h -- zero operators table for CRC combine - * Generated automatically by makecrct.c - */ - -static const uint32_t crc_comb[32][32] = -{ - { - 0x77073096, 0xee0e612c, 0x076dc419, 0x0edb8832, 0x1db71064, - 0x3b6e20c8, 0x76dc4190, 0xedb88320, 0x00000001, 0x00000002, - 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, - 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, - 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, - 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, - 0x00400000, 0x00800000 - }, - { - 0x191b3141, 0x32366282, 0x646cc504, 0xc8d98a08, 0x4ac21251, - 0x958424a2, 0xf0794f05, 0x3b83984b, 0x77073096, 0xee0e612c, - 0x076dc419, 0x0edb8832, 0x1db71064, 0x3b6e20c8, 0x76dc4190, - 0xedb88320, 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, - 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, - 0x00004000, 0x00008000 - }, - { - 0xb8bc6765, 0xaa09c88b, 0x8f629757, 0xc5b428ef, 0x5019579f, - 0xa032af3e, 0x9b14583d, 0xed59b63b, 0x01c26a37, 0x0384d46e, - 0x0709a8dc, 0x0e1351b8, 0x1c26a370, 0x384d46e0, 0x709a8dc0, - 0xe1351b80, 0x191b3141, 0x32366282, 0x646cc504, 0xc8d98a08, - 0x4ac21251, 0x958424a2, 0xf0794f05, 0x3b83984b, 0x77073096, - 0xee0e612c, 0x076dc419, 0x0edb8832, 0x1db71064, 0x3b6e20c8, - 0x76dc4190, 0xedb88320 - }, - { - 0xccaa009e, 0x4225077d, 0x844a0efa, 0xd3e51bb5, 0x7cbb312b, - 0xf9766256, 0x299dc2ed, 0x533b85da, 0xa6770bb4, 0x979f1129, - 0xf44f2413, 0x33ef4e67, 0x67de9cce, 0xcfbd399c, 0x440b7579, - 0x8816eaf2, 0xcb5cd3a5, 0x4dc8a10b, 0x9b914216, 0xec53826d, - 0x03d6029b, 0x07ac0536, 0x0f580a6c, 0x1eb014d8, 0x3d6029b0, - 0x7ac05360, 0xf580a6c0, 0x30704bc1, 0x60e09782, 0xc1c12f04, - 0x58f35849, 0xb1e6b092 - }, - { - 0xae689191, 0x87a02563, 0xd4314c87, 0x73139f4f, 0xe6273e9e, - 0x173f7b7d, 0x2e7ef6fa, 0x5cfdedf4, 0xb9fbdbe8, 0xa886b191, - 0x8a7c6563, 0xcf89cc87, 0x44629f4f, 0x88c53e9e, 0xcafb7b7d, - 0x4e87f0bb, 0x9d0fe176, 0xe16ec4ad, 0x19ac8f1b, 0x33591e36, - 0x66b23c6c, 0xcd6478d8, 0x41b9f7f1, 0x8373efe2, 0xdd96d985, - 0x605cb54b, 0xc0b96a96, 0x5a03d36d, 0xb407a6da, 0xb37e4bf5, - 0xbd8d91ab, 0xa06a2517 - }, - { - 0xf1da05aa, 0x38c50d15, 0x718a1a2a, 0xe3143454, 0x1d596ee9, - 0x3ab2ddd2, 0x7565bba4, 0xeacb7748, 0x0ee7e8d1, 0x1dcfd1a2, - 0x3b9fa344, 0x773f4688, 0xee7e8d10, 0x078c1c61, 0x0f1838c2, - 0x1e307184, 0x3c60e308, 0x78c1c610, 0xf1838c20, 0x38761e01, - 0x70ec3c02, 0xe1d87804, 0x18c1f649, 0x3183ec92, 0x6307d924, - 0xc60fb248, 0x576e62d1, 0xaedcc5a2, 0x86c88d05, 0xd6e01c4b, - 0x76b13ed7, 0xed627dae - }, - { - 0x8f352d95, 0xc51b5d6b, 0x5147bc97, 0xa28f792e, 0x9e6ff41d, - 0xe7aeee7b, 0x142cdab7, 0x2859b56e, 0x50b36adc, 0xa166d5b8, - 0x99bcad31, 0xe8085c23, 0x0b61be07, 0x16c37c0e, 0x2d86f81c, - 0x5b0df038, 0xb61be070, 0xb746c6a1, 0xb5fc8b03, 0xb0881047, - 0xba6126cf, 0xafb34bdf, 0x841791ff, 0xd35e25bf, 0x7dcd4d3f, - 0xfb9a9a7e, 0x2c4432bd, 0x5888657a, 0xb110caf4, 0xb95093a9, - 0xa9d02113, 0x88d14467 - }, - { - 0x33fff533, 0x67ffea66, 0xcfffd4cc, 0x448eafd9, 0x891d5fb2, - 0xc94bb925, 0x49e6740b, 0x93cce816, 0xfce8d66d, 0x22a0aa9b, - 0x45415536, 0x8a82aa6c, 0xce745299, 0x4799a373, 0x8f3346e6, - 0xc5178b8d, 0x515e115b, 0xa2bc22b6, 0x9e09432d, 0xe763801b, - 0x15b60677, 0x2b6c0cee, 0x56d819dc, 0xadb033b8, 0x80116131, - 0xdb53c423, 0x6dd68e07, 0xdbad1c0e, 0x6c2b3e5d, 0xd8567cba, - 0x6bddff35, 0xd7bbfe6a - }, - { - 0xce3371cb, 0x4717e5d7, 0x8e2fcbae, 0xc72e911d, 0x552c247b, - 0xaa5848f6, 0x8fc197ad, 0xc4f2291b, 0x52955477, 0xa52aa8ee, - 0x9124579d, 0xf939a97b, 0x290254b7, 0x5204a96e, 0xa40952dc, - 0x9363a3f9, 0xfdb641b3, 0x201d8527, 0x403b0a4e, 0x8076149c, - 0xdb9d2f79, 0x6c4b58b3, 0xd896b166, 0x6a5c648d, 0xd4b8c91a, - 0x72009475, 0xe40128ea, 0x13735795, 0x26e6af2a, 0x4dcd5e54, - 0x9b9abca8, 0xec447f11 - }, - { - 0x1072db28, 0x20e5b650, 0x41cb6ca0, 0x8396d940, 0xdc5cb4c1, - 0x63c86fc3, 0xc790df86, 0x5450b94d, 0xa8a1729a, 0x8a33e375, - 0xcf16c0ab, 0x455c8717, 0x8ab90e2e, 0xce031a1d, 0x4777327b, - 0x8eee64f6, 0xc6adcfad, 0x562a991b, 0xac553236, 0x83db622d, - 0xdcc7c21b, 0x62fe8277, 0xc5fd04ee, 0x508b0f9d, 0xa1161f3a, - 0x995d3835, 0xe9cb762b, 0x08e7ea17, 0x11cfd42e, 0x239fa85c, - 0x473f50b8, 0x8e7ea170 - }, - { - 0xf891f16f, 0x2a52e49f, 0x54a5c93e, 0xa94b927c, 0x89e622b9, - 0xc8bd4333, 0x4a0b8027, 0x9417004e, 0xf35f06dd, 0x3dcf0bfb, - 0x7b9e17f6, 0xf73c2fec, 0x35095999, 0x6a12b332, 0xd4256664, - 0x733bca89, 0xe6779512, 0x179e2c65, 0x2f3c58ca, 0x5e78b194, - 0xbcf16328, 0xa293c011, 0x9e568663, 0xe7dc0a87, 0x14c9134f, - 0x2992269e, 0x53244d3c, 0xa6489a78, 0x97e032b1, 0xf4b16323, - 0x3213c007, 0x6427800e - }, - { - 0x88b6ba63, 0xca1c7287, 0x4f49e34f, 0x9e93c69e, 0xe6568b7d, - 0x17dc10bb, 0x2fb82176, 0x5f7042ec, 0xbee085d8, 0xa6b00df1, - 0x96111da3, 0xf7533d07, 0x35d77c4f, 0x6baef89e, 0xd75df13c, - 0x75cae439, 0xeb95c872, 0x0c5a96a5, 0x18b52d4a, 0x316a5a94, - 0x62d4b528, 0xc5a96a50, 0x5023d2e1, 0xa047a5c2, 0x9bfe4dc5, - 0xec8d9dcb, 0x026a3dd7, 0x04d47bae, 0x09a8f75c, 0x1351eeb8, - 0x26a3dd70, 0x4d47bae0 - }, - { - 0x5ad8a92c, 0xb5b15258, 0xb013a2f1, 0xbb5643a3, 0xaddd8107, - 0x80ca044f, 0xdae50edf, 0x6ebb1bff, 0xdd7637fe, 0x619d69bd, - 0xc33ad37a, 0x5d04a0b5, 0xba09416a, 0xaf638495, 0x85b60f6b, - 0xd01d1897, 0x7b4b376f, 0xf6966ede, 0x365ddbfd, 0x6cbbb7fa, - 0xd9776ff4, 0x699fd9a9, 0xd33fb352, 0x7d0e60e5, 0xfa1cc1ca, - 0x2f4885d5, 0x5e910baa, 0xbd221754, 0xa13528e9, 0x991b5793, - 0xe947a967, 0x09fe548f - }, - { - 0xb566f6e2, 0xb1bceb85, 0xb808d14b, 0xab60a4d7, 0x8db04fef, - 0xc011999f, 0x5b52357f, 0xb6a46afe, 0xb639d3bd, 0xb702a13b, - 0xb5744437, 0xb1998e2f, 0xb8421a1f, 0xabf5327f, 0x8c9b62bf, - 0xc247c33f, 0x5ffe803f, 0xbffd007e, 0xa48b06bd, 0x92670b3b, - 0xffbf1037, 0x240f262f, 0x481e4c5e, 0x903c98bc, 0xfb083739, - 0x2d616833, 0x5ac2d066, 0xb585a0cc, 0xb07a47d9, 0xbb8589f3, - 0xac7a15a7, 0x83852d0f - }, - { - 0x9d9129bf, 0xe053553f, 0x1bd7ac3f, 0x37af587e, 0x6f5eb0fc, - 0xdebd61f8, 0x660bc5b1, 0xcc178b62, 0x435e1085, 0x86bc210a, - 0xd6094455, 0x77638eeb, 0xeec71dd6, 0x06ff3ded, 0x0dfe7bda, - 0x1bfcf7b4, 0x37f9ef68, 0x6ff3ded0, 0xdfe7bda0, 0x64be7d01, - 0xc97cfa02, 0x4988f245, 0x9311e48a, 0xfd52cf55, 0x21d498eb, - 0x43a931d6, 0x875263ac, 0xd5d5c119, 0x70da8473, 0xe1b508e6, - 0x181b178d, 0x30362f1a - }, - { - 0x2ee43a2c, 0x5dc87458, 0xbb90e8b0, 0xac50d721, 0x83d0a803, - 0xdcd05647, 0x62d1aacf, 0xc5a3559e, 0x5037ad7d, 0xa06f5afa, - 0x9bafb3b5, 0xec2e612b, 0x032dc417, 0x065b882e, 0x0cb7105c, - 0x196e20b8, 0x32dc4170, 0x65b882e0, 0xcb7105c0, 0x4d930dc1, - 0x9b261b82, 0xed3d3145, 0x010b64cb, 0x0216c996, 0x042d932c, - 0x085b2658, 0x10b64cb0, 0x216c9960, 0x42d932c0, 0x85b26580, - 0xd015cd41, 0x7b5a9cc3 - }, - { - 0x1b4511ee, 0x368a23dc, 0x6d1447b8, 0xda288f70, 0x6f2018a1, - 0xde403142, 0x67f164c5, 0xcfe2c98a, 0x44b49555, 0x89692aaa, - 0xc9a35315, 0x4837a06b, 0x906f40d6, 0xfbaf87ed, 0x2c2e099b, - 0x585c1336, 0xb0b8266c, 0xba014a99, 0xaf739373, 0x859620a7, - 0xd05d470f, 0x7bcb885f, 0xf79710be, 0x345f273d, 0x68be4e7a, - 0xd17c9cf4, 0x79883fa9, 0xf3107f52, 0x3d51f8e5, 0x7aa3f1ca, - 0xf547e394, 0x31fec169 - }, - { - 0xbce15202, 0xa2b3a245, 0x9e1642cb, 0xe75d83d7, 0x15ca01ef, - 0x2b9403de, 0x572807bc, 0xae500f78, 0x87d118b1, 0xd4d33723, - 0x72d76807, 0xe5aed00e, 0x102ca65d, 0x20594cba, 0x40b29974, - 0x816532e8, 0xd9bb6391, 0x6807c163, 0xd00f82c6, 0x7b6e03cd, - 0xf6dc079a, 0x36c90975, 0x6d9212ea, 0xdb2425d4, 0x6d394de9, - 0xda729bd2, 0x6f9431e5, 0xdf2863ca, 0x6521c1d5, 0xca4383aa, - 0x4ff60115, 0x9fec022a - }, - { - 0xff08e5ef, 0x2560cd9f, 0x4ac19b3e, 0x9583367c, 0xf0776ab9, - 0x3b9fd333, 0x773fa666, 0xee7f4ccc, 0x078f9fd9, 0x0f1f3fb2, - 0x1e3e7f64, 0x3c7cfec8, 0x78f9fd90, 0xf1f3fb20, 0x3896f001, - 0x712de002, 0xe25bc004, 0x1fc68649, 0x3f8d0c92, 0x7f1a1924, - 0xfe343248, 0x271962d1, 0x4e32c5a2, 0x9c658b44, 0xe3ba10c9, - 0x1c0527d3, 0x380a4fa6, 0x70149f4c, 0xe0293e98, 0x1b237b71, - 0x3646f6e2, 0x6c8dedc4 - }, - { - 0x6f76172e, 0xdeec2e5c, 0x66a95af9, 0xcd52b5f2, 0x41d46da5, - 0x83a8db4a, 0xdc20b0d5, 0x633067eb, 0xc660cfd6, 0x57b099ed, - 0xaf6133da, 0x85b361f5, 0xd017c5ab, 0x7b5e8d17, 0xf6bd1a2e, - 0x360b321d, 0x6c16643a, 0xd82cc874, 0x6b2896a9, 0xd6512d52, - 0x77d35ce5, 0xefa6b9ca, 0x043c75d5, 0x0878ebaa, 0x10f1d754, - 0x21e3aea8, 0x43c75d50, 0x878ebaa0, 0xd46c7301, 0x73a9e043, - 0xe753c086, 0x15d6874d - }, - { - 0x56f5cab9, 0xadeb9572, 0x80a62ca5, 0xda3d5f0b, 0x6f0bb857, - 0xde1770ae, 0x675fe71d, 0xcebfce3a, 0x460e9a35, 0x8c1d346a, - 0xc34b6e95, 0x5de7db6b, 0xbbcfb6d6, 0xacee6bed, 0x82add19b, - 0xde2aa577, 0x67244caf, 0xce48995e, 0x47e034fd, 0x8fc069fa, - 0xc4f1d5b5, 0x5292ad2b, 0xa5255a56, 0x913bb2ed, 0xf906639b, - 0x297dc177, 0x52fb82ee, 0xa5f705dc, 0x909f0df9, 0xfa4f1db3, - 0x2fef3d27, 0x5fde7a4e - }, - { - 0x385993ac, 0x70b32758, 0xe1664eb0, 0x19bd9b21, 0x337b3642, - 0x66f66c84, 0xcdecd908, 0x40a8b451, 0x815168a2, 0xd9d3d705, - 0x68d6a84b, 0xd1ad5096, 0x782ba76d, 0xf0574eda, 0x3bdf9bf5, - 0x77bf37ea, 0xef7e6fd4, 0x058dd9e9, 0x0b1bb3d2, 0x163767a4, - 0x2c6ecf48, 0x58dd9e90, 0xb1bb3d20, 0xb8077c01, 0xab7ffe43, - 0x8d8efac7, 0xc06cf3cf, 0x5ba8e1df, 0xb751c3be, 0xb5d2813d, - 0xb0d4043b, 0xbad90e37 - }, - { - 0xb4247b20, 0xb339f001, 0xbd02e643, 0xa174cac7, 0x999893cf, - 0xe84021df, 0x0bf145ff, 0x17e28bfe, 0x2fc517fc, 0x5f8a2ff8, - 0xbf145ff0, 0xa559b9a1, 0x91c27503, 0xf8f5ec47, 0x2a9adecf, - 0x5535bd9e, 0xaa6b7b3c, 0x8fa7f039, 0xc43ee633, 0x530cca27, - 0xa619944e, 0x97422edd, 0xf5f55bfb, 0x309bb1b7, 0x6137636e, - 0xc26ec6dc, 0x5fac8bf9, 0xbf5917f2, 0xa5c329a5, 0x90f7550b, - 0xfa9fac57, 0x2e4e5eef - }, - { - 0x695186a7, 0xd2a30d4e, 0x7e371cdd, 0xfc6e39ba, 0x23ad7535, - 0x475aea6a, 0x8eb5d4d4, 0xc61aafe9, 0x57445993, 0xae88b326, - 0x8660600d, 0xd7b1c65b, 0x74128af7, 0xe82515ee, 0x0b3b2d9d, - 0x16765b3a, 0x2cecb674, 0x59d96ce8, 0xb3b2d9d0, 0xbc14b5e1, - 0xa3586d83, 0x9dc1dd47, 0xe0f2bccf, 0x1a947fdf, 0x3528ffbe, - 0x6a51ff7c, 0xd4a3fef8, 0x7236fbb1, 0xe46df762, 0x13aae885, - 0x2755d10a, 0x4eaba214 - }, - { - 0x66bc001e, 0xcd78003c, 0x41810639, 0x83020c72, 0xdd751ea5, - 0x619b3b0b, 0xc3367616, 0x5d1dea6d, 0xba3bd4da, 0xaf06aff5, - 0x857c59ab, 0xd189b517, 0x78626c6f, 0xf0c4d8de, 0x3af8b7fd, - 0x75f16ffa, 0xebe2dff4, 0x0cb4b9a9, 0x19697352, 0x32d2e6a4, - 0x65a5cd48, 0xcb4b9a90, 0x4de63361, 0x9bcc66c2, 0xece9cbc5, - 0x02a291cb, 0x05452396, 0x0a8a472c, 0x15148e58, 0x2a291cb0, - 0x54523960, 0xa8a472c0 - }, - { - 0xb58b27b3, 0xb0674927, 0xbbbf940f, 0xac0e2e5f, 0x836d5aff, - 0xddabb3bf, 0x6026613f, 0xc04cc27e, 0x5be882bd, 0xb7d1057a, - 0xb4d30cb5, 0xb2d71f2b, 0xbedf3817, 0xa6cf766f, 0x96efea9f, - 0xf6aed37f, 0x362ca0bf, 0x6c59417e, 0xd8b282fc, 0x6a1403b9, - 0xd4280772, 0x732108a5, 0xe642114a, 0x17f524d5, 0x2fea49aa, - 0x5fd49354, 0xbfa926a8, 0xa4234b11, 0x93379063, 0xfd1e2687, - 0x214d4b4f, 0x429a969e - }, - { - 0xfe273162, 0x273f6485, 0x4e7ec90a, 0x9cfd9214, 0xe28a2269, - 0x1e654293, 0x3cca8526, 0x79950a4c, 0xf32a1498, 0x3d252f71, - 0x7a4a5ee2, 0xf494bdc4, 0x32587dc9, 0x64b0fb92, 0xc961f724, - 0x49b2e809, 0x9365d012, 0xfdbaa665, 0x20044a8b, 0x40089516, - 0x80112a2c, 0xdb535219, 0x6dd7a273, 0xdbaf44e6, 0x6c2f8f8d, - 0xd85f1f1a, 0x6bcf3875, 0xd79e70ea, 0x744de795, 0xe89bcf2a, - 0x0a469815, 0x148d302a - }, - { - 0xd3c98813, 0x7ce21667, 0xf9c42cce, 0x28f95fdd, 0x51f2bfba, - 0xa3e57f74, 0x9cbbf8a9, 0xe206f713, 0x1f7ce867, 0x3ef9d0ce, - 0x7df3a19c, 0xfbe74338, 0x2cbf8031, 0x597f0062, 0xb2fe00c4, - 0xbe8d07c9, 0xa66b09d3, 0x97a715e7, 0xf43f2d8f, 0x330f5d5f, - 0x661ebabe, 0xcc3d757c, 0x430becb9, 0x8617d972, 0xd75eb4a5, - 0x75cc6f0b, 0xeb98de16, 0x0c40ba6d, 0x188174da, 0x3102e9b4, - 0x6205d368, 0xc40ba6d0 - }, - { - 0xf7d6deb4, 0x34dcbb29, 0x69b97652, 0xd372eca4, 0x7d94df09, - 0xfb29be12, 0x2d227a65, 0x5a44f4ca, 0xb489e994, 0xb262d569, - 0xbfb4ac93, 0xa4185f67, 0x9341b88f, 0xfdf2775f, 0x2095e8ff, - 0x412bd1fe, 0x8257a3fc, 0xdfde41b9, 0x64cd8533, 0xc99b0a66, - 0x4847128d, 0x908e251a, 0xfa6d4c75, 0x2fab9eab, 0x5f573d56, - 0xbeae7aac, 0xa62df319, 0x972ae073, 0xf524c6a7, 0x31388b0f, - 0x6271161e, 0xc4e22c3c - }, - { - 0xedb88320, 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, - 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, - 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, - 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000 - }, - { - 0x76dc4190, 0xedb88320, 0x00000001, 0x00000002, 0x00000004, - 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, - 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, - 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, - 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000 - }, - { - 0x1db71064, 0x3b6e20c8, 0x76dc4190, 0xedb88320, 0x00000001, - 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, - 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, - 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, - 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, - 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, - 0x04000000, 0x08000000 - } -}; - -#endif /* CRC32_COMB_TBL_H_ */ diff --git a/crc32_p.h b/crc32_p.h deleted file mode 100644 index ae54c579ff..0000000000 --- a/crc32_p.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CRC32_P_H_ -#define CRC32_P_H_ - -#include "zbuild.h" -#include "zendian.h" - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - - -static inline uint32_t gf2_matrix_times(const uint32_t *mat, uint32_t vec) { - uint32_t sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - - -extern uint32_t crc32_byfour(uint32_t, const unsigned char *, uint64_t); - -#endif /* CRC32_P_H_ */ diff --git a/crc32_tbl.h b/crc32_tbl.h deleted file mode 100644 index ee2030c6ce..0000000000 --- a/crc32_tbl.h +++ /dev/null @@ -1,444 +0,0 @@ -#ifndef CRC32_TBL_H_ -#define CRC32_TBL_H_ - -/* crc32_tbl.h -- tables for rapid CRC calculation - * Generated automatically by makecrct.c - */ - -static const uint32_t crc_table[8][256] = -{ - { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, - 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, - 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, - 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, - 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, - 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, - 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, - 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, - 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, - 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, - 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, - 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, - 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, - 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, - 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, - 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, - 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, - 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, - 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, - 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, - 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, - 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, - 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, - 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, - 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, - 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, - 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, - 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, - 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, - 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, - 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, - 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, - 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, - 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, - 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, - 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, - 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, - 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, - 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, - 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, - 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, - 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, - 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, - 0x2d02ef8d - }, - { - 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, - 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, - 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, - 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, - 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859, - 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, - 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, - 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, - 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae, - 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2, - 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175, - 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, - 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, - 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40, - 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, - 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, - 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850, - 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, - 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, - 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, - 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af, - 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea, - 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74, - 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, - 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, - 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a, - 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, - 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, - 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a, - 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, - 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, - 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, - 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed, - 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0, - 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, - 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, - 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, - 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5, - 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, - 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, - 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842, - 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, - 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, - 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, - 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec, - 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9, - 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66, - 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, - 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, - 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4, - 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, - 0x9324fd72 - }, - { - 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, - 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f, - 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a, - 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, - 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8, - 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, - 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, - 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, - 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84, - 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7, - 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922, - 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, - 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, - 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b, - 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, - 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, - 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c, - 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, - 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, - 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, - 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98, - 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873, - 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e, - 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, - 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, - 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7, - 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732, - 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, - 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0, - 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, - 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, - 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, - 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc, - 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef, - 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a, - 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, - 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, - 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43, - 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e, - 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, - 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24, - 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, - 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, - 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, - 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0, - 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b, - 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576, - 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, - 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, - 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f, - 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, - 0xbe9834ed - }, - { - 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, - 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a, - 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, - 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, - 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70, - 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, - 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, - 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, - 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086, - 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4, - 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d, - 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, - 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, - 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, - 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, - 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, - 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5, - 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, - 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, - 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, - 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec, - 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde, - 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817, - 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, - 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, - 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e, - 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7, - 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, - 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4, - 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, - 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, - 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, - 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52, - 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f, - 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, - 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, - 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, - 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647, - 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d, - 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, - 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be, - 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, - 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, - 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, - 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138, - 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a, - 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, - 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, - 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, - 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d, - 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194, - 0xde0506f1 - }, - { - 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07, - 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79, - 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7, - 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84, - 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13, - 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663, - 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5, - 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5, - 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832, - 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51, - 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf, - 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1, - 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76, - 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606, - 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996, - 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6, - 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c, - 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712, - 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c, - 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4, - 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943, - 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333, - 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe, - 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce, - 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359, - 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a, - 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04, - 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a, - 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0, - 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580, - 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10, - 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060, - 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1, - 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf, - 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31, - 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852, - 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5, - 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5, - 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75, - 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005, - 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292, - 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1, - 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f, - 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111, - 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0, - 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0, - 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40, - 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530, - 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba, - 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4, - 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a, - 0x8def022d - }, - { - 0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64, - 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1, - 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e, - 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61, - 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82, - 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff, - 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7, - 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da, - 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139, - 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6, - 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89, - 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c, - 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0, - 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d, - 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a, - 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177, - 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de, - 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b, - 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824, - 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e, - 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad, - 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0, - 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d, - 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60, - 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83, - 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822, - 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d, - 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8, - 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171, - 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c, - 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b, - 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6, - 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca, - 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f, - 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430, - 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf, - 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c, - 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51, - 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9, - 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84, - 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67, - 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398, - 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7, - 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62, - 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e, - 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923, - 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4, - 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9, - 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070, - 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5, - 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a, - 0x72fd2493 - }, - { - 0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907, - 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f, - 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a, - 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e, - 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512, - 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14, - 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b, - 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d, - 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731, - 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925, - 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620, - 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28, - 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70, - 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176, - 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d, - 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b, - 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b, - 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63, - 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266, - 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a, - 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446, - 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40, - 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557, - 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51, - 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d, - 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0, - 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5, - 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed, - 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd, - 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb, - 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0, - 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6, - 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de, - 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6, - 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3, - 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7, - 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb, - 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd, - 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92, - 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094, - 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598, - 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c, - 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489, - 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81, - 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9, - 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af, - 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4, - 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2, - 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2, - 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba, - 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf, - 0xed3498be - }, - { - 0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f, - 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d, - 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0, - 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42, - 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95, - 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2, - 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a, - 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d, - 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea, - 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748, - 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5, - 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27, - 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b, - 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac, - 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4, - 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3, - 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44, - 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6, - 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b, - 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329, - 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe, - 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9, - 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1, - 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6, - 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921, - 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555, - 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8, - 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a, - 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd, - 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a, - 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2, - 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5, - 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2, - 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330, - 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad, - 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f, - 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8, - 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef, - 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc, - 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb, - 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c, - 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e, - 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03, - 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1, - 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6, - 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1, - 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9, - 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e, - 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409, - 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb, - 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966, - 0xf10605de - } -}; - -#endif /* CRC32_TBL_H_ */ diff --git a/doc/crc-doc.1.0.pdf b/doc/crc-doc.1.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d6942ecc09a3f8b2d7e4b6fbecc5955121e8e7cf GIT binary patch literal 776142 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

    ha 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�rRb`0y|*v1_Y0K2x& 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