Use CRC32 ss42 instruction. Load it dynamically.

Test Plan: make all check

Reviewers: dhruba

Reviewed By: dhruba

CC: leveldb, zshao

Differential Revision: https://reviews.facebook.net/D7503
main
Abhishek Kona 12 years ago
parent 7521a225d1
commit 1aae609b92
  1. 8
      Makefile
  2. 74
      util/crc32c.cc

@ -98,7 +98,7 @@ $(SHARED3):
endif # PLATFORM_SHARED_EXT endif # PLATFORM_SHARED_EXT
all: $(VERSIONFILE) $(SHARED) $(LIBRARY) $(THRIFTSERVER) $(TOOLS) all: $(VERSIONFILE) $(SHARED) $(LIBRARY) $(TOOLS)
check: all $(PROGRAMS) $(TESTS) $(TOOLS) check: all $(PROGRAMS) $(TESTS) $(TOOLS)
for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done for t in $(TESTS); do echo "***** Running $$t"; ./$$t || exit 1; done
@ -191,12 +191,6 @@ $(MEMENVLIBRARY) : $(MEMENVOBJECTS)
memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS)
$(CXX) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LDFLAGS) $(CXX) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@ $(LDFLAGS)
leveldb_server: thrift/server.o leveldb_shell $(LIBRARY)
$(CXX) thrift/server.o $(LIBRARY) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS)
leveldb_server_test: thrift/test/simpletest.o $(LIBRARY)
$(CXX) thrift/test/simpletest.o $(LIBRARY) $(EXEC_LDFLAGS) -o $@ $(LDFLAGS)
leveldb_shell: tools/shell/ShellContext.o tools/shell/ShellState.o tools/shell/LeveldbShell.o tools/shell/DBClientProxy.o tools/shell/ShellContext.h tools/shell/ShellState.h tools/shell/DBClientProxy.h $(LIBOBJECTS) leveldb_shell: tools/shell/ShellContext.o tools/shell/ShellState.o tools/shell/LeveldbShell.o tools/shell/DBClientProxy.o tools/shell/ShellContext.h tools/shell/ShellState.h tools/shell/DBClientProxy.h $(LIBOBJECTS)
$(CXX) tools/shell/ShellContext.o tools/shell/ShellState.o tools/shell/LeveldbShell.o tools/shell/DBClientProxy.o $(LIBOBJECTS) -o $@ $(LDFLAGS) $(CXX) tools/shell/ShellContext.o tools/shell/ShellState.o tools/shell/LeveldbShell.o tools/shell/DBClientProxy.o $(LIBOBJECTS) -o $@ $(LDFLAGS)

@ -7,10 +7,10 @@
#include "util/crc32c.h" #include "util/crc32c.h"
#include <stdint.h>
#ifdef __SSE4_2__ #ifdef __SSE4_2__
#include <nmmintrin.h> #include <nmmintrin.h>
#endif #endif
#include <stdint.h>
#include "util/coding.h" #include "util/coding.h"
namespace leveldb { namespace leveldb {
@ -290,6 +290,58 @@ static inline uint64_t LE_LOAD64(const uint8_t *p) {
return DecodeFixed64(reinterpret_cast<const char*>(p)); return DecodeFixed64(reinterpret_cast<const char*>(p));
} }
static inline void Slow_CRC32(uint64_t* l, uint8_t const **p) {
uint32_t c = *l ^ LE_LOAD32(*p);
*p += 4;
*l = table3_[c & 0xff] ^
table2_[(c >> 8) & 0xff] ^
table1_[(c >> 16) & 0xff] ^
table0_[c >> 24];
// DO it twice.
c = *l ^ LE_LOAD32(*p);
*p += 4;
*l = table3_[c & 0xff] ^
table2_[(c >> 8) & 0xff] ^
table1_[(c >> 16) & 0xff] ^
table0_[c >> 24];
}
static inline void Fast_CRC32(uint64_t* l, uint8_t const **p) {
#ifdef __SSE4_2__
*l = _mm_crc32_u64(*l, LE_LOAD64(*p));
*p += 8;
#else
Slow_CRC32(l, p);
#endif
}
// Detect if SS42 or not.
static bool isSSE42() {
#ifdef __GNUC__
uint32_t c_;
uint32_t d_;
__asm__("cpuid" : "=c"(c_), "=d"(d_) : "a"(1) : "ebx");
return c_ & (1U << 20); // copied from CpuId.h in Folly.
#else
return false;
#endif
}
typedef void (*Function)(uint64_t*, uint8_t const**);
static Function func = NULL;
static inline Function Choose_CRC32() {
return isSSE42() ? Fast_CRC32 : Slow_CRC32;
}
static inline void CRC32(uint64_t* l, uint8_t const **p) {
if (func != NULL) {
return func(l, p);
}
func = Choose_CRC32();
func(l, p);
}
uint32_t Extend(uint32_t crc, const char* buf, size_t size) { uint32_t Extend(uint32_t crc, const char* buf, size_t size) {
const uint8_t *p = reinterpret_cast<const uint8_t *>(buf); const uint8_t *p = reinterpret_cast<const uint8_t *>(buf);
const uint8_t *e = p + size; const uint8_t *e = p + size;
@ -302,20 +354,7 @@ uint32_t Extend(uint32_t crc, const char* buf, size_t size) {
int c = (l & 0xff) ^ *p++; \ int c = (l & 0xff) ^ *p++; \
l = table0_[c] ^ (l >> 8); \ l = table0_[c] ^ (l >> 8); \
} while (0) } while (0)
#define STEP4 do { \
uint32_t c = l ^ LE_LOAD32(p); \
p += 4; \
l = table3_[c & 0xff] ^ \
table2_[(c >> 8) & 0xff] ^ \
table1_[(c >> 16) & 0xff] ^ \
table0_[c >> 24]; \
} while (0)
#ifdef __SSE4_2__
#define STEP8 do { l = _mm_crc32_u64(l, LE_LOAD64(p)); p += 8; } while(0)
#else
#define STEP8 do { STEP4; STEP4; } while(0)
#endif
// Point x at first 16-byte aligned byte in string. This might be // Point x at first 16-byte aligned byte in string. This might be
// just past the end of the string. // just past the end of the string.
@ -329,18 +368,17 @@ uint32_t Extend(uint32_t crc, const char* buf, size_t size) {
} }
// Process bytes 16 at a time // Process bytes 16 at a time
while ((e-p) >= 16) { while ((e-p) >= 16) {
STEP8; STEP8; CRC32(&l, &p);
CRC32(&l, &p);
} }
// Process bytes 8 at a time // Process bytes 8 at a time
while ((e-p) >= 8) { while ((e-p) >= 8) {
STEP8; CRC32(&l, &p);
} }
// Process the last few bytes // Process the last few bytes
while (p != e) { while (p != e) {
STEP1; STEP1;
} }
#undef STEP8
#undef STEP4
#undef STEP1 #undef STEP1
#undef ALIGN #undef ALIGN
return l ^ 0xffffffffu; return l ^ 0xffffffffu;

Loading…
Cancel
Save