crc32_hw.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /* Compile with gcc -O3 -msse4.2 ... */
  2. #include <stdint.h>
  3. #ifdef __SSE4_2__
  4. #include <smmintrin.h>
  5. // Byte-boundary alignment issues
  6. #define ALIGN_SIZE 0x08UL
  7. #define ALIGN_MASK (ALIGN_SIZE - 1)
  8. #define CALC_CRC(op, crc, type, buf, len) \
  9. do { \
  10. for (; (len) >= sizeof (type); (len) -= sizeof(type), buf += sizeof (type)) { \
  11. (crc) = op((crc), *(type *) (buf)); \
  12. } \
  13. } while(0)
  14. /* Compute CRC-32C using the Intel hardware instruction. */
  15. /* for better parallelization with bigger buffers see
  16. http://www.drdobbs.com/parallel/fast-parallelized-crc-computation-using/229401411 */
  17. uint32_t crc32c_hw(const void *input, int len, uint32_t crc)
  18. {
  19. const char* buf = (const char*)input;
  20. // XOR the initial CRC with INT_MAX
  21. crc ^= 0xFFFFFFFF;
  22. // Align the input to the word boundary
  23. for (; (len > 0) && ((size_t)buf & ALIGN_MASK); len--, buf++) {
  24. crc = _mm_crc32_u8(crc, *buf);
  25. }
  26. // Blast off the CRC32 calculation
  27. #ifdef __x86_64__
  28. CALC_CRC(_mm_crc32_u64, crc, uint64_t, buf, len);
  29. #endif
  30. CALC_CRC(_mm_crc32_u32, crc, uint32_t, buf, len);
  31. CALC_CRC(_mm_crc32_u16, crc, uint16_t, buf, len);
  32. CALC_CRC(_mm_crc32_u8, crc, uint8_t, buf, len);
  33. // Post-process the crc
  34. return (crc ^ 0xFFFFFFFF);
  35. }
  36. uint64_t crc64c_hw(const void *input, int len, uint32_t seed)
  37. {
  38. const char* buf = (const char*)input;
  39. uint64_t crc = (uint64_t)seed;
  40. // Align the input to the word boundary
  41. for (; (len > 0) && ((size_t)buf & ALIGN_MASK); len--, buf++) {
  42. crc = _mm_crc32_u8(crc, *buf);
  43. }
  44. // Blast off the CRC32 calculation
  45. #ifdef __x86_64__
  46. CALC_CRC(_mm_crc32_u64, crc, uint64_t, buf, len);
  47. #endif
  48. CALC_CRC(_mm_crc32_u32, crc, uint32_t, buf, len);
  49. CALC_CRC(_mm_crc32_u16, crc, uint16_t, buf, len);
  50. CALC_CRC(_mm_crc32_u8, crc, uint8_t, buf, len);
  51. // Post-process the crc
  52. return crc;
  53. }
  54. #endif