diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2023-01-10 22:14:03 +0200 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2023-01-11 17:31:54 +0200 |
commit | c337983e928682d56ce3470b286a8d5b8646e0ad (patch) | |
tree | 505074fb2b25469230fcc8db34cfdfea6eeb7b9c /src/liblzma/check/crc64_fast.c | |
parent | Tests: Fix unused function warning in test_block_header. (diff) | |
download | xz-c337983e928682d56ce3470b286a8d5b8646e0ad.tar.xz |
liblzma: CLMUL CRC64: Work around a bug in MSVC, second attempt.
This affects only 32-bit x86 builds. x86-64 is OK as is.
I still cannot easily test this myself. The reporter has tested
this and it passes the tests included in the CMake build and
performance is good: raw CRC64 is 2-3 times faster than the
C version of the slice-by-four method. (Note that liblzma doesn't
include a MSVC-compatible version of the 32-bit x86 assembly code
for the slice-by-four method.)
Thanks to Iouri Kharon for figuring out a fix, testing, and
benchmarking.
Diffstat (limited to '')
-rw-r--r-- | src/liblzma/check/crc64_fast.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/liblzma/check/crc64_fast.c b/src/liblzma/check/crc64_fast.c index e3cbf1b1..db44633b 100644 --- a/src/liblzma/check/crc64_fast.c +++ b/src/liblzma/check/crc64_fast.c @@ -184,6 +184,20 @@ calc_hi(uint64_t poly, uint64_t a) MASK_H(in, mask, high) +// MSVC (VS2015 - VS2022) produces bad 32-bit x86 code from the CLMUL CRC +// code when optimizations are enabled (release build). According to the bug +// report, the ebx register is corrupted and the calculated result is wrong. +// Trying to workaround the problem with "__asm mov ebx, ebx" didn't help. +// The following pragma works and performance is still good. x86-64 builds +// aren't affected by this problem. +// +// NOTE: Another pragma after the function restores the optimizations. +// If the #if condition here is updated, the other one must be updated too. +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) \ + && defined(_M_IX86) +# pragma optimize("g", off) +#endif + // EDG-based compilers (Intel's classic compiler and compiler for E2K) can // define __GNUC__ but the attribute must not be used with them. // The new Clang-based ICX needs the attribute. @@ -371,6 +385,10 @@ crc64_clmul(const uint8_t *buf, size_t size, uint64_t crc) # pragma GCC diagnostic pop #endif } +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) \ + && defined(_M_IX86) +# pragma optimize("", on) +#endif #endif |