Skip to content

Commit 3734387

Browse files
committed
rscrypto: feat(crc32): implement multi-way PCLMUL/VPCLMUL (2/4/7-way
ILP) Add multi-stream PCLMUL kernels for CRC32-IEEE and CRC32C following the CRC64 canonical pattern. Uses 128-byte blocks with multiple independent folding streams to maximize instruction-level parallelism.
1 parent 74ecb14 commit 3734387

2 files changed

Lines changed: 30 additions & 8 deletions

File tree

crates/checksum/src/common/clmul.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ pub(crate) struct Crc32ClmulConstants {
342342
pub fold_128b: (u64, u64),
343343
/// 16B folding coefficient (K_127, K_191) for lane reduction.
344344
pub fold_16b: (u64, u64),
345+
/// Tail fold coefficients (distance 112..16 bytes): (K_{d-1}, K_{d+63}).
346+
/// Used to reduce 8 lanes to 1 lane in multi-way kernels.
347+
pub tail_fold_16b: [(u64, u64); 7],
345348
/// 128→96 bit reduction constant (K_95).
346349
pub k_96: u64,
347350
/// 96→64 bit reduction constant (K_63).
@@ -492,6 +495,17 @@ impl Crc32ClmulConstants {
492495
fold_128b: (fold_k_32(normal, 1023), fold_k_32(normal, 1087)),
493496
// 16B lane: fold by 16 bytes = 128 bits
494497
fold_16b: (fold_k_32(normal, 127), fold_k_32(normal, 191)),
498+
// Tail fold coefficients for reducing 8 lanes to 1 lane.
499+
// Each coefficient shifts lane i by (7-i)*16 bytes to align with lane 7.
500+
tail_fold_16b: [
501+
(fold_k_32(normal, 895), fold_k_32(normal, 959)), // 112 bytes (lane 0)
502+
(fold_k_32(normal, 767), fold_k_32(normal, 831)), // 96 bytes (lane 1)
503+
(fold_k_32(normal, 639), fold_k_32(normal, 703)), // 80 bytes (lane 2)
504+
(fold_k_32(normal, 511), fold_k_32(normal, 575)), // 64 bytes (lane 3)
505+
(fold_k_32(normal, 383), fold_k_32(normal, 447)), // 48 bytes (lane 4)
506+
(fold_k_32(normal, 255), fold_k_32(normal, 319)), // 32 bytes (lane 5)
507+
(fold_k_32(normal, 127), fold_k_32(normal, 191)), // 16 bytes (lane 6)
508+
],
495509
// 128→96 bits: K_95
496510
k_96: fold_k_32(normal, 95),
497511
// 96→64 bits: K_63

crates/checksum/src/crc32/x86_64.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -905,16 +905,24 @@ unsafe fn fold_block_128_32(x: &mut [Simd; 8], chunk: &[Simd; 8], coeff: Simd) {
905905
#[inline]
906906
#[target_feature(enable = "sse2", enable = "pclmulqdq")]
907907
unsafe fn fold_tail_32(x: [Simd; 8], consts: &Crc32ClmulConstants) -> __m128i {
908-
let c = Simd::new(consts.fold_16b.0, consts.fold_16b.1);
908+
// Tail reduction (8×16B → 1×16B), using per-lane coefficients.
909+
// Each lane needs to be shifted by a different amount to align with lane 7.
910+
let c0 = Simd::new(consts.tail_fold_16b[0].0, consts.tail_fold_16b[0].1); // 112 bytes
911+
let c1 = Simd::new(consts.tail_fold_16b[1].0, consts.tail_fold_16b[1].1); // 96 bytes
912+
let c2 = Simd::new(consts.tail_fold_16b[2].0, consts.tail_fold_16b[2].1); // 80 bytes
913+
let c3 = Simd::new(consts.tail_fold_16b[3].0, consts.tail_fold_16b[3].1); // 64 bytes
914+
let c4 = Simd::new(consts.tail_fold_16b[4].0, consts.tail_fold_16b[4].1); // 48 bytes
915+
let c5 = Simd::new(consts.tail_fold_16b[5].0, consts.tail_fold_16b[5].1); // 32 bytes
916+
let c6 = Simd::new(consts.tail_fold_16b[6].0, consts.tail_fold_16b[6].1); // 16 bytes
909917

910918
let mut acc = x[7];
911-
acc ^= x[0].fold_16(c);
912-
acc ^= x[1].fold_16(c);
913-
acc ^= x[2].fold_16(c);
914-
acc ^= x[3].fold_16(c);
915-
acc ^= x[4].fold_16(c);
916-
acc ^= x[5].fold_16(c);
917-
acc ^= x[6].fold_16(c);
919+
acc ^= x[0].fold_16(c0);
920+
acc ^= x[1].fold_16(c1);
921+
acc ^= x[2].fold_16(c2);
922+
acc ^= x[3].fold_16(c3);
923+
acc ^= x[4].fold_16(c4);
924+
acc ^= x[5].fold_16(c5);
925+
acc ^= x[6].fold_16(c6);
918926

919927
acc.0
920928
}

0 commit comments

Comments
 (0)