From 93f503166d068f97ad298a45fe48292fb14c2afa Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 17 Feb 2025 19:35:01 +0100 Subject: [PATCH] apply the `crc` target feature to the acle crc32 implementation --- zlib-rs/src/crc32.rs | 18 +++------- zlib-rs/src/crc32/acle.rs | 72 ++++++--------------------------------- 2 files changed, 15 insertions(+), 75 deletions(-) diff --git a/zlib-rs/src/crc32.rs b/zlib-rs/src/crc32.rs index a936d094..f3990ebd 100644 --- a/zlib-rs/src/crc32.rs +++ b/zlib-rs/src/crc32.rs @@ -52,24 +52,14 @@ impl Crc32Fold { } } - #[cfg_attr(not(target_arch = "x86_64"), allow(unused))] - pub(crate) fn is_pclmulqdq_enabled() -> bool { - crate::cpu_features::is_enabled_pclmulqdq() - } - - #[cfg_attr(not(target_arch = "aarch64"), allow(unused))] - pub(crate) fn is_crc_enabled() -> bool { - crate::cpu_features::is_enabled_crc() - } - pub fn fold(&mut self, src: &[u8], _start: u32) { #[cfg(target_arch = "x86_64")] - if Self::is_pclmulqdq_enabled() { + if crate::cpu_features::is_enabled_pclmulqdq() { return unsafe { self.fold.fold(src, _start) }; } #[cfg(target_arch = "aarch64")] - if Self::is_crc_enabled() { + if crate::cpu_features::is_enabled_crc() { self.value = unsafe { self::acle::crc32_acle_aarch64(self.value, src) }; return; } @@ -80,7 +70,7 @@ impl Crc32Fold { pub fn fold_copy(&mut self, dst: &mut [u8], src: &[u8]) { #[cfg(target_arch = "x86_64")] - if Self::is_pclmulqdq_enabled() { + if crate::cpu_features::is_enabled_pclmulqdq() { return unsafe { self.fold.fold_copy(dst, src) }; } @@ -90,7 +80,7 @@ impl Crc32Fold { pub fn finish(self) -> u32 { #[cfg(target_arch = "x86_64")] - if Self::is_pclmulqdq_enabled() { + if crate::cpu_features::is_enabled_pclmulqdq() { return unsafe { self.fold.finish() }; } diff --git a/zlib-rs/src/crc32/acle.rs b/zlib-rs/src/crc32/acle.rs index 347a6f7a..bf89692c 100644 --- a/zlib-rs/src/crc32/acle.rs +++ b/zlib-rs/src/crc32/acle.rs @@ -3,6 +3,7 @@ //! The functions in this module must only be executed on an ARM system with the CRC feature. #[cfg_attr(not(target_arch = "aarch64"), allow(unused))] +#[target_feature(enable = "crc")] pub unsafe fn crc32_acle_aarch64(crc: u32, buf: &[u8]) -> u32 { let mut c = !crc; @@ -24,29 +25,9 @@ pub unsafe fn crc32_acle_aarch64(crc: u32, buf: &[u8]) -> u32 { !c } -#[cfg_attr(not(target_arch = "arm"), allow(unused))] -pub unsafe fn crc32_acle_arm(crc: u32, buf: &[u8]) -> u32 { - let mut c = !crc; - - // SAFETY: [u8; 4] safely transmutes into u32. - let (before, middle, after) = unsafe { buf.align_to::() }; - - c = remainder(c, before); - - if middle.is_empty() && after.is_empty() { - return !c; - } - - for w in middle { - c = unsafe { __crc32w(c, *w) }; - } - - c = remainder(c, after); - - !c -} - -fn remainder(mut c: u32, mut buf: &[u8]) -> u32 { +#[inline] +#[target_feature(enable = "crc")] +unsafe fn remainder(mut c: u32, mut buf: &[u8]) -> u32 { if let [b0, b1, b2, b3, rest @ ..] = buf { c = unsafe { __crc32w(c, u32::from_le_bytes([*b0, *b1, *b2, *b3])) }; buf = rest; @@ -67,6 +48,9 @@ fn remainder(mut c: u32, mut buf: &[u8]) -> u32 { c } +// FIXME the intrinsics below are stable since rust 1.80.0: remove these and use the standard +// library versions once our MSRV reaches that version. + /// CRC32 single round checksum for bytes (8 bits). /// /// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32b) @@ -115,18 +99,6 @@ unsafe fn __crc32d(mut crc: u32, data: u64) -> u32 { } } -/// CRC32-C single round checksum for words (32 bits). -/// -/// [Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/__crc32cw) -#[target_feature(enable = "crc")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v8"))] -pub unsafe fn __crc32cw(mut crc: u32, data: u32) -> u32 { - unsafe { - core::arch::asm!("crc32cw {crc:w}, {crc:w}, {data:w}", crc = inout(reg) crc, data = in(reg) data); - crc - } -} - #[cfg(test)] mod tests { use super::*; @@ -142,21 +114,11 @@ mod tests { a == b } - - fn crc32_acle_arm_is_crc32fast(v: Vec, start: u32) -> bool { - let mut h = crc32fast::Hasher::new_with_initial(start); - h.update(&v); - - let a = unsafe { crc32_acle_arm(start, &v) }; - let b = h.finalize(); - - a == b - } } #[test] fn test_crc32b() { - if !crate::crc32::Crc32Fold::is_crc_enabled() { + if !crate::cpu_features::is_enabled_crc() { return; } @@ -168,7 +130,7 @@ mod tests { #[test] fn test_crc32h() { - if !crate::crc32::Crc32Fold::is_crc_enabled() { + if !crate::cpu_features::is_enabled_crc() { return; } @@ -180,7 +142,7 @@ mod tests { #[test] fn test_crc32w() { - if !crate::crc32::Crc32Fold::is_crc_enabled() { + if !crate::cpu_features::is_enabled_crc() { return; } @@ -193,7 +155,7 @@ mod tests { #[test] #[cfg(target_arch = "aarch64")] fn test_crc32d() { - if !crate::crc32::Crc32Fold::is_crc_enabled() { + if !crate::cpu_features::is_enabled_crc() { return; } @@ -202,16 +164,4 @@ mod tests { assert_eq!(__crc32d(0, 18446744073709551615), 1147535477); } } - - #[test] - fn test_crc32cw() { - if !crate::crc32::Crc32Fold::is_crc_enabled() { - return; - } - - unsafe { - assert_eq!(__crc32cw(0, 0), 0); - assert_eq!(__crc32cw(0, 4294967295), 3080238136); - } - } }