From 322b2f5e70115a8f11cefb010c12e1bb7234bd1e Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Wed, 20 Mar 2024 00:50:22 +0100 Subject: [PATCH 1/5] NEON support for aarch64 --- src/block/mod.rs | 6 +++ src/block/neon.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/block/neon.rs diff --git a/src/block/mod.rs b/src/block/mod.rs index be64af9..ee71f7c 100644 --- a/src/block/mod.rs +++ b/src/block/mod.rs @@ -11,6 +11,7 @@ mod default; not(target_arch = "wasm32"), not(target_feature = "sse2"), not(target_feature = "avx2"), + not(target_feature = "neon"), ))] pub use self::default::*; @@ -32,6 +33,11 @@ mod avx2; #[cfg(all(not(target_arch = "wasm32"), target_feature = "avx2",))] pub use self::avx2::*; +#[cfg(all(not(target_arch = "wasm32"), target_feature = "neon",))] +mod neon; +#[cfg(all(not(target_arch = "wasm32"), target_feature = "neon",))] +pub use self::neon::*; + #[cfg(target_arch = "wasm32")] mod wasm32; #[cfg(target_arch = "wasm32")] diff --git a/src/block/neon.rs b/src/block/neon.rs new file mode 100644 index 0000000..538ec70 --- /dev/null +++ b/src/block/neon.rs @@ -0,0 +1,108 @@ +#[cfg(target_arch = "aarch64")] +use core::arch::aarch64::*; +use core::{ + cmp::Ordering, + hash::{Hash, Hasher}, + iter::Iterator, + ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not}, +}; + +#[derive(Copy, Clone, Debug)] +#[repr(transparent)] +pub struct Block(pub uint8x16_t); + +impl Block { + pub const USIZE_COUNT: usize = core::mem::size_of::() / core::mem::size_of::(); + pub const NONE: Self = Self::from_usize_array([0; Self::USIZE_COUNT]); + pub const ALL: Self = Self::from_usize_array([core::usize::MAX; Self::USIZE_COUNT]); + pub const BITS: usize = core::mem::size_of::() * 8; + + #[inline] + pub fn into_usize_array(self) -> [usize; Self::USIZE_COUNT] { + unsafe { core::mem::transmute(self.0) } + } + + #[inline] + pub const fn from_usize_array(array: [usize; Self::USIZE_COUNT]) -> Self { + Self(unsafe { core::mem::transmute(array) }) + } + + #[inline] + pub fn is_empty(self) -> bool { + unsafe { vmaxvq_u8(self.0) == 0 } + } + + #[inline] + pub fn andnot(self, other: Self) -> Self { + Self(unsafe { vbicq_u8(self.0, other.0) }) + } +} + +impl Not for Block { + type Output = Block; + #[inline] + fn not(self) -> Self::Output { + Self(unsafe { vmvnq_u8(self.0) }) + } +} + +impl BitAnd for Block { + type Output = Block; + #[inline] + fn bitand(self, other: Self) -> Self::Output { + Self(unsafe { vandq_u8(self.0, other.0) }) + } +} + +impl BitAndAssign for Block { + #[inline] + fn bitand_assign(&mut self, other: Self) { + unsafe { + self.0 = vandq_u8(self.0, other.0); + } + } +} + +impl BitOr for Block { + type Output = Block; + #[inline] + fn bitor(self, other: Self) -> Self::Output { + Self(unsafe { vorrq_u8(self.0, other.0) }) + } +} + +impl BitOrAssign for Block { + #[inline] + fn bitor_assign(&mut self, other: Self) { + unsafe { + self.0 = vorrq_u8(self.0, other.0); + } + } +} + +impl BitXor for Block { + type Output = Block; + #[inline] + fn bitxor(self, other: Self) -> Self::Output { + Self(unsafe { veorq_u8(self.0, other.0) }) + } +} + +impl BitXorAssign for Block { + #[inline] + fn bitxor_assign(&mut self, other: Self) { + unsafe { + self.0 = veorq_u8(self.0, other.0); + } + } +} + +impl PartialEq for Block { + #[inline] + fn eq(&self, other: &Self) -> bool { + unsafe { + let eq = vceqq_u8(self.0, other.0); + vminvq_u8(eq) == 0xff + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 8b87ff3..bea4cb8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,7 @@ //! When SIMD is not available on the target, the crate will gracefully fallback to a default implementation. It is intended to add support for other SIMD architectures //! once they appear in stable Rust. //! -//! Currently only SSE2/AVX2 on x86/x86_64 and wasm32 SIMD are supported as this is what stable Rust supports. +//! Currently only SSE2/AVX2 on x86/x86_64, NEON on aarch64, and wasm32 SIMD are supported as this is what stable Rust supports. #![no_std] #![deny(clippy::undocumented_unsafe_blocks)] From a75c1f906645bacba4b90f50f34e06b004567c62 Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Wed, 20 Mar 2024 01:03:36 +0100 Subject: [PATCH 2/5] Try to add macos-14 runner --- .github/workflows/rust.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 09e45a3..0f8e46f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -33,7 +33,7 @@ jobs: cargo test --verbose --features "$FEATURES" && cargo test --verbose --release --features "$FEATURES" - build_aarch64: + build_aarch64_ubuntu: runs-on: ubuntu-latest strategy: matrix: @@ -47,6 +47,27 @@ jobs: - name: Tests (aarch64) run: cargo check --target aarch64-unknown-linux-gnu + build_aarch64_darwin: + runs-on: macos-14 + strategy: + matrix: + rust: [1.56.0, stable, nightly] + features: ["+neon"] + env: + RUSTFLAGS: "-C target-feature=${{matrix.features}}" + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + target: aarch64-apple-darwin + toolchain: ${{ matrix.rust }} + - name: Tests (arm64) + run: | + cargo test -v --no-default-features --tests --lib && + cargo build --verbose --features "$FEATURES" && + cargo test --verbose --features "$FEATURES" && + cargo test --verbose --release --features "$FEATURES" + # Use clippy to lint for code smells clippy: runs-on: ubuntu-latest From c3a99b3b98490c459a1ff5882d7067541019b0a7 Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Wed, 20 Mar 2024 01:07:57 +0100 Subject: [PATCH 3/5] Replace ubuntu job with macos job --- .github/workflows/rust.yml | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0f8e46f..0c8775d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -33,21 +33,7 @@ jobs: cargo test --verbose --features "$FEATURES" && cargo test --verbose --release --features "$FEATURES" - build_aarch64_ubuntu: - runs-on: ubuntu-latest - strategy: - matrix: - rust: [1.56.0, stable, nightly] - steps: - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - with: - target: aarch64-unknown-linux-gnu - toolchain: ${{ matrix.rust }} - - name: Tests (aarch64) - run: cargo check --target aarch64-unknown-linux-gnu - - build_aarch64_darwin: + build_aarch64: runs-on: macos-14 strategy: matrix: @@ -61,7 +47,7 @@ jobs: with: target: aarch64-apple-darwin toolchain: ${{ matrix.rust }} - - name: Tests (arm64) + - name: Tests (aarch64) run: | cargo test -v --no-default-features --tests --lib && cargo build --verbose --features "$FEATURES" && From 609a39c89c72eeb7fd2f51d6debf88e34f29285a Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Wed, 20 Mar 2024 01:18:27 +0100 Subject: [PATCH 4/5] Ensure default module is hidden if neon is enabled --- src/block/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/block/mod.rs b/src/block/mod.rs index ee71f7c..ac7585b 100644 --- a/src/block/mod.rs +++ b/src/block/mod.rs @@ -5,6 +5,7 @@ use core::hash::{Hash, Hasher}; not(target_arch = "wasm32"), not(target_feature = "sse2"), not(target_feature = "avx2"), + not(target_feature = "neon"), ))] mod default; #[cfg(all( From 428e553d08a11b8a50f64a2d4b1399a3c28b2436 Mon Sep 17 00:00:00 2001 From: Martin Svanberg Date: Wed, 20 Mar 2024 01:21:23 +0100 Subject: [PATCH 5/5] Bump MSRV to 1.59 --- .github/workflows/rust.yml | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0c8775d..e1e80d8 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - rust: [1.56.0, stable, nightly] + rust: [1.59.0, stable, nightly] features: ["+avx2", "+sse2"] env: RUSTFLAGS: "-C target-feature=${{matrix.features}}" @@ -37,7 +37,7 @@ jobs: runs-on: macos-14 strategy: matrix: - rust: [1.56.0, stable, nightly] + rust: [1.59.0, stable, nightly] features: ["+neon"] env: RUSTFLAGS: "-C target-feature=${{matrix.features}}" diff --git a/Cargo.toml b/Cargo.toml index 8f782d8..06bd2d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.5.4" authors = ["bluss"] license = "MIT OR Apache-2.0" readme = "README.md" -rust-version = "1.56" +rust-version = "1.59" edition = "2021" description = "FixedBitSet is a simple bitset collection"