Skip to content

Commit 2387ac1

Browse files
authored
crc64ecma_combine_sw() and crc64ecma_combine_auto (alibaba#1118)
1 parent 0db8b00 commit 2387ac1

3 files changed

Lines changed: 66 additions & 4 deletions

File tree

common/checksum/crc.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,13 @@ uint64_t crc64ecma_sw(const uint8_t *buffer, size_t nbytes, uint64_t crc) {
120120
uint64_t crc64ecma_hw_sse128(const uint8_t *buf, size_t len, uint64_t crc);
121121
uint64_t crc64ecma_hw_avx512(const uint8_t *buf, size_t len, uint64_t crc);
122122
uint32_t (*crc32c_auto)(const uint8_t*, size_t, uint32_t) = nullptr;
123-
uint64_t (*crc64ecma_auto)(const uint8_t *data, size_t nbytes, uint64_t crc);
124123
uint32_t (*crc32c_combine_auto)(uint32_t crc1, uint32_t crc2, uint32_t len2);
125124
uint32_t (*crc32c_combine_series_auto)(uint32_t* crc, uint32_t part_size, uint32_t n_parts);
126125
void (*crc32c_series_auto)(const uint8_t *buffer, uint32_t part_size, uint32_t n_parts, uint32_t* crc_parts);
126+
uint64_t (*crc64ecma_auto)(const uint8_t *data, size_t nbytes, uint64_t crc);
127+
uint64_t (*crc64ecma_combine_auto)(uint64_t crc1, uint64_t crc2, uint32_t len2);
128+
uint64_t (*crc64ecma_combine_series_auto)(uint64_t* crc, uint32_t part_size, uint32_t n_parts);
129+
void (*crc64ecma_series_auto)(const uint8_t *buffer, uint32_t part_size, uint32_t n_parts, uint64_t* crc_parts);
127130

128131
__attribute__((constructor))
129132
static void crc_init() {
@@ -157,6 +160,9 @@ static void crc_init() {
157160
tie32 = sw32;
158161
crc64ecma_auto = crc64ecma_sw;
159162
#endif
163+
crc64ecma_combine_auto = (crc64ecma_auto == crc64ecma_sw) ?
164+
crc64ecma_combine_sw :
165+
crc64ecma_combine_hw ;
160166
}
161167

162168
#ifdef __x86_64__
@@ -912,6 +918,33 @@ uint64_t crc64ecma_combine_hw(uint64_t crc1, uint64_t crc2, uint32_t len2) {
912918
return crc1 ^ crc2;
913919
}
914920

921+
inline __uint128_t clmul(uint64_t a, uint64_t b) {
922+
__uint128_t ret = 0;
923+
for (uint32_t i = 0; i < 64; ++i)
924+
if ((a >> i) & 1)
925+
ret ^= (__uint128_t)b << i;
926+
return ret;
927+
}
928+
929+
static uint64_t do_crc64ecma_lshift_sw(uint64_t crc, uint64_t x) {
930+
__uint128_t crc1x = clmul(crc, x);
931+
__uint128_t crc2x = clmul(crc1x, rk[5-1]);
932+
__uint128_t crc3x = crc1x >> 64;
933+
crc1x = crc2x ^ crc3x;
934+
crc2x = clmul(crc1x, rk[7-1]);
935+
crc3x = clmul(crc2x, rk[7]);
936+
return (crc1x >> 64) ^ crc2x ^ (crc3x >> 64);
937+
}
938+
939+
uint64_t crc64ecma_combine_sw(uint64_t crc1, uint64_t crc2, uint32_t len2) {
940+
if (unlikely(!crc1)) return crc2;
941+
if (unlikely(!len2)) return crc1;
942+
if (unlikely(len2 & 31)) {
943+
crc1 = ~crc64ecma_sw(zeros, len2 & 31, ~crc1);
944+
}
945+
crc1 = crc64ecma_lshift_big(crc1, len2, do_crc64ecma_lshift_sw);
946+
return crc1 ^ crc2;
947+
}
915948

916949
#ifdef __x86_64__
917950
#ifdef __clang__

common/checksum/crc64ecma.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,25 @@ inline bool is_crc64ecma_hw_available() {
4242
return crc64ecma_auto != crc64ecma_sw;
4343
}
4444

45+
void crc64ecma_series_sw(const uint8_t *buffer, uint32_t part_size, uint32_t n_parts, uint64_t* crc_parts);
46+
void crc64ecma_series_hw(const uint8_t *buffer, uint32_t part_size, uint32_t n_parts, uint64_t* crc_parts);
47+
inline void crc64ecma_series(const uint8_t *buffer, uint32_t part_size, uint32_t n_parts, uint64_t* crc_parts) {
48+
extern void (*crc64ecma_series_auto)(const uint8_t *buffer, uint32_t part_size, uint32_t n_parts, uint64_t* crc_parts);
49+
crc64ecma_series_auto(buffer, part_size, n_parts, crc_parts);
50+
}
51+
52+
53+
uint64_t crc64ecma_combine_sw(uint64_t crc1, uint64_t crc2, uint32_t len2);
4554
uint64_t crc64ecma_combine_hw(uint64_t crc1, uint64_t crc2, uint32_t len2);
55+
inline uint64_t crc64ecma_combine(uint64_t crc1, uint64_t crc2, uint32_t len2) {
56+
extern uint64_t (*crc64ecma_combine_auto)(uint64_t crc1, uint64_t crc2, uint32_t len2);
57+
return crc64ecma_combine_auto(crc1, crc2, len2);
58+
}
59+
60+
// combine a series of CRC32C values of a fixed part size
61+
uint64_t crc64ecma_combine_series_sw(uint64_t* crc, uint32_t part_size, uint32_t n_parts);
62+
uint64_t crc64ecma_combine_series_hw(uint64_t* crc, uint32_t part_size, uint32_t n_parts);
63+
inline uint32_t crc64ecma_combine_series(uint64_t* crc, uint32_t part_size, uint32_t n_parts) {
64+
extern uint64_t (*crc64ecma_combine_series_auto)(uint64_t* crc, uint32_t part_size, uint32_t n_parts);
65+
return crc64ecma_combine_series_auto(crc, part_size, n_parts);
66+
}

common/checksum/test/test_checksum.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <sstream>
77
#include <string>
88
#include <unistd.h>
9+
#include <photon/common/alog.h>
910
#include "../../../test/ci-tools.h"
1011
#include "../../../test/gtest.h"
1112

@@ -262,7 +263,9 @@ TEST(TestChecksum, crc32_combine) {
262263
}
263264
}
264265

265-
TEST(TestChecksum, crc64_combine) {
266+
void test_crc64_combine(uint64_t (*crc64_combine)(uint64_t crc1,
267+
uint64_t crc2, uint32_t len2), ALogStringL name) {
268+
LOG_INFO(name);
266269
const uint32_t N = 10, M = 510;
267270
unsigned char buf[M * N];
268271
memset(buf, 0, sizeof(buf));
@@ -271,7 +274,7 @@ TEST(TestChecksum, crc64_combine) {
271274
auto y1 = crc64ecma_sw(buf, 8, 0);
272275
EXPECT_EQ(y, crc64ecma_sw(buf+8, 30-8, y1));
273276
auto y2 = crc64ecma_sw(buf+8, 30-8, 0);
274-
EXPECT_EQ(y, crc64ecma_combine_hw(y1, y2, 30-8));
277+
EXPECT_EQ(y, crc64_combine(y1, y2, 30-8));
275278

276279
for (auto& c: buf) c = rand();
277280
auto x = crc64ecma_sw(buf, M * N, 0);
@@ -282,11 +285,16 @@ TEST(TestChecksum, crc64_combine) {
282285
uint32_t L1 = sizeof(buf) - L2;
283286
auto crc1 = crc64ecma_sw(buf, L1, 0);
284287
auto crc2 = crc64ecma_sw(buf + L1, L2, 0);
285-
EXPECT_EQ(x, crc64ecma_combine_hw(crc1, crc2, L2));
288+
EXPECT_EQ(x, crc64_combine(crc1, crc2, L2));
286289
EXPECT_EQ(x, crc64ecma_sw(buf + L1, L2, crc1));
287290
}
288291
}
289292

293+
TEST(TestChecksum, crc64_combine) {
294+
test_crc64_combine(crc64ecma_combine_hw, "hw");
295+
test_crc64_combine(crc64ecma_combine_sw, "sw");
296+
}
297+
290298
TEST(Perf, crc32c_hw_series) {
291299
const uint32_t PART_SIZE = 4096;
292300
static uint32_t crc[1024*1024];

0 commit comments

Comments
 (0)