remove pesky fun ptr from CRC32 computation

This commit is contained in:
Dennis Luxen 2014-03-17 11:07:01 +01:00
parent 9483b781e2
commit 52b859b3e6

View File

@ -52,13 +52,13 @@ private:
typedef typename ContainerT::iterator IteratorType; typedef typename ContainerT::iterator IteratorType;
unsigned crc; unsigned crc;
typedef unsigned (IteratorbasedCRC32::*CRC32CFunctionPtr)(char *str, unsigned len, unsigned crc); bool use_SSE42_CRC_function;
CRC32CFunctionPtr crc_function;
#if !defined(__x86_64__) #if !defined(__x86_64__)
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor; boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> CRC32_processor;
#endif #endif
unsigned SoftwareBasedCRC32(char *str, unsigned len, unsigned ){ unsigned SoftwareBasedCRC32( char *str, unsigned len )
{
#if !defined(__x86_64__) #if !defined(__x86_64__)
CRC32_processor.process_bytes( str, len); CRC32_processor.process_bytes( str, len);
return CRC32_processor.checksum(); return CRC32_processor.checksum();
@ -68,7 +68,8 @@ private:
} }
// adapted from http://byteworm.com/2010/10/13/crc32/ // adapted from http://byteworm.com/2010/10/13/crc32/
unsigned SSE42BasedCRC32( char *str, unsigned len, unsigned){ unsigned SSE42BasedCRC32( char *str, unsigned len )
{
#if defined(__x86_64__) #if defined(__x86_64__)
unsigned q = len/sizeof(unsigned); unsigned q = len/sizeof(unsigned);
unsigned r = len%sizeof(unsigned); unsigned r = len%sizeof(unsigned);
@ -97,36 +98,47 @@ private:
return crc; return crc;
} }
inline unsigned cpuid() const { inline unsigned cpuid() const
{
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0; unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl. // on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
__get_cpuid( 1, &eax, &ebx, &ecx, &edx ); __get_cpuid( 1, &eax, &ebx, &ecx, &edx );
return ecx; return ecx;
} }
CRC32CFunctionPtr DetectNativeCRC32Support(){ bool DetectNativeCRC32Support()
{
static const int SSE42_BIT = 0x00100000; static const int SSE42_BIT = 0x00100000;
const unsigned ecx = cpuid(); const unsigned ecx = cpuid();
const bool has_SSE42 = ecx & SSE42_BIT; const bool has_SSE42 = ecx & SSE42_BIT;
if (has_SSE42) { if (has_SSE42) {
SimpleLogger().Write() << "using hardware based CRC32 computation"; SimpleLogger().Write() << "using hardware based CRC32 computation";
return &IteratorbasedCRC32::SSE42BasedCRC32; //crc32 hardware accelarated;
} else { } else {
SimpleLogger().Write() << "using software based CRC32 computation"; SimpleLogger().Write() << "using software based CRC32 computation";
return &IteratorbasedCRC32::SoftwareBasedCRC32; //crc32cSlicingBy8;
} }
return has_SSE42;
} }
public: public:
IteratorbasedCRC32(): crc(0) { IteratorbasedCRC32() : crc(0)
crc_function = DetectNativeCRC32Support(); {
use_SSE42_CRC_function = DetectNativeCRC32Support();
} }
unsigned operator()( IteratorType iter, const IteratorType end) { unsigned operator()( IteratorType iter, const IteratorType end )
{
unsigned crc = 0; unsigned crc = 0;
while(iter != end) { while(iter != end) {
char * data = reinterpret_cast<char*>(&(*iter) ); char * data = reinterpret_cast<char*>(&(*iter) );
crc =((*this).*(crc_function))(data, sizeof(typename ContainerT::value_type), crc);
if (use_SSE42_CRC_function)
{
crc = SSE42BasedCRC32( data, sizeof(typename ContainerT::value_type) );
}
else
{
crc = SoftwareBasedCRC32( data, sizeof(typename ContainerT::value_type) );
}
++iter; ++iter;
} }
return crc; return crc;