diff --git a/Makefile.am b/Makefile.am index 471f18b5..5d2a06a2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -217,7 +217,10 @@ $(CLI_PREFIX)sync.$(OBJEXT): $(CLI_INCLUDES) $(CLI_PREFIX)thermal.$(OBJEXT): $(CLI_INCLUDES) $(CLI_PREFIX)touch.$(OBJEXT): $(CLI_INCLUDES) $(CLI_PREFIX)unixapp.$(OBJEXT): $(CLI_INCLUDES) -$(CLI_PREFIX)util.$(OBJEXT): $(CLI_INCLUDES) +$(CLI_PREFIX)util.$(OBJEXT): $(CLI_INCLUDES) \ + $(srcdir)/cmdline/murmur3.c \ + $(srcdir)/cmdline/spooky2.c \ + $(srcdir)/cmdline/museair.c # Add the .version file in the distribution dist-hook: diff --git a/cmdline/murmur3.c b/cmdline/murmur3.c index 9ac614db..51cc8b09 100644 --- a/cmdline/murmur3.c +++ b/cmdline/murmur3.c @@ -26,42 +26,16 @@ static inline uint32_t fmix32(uint32_t h) } /* - * Warning! - * Don't declare these variables static, otherwise the gcc optimizer - * may generate very slow code for multiplication with these constants, - * like: - - -> .cpp - k1 *= c1; - -> .asm - 152: 8d 14 80 lea (%eax,%eax,4),%edx - 155: 8d 14 90 lea (%eax,%edx,4),%edx - 158: c1 e2 03 shl $0x3,%edx - 15b: 29 c2 sub %eax,%edx - 15d: 8d 14 d2 lea (%edx,%edx,8),%edx - 160: 8d 14 90 lea (%eax,%edx,4),%edx - 163: 8d 14 d0 lea (%eax,%edx,8),%edx - 166: 8d 14 90 lea (%eax,%edx,4),%edx - 169: 8d 14 50 lea (%eax,%edx,2),%edx - 16c: 8d 14 90 lea (%eax,%edx,4),%edx - 16f: 8d 14 92 lea (%edx,%edx,4),%edx - 172: 8d 14 50 lea (%eax,%edx,2),%edx - 175: 8d 04 d0 lea (%eax,%edx,8),%eax - 178: 8d 14 c5 00 00 00 00 lea 0x0(,%eax,8),%edx - 17f: 29 d0 sub %edx,%eax - - * resulting in speeds of 500 MB/s instead of 3000 MB/s. - * - * Verified with gcc 4.4.4 compiling with : - * - * g++ -g -c -O2 MurmurHash3.cpp -o MurmurHash3.o + * Non-static variables are intentionally used instead of static const + * because keeping these constants in CPU registers yields measurably + * higher throughput than using 32-bit immediate constants in imul. */ uint32_t c1 = 0x239b961b; uint32_t c2 = 0xab0e9789; uint32_t c3 = 0x38b34ae5; uint32_t c4 = 0xa1e38b93; -void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest) +static void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest) { const uint8_t* p; const uint8_t* end; @@ -77,6 +51,11 @@ void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, voi end = p + (size & ~15); /* body */ +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC unroll 8 +#elif defined(__clang__) +#pragma unroll 8 +#endif while (p < end) { uint32_t k1 = util_read32(p + 0); uint32_t k2 = util_read32(p + 4); diff --git a/cmdline/museair.c b/cmdline/museair.c index e6db6046..1eaad941 100644 --- a/cmdline/museair.c +++ b/cmdline/museair.c @@ -190,6 +190,11 @@ static void MuseAirLoong(const void* bytes, size_t len, const uint8_t* seed, uin state[5] ^= seed_b & MASK_K; if (unlikely(q > u64x(12))) { +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC unroll 2 +#elif defined(__clang__) +#pragma unroll 2 +#endif do { state[0] ^= util_read64(p + u64x(0)); state[1] ^= util_read64(p + u64x(1)); diff --git a/cmdline/spooky2.c b/cmdline/spooky2.c index ca063a32..67a86efe 100644 --- a/cmdline/spooky2.c +++ b/cmdline/spooky2.c @@ -96,7 +96,7 @@ // #define sc_const 0xdeadbeefdeadbeefULL -void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) +static void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) { uint64_t h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11; uint8_t buf[sc_blockSize]; @@ -117,6 +117,11 @@ void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* end = p + nblocks * sc_blockSize; /* body */ +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC unroll 1 +#elif defined(__clang__) +#pragma unroll 1 +#endif while (p < end) { Mix(p, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); p += sc_blockSize; diff --git a/cmdline/util.h b/cmdline/util.h index f65dce31..a197f01f 100644 --- a/cmdline/util.h +++ b/cmdline/util.h @@ -110,6 +110,11 @@ uint32_t crc32c_shift(uint32_t crc, size_t size); */ static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, size_t size) { +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC unroll 1 +#elif defined(__clang__) +#pragma unroll 1 +#endif while (size >= 4) { crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24; crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24];