diff --git a/CHANGELOG.md b/CHANGELOG.md index 529644dc..4babeeb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,37 +6,54 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe --> -The latest published Fearless SIMD release is [0.6.0](#060-2026-07-10) which was released on 2026-07-10. -You can find its changes [documented below](#060-2026-07-10). +The latest published Fearless SIMD release is [0.7.0](#070-2026-08-11) which was released on 2026-08-11. +You can find its changes [documented below](#070-2026-08-11). ## [Unreleased] +## [0.7.0][] (2026-08-11) + +This release has an [MSRV][] of 1.89. + ### Added -- Added an `Sse2` level. This is the new baseline for i686-* and x86_64-* targets, replacing `Fallback`. ([#270][] by [@Shnatsel][]) -- Added full-vector `swizzle_dyn` and `swizzle_dyn_precise` byte swizzles. `swizzle_dyn` permits implementation-defined results for out-of-range indices, while `swizzle_dyn_precise` always returns zero for them. +- Added `i64x2`, `i64x4`, `i64x8`, `u64x2`, `u64x4`, and `u64x8` vector types, the native-width `i64s` and `u64s` associated types, and 64-bit integer operations across all backends. ([#253][], [#310][] by [@Shnatsel][]) +- Added an `Sse2` level. This is the new baseline for i686-* and x86_64-* targets, replacing `Fallback`. It is detected at runtime on Tier-2 i586-* targets. ([#270][] by [@Shnatsel][]) +- Added `shift_elements_left`, `shift_elements_right`, `rotate_elements_left`, and `rotate_elements_right` to non-mask vectors. Shifts accept a padding element and fill the entire vector when the offset is at least its lane count; rotations wrap the offset. ([#274][] by [@Shnatsel][]) +- Added full-vector `swizzle_dyn` and `swizzle_dyn_precise` byte swizzles. `swizzle_dyn` permits implementation-defined results for out-of-range indices, while `swizzle_dyn_precise` always returns zero for them. ([#276][], [#304][] by [@Shnatsel][]) +- Added the `SimdElement::BITS` constant, exposing the bit width of a vector's lane type to generic code. ([#296][] by [@danderson][]) - Added trait bounds on `SimdElement`, and introduced the `SimdIntElement` and `SimdFloatElement` subtraits. These allow generic code to access many math and utility operations on the elements of SIMD vector types. ([#302][] by [@danderson][]) +- Added the `SimdWiden` and `SimdNarrow` traits, providing widening, narrowing, and saturating narrowing operations for all integer and floating-point vector types. ([#300][] by [@Shnatsel][]) +- The four-way interleaved load and store operations are now exposed on the vector types they operate on and are available to generic code through `SimdInterleaved`. ([#321][] by [@Shnatsel][]) ### Changed -- Breaking change: the `load_interleaved_128_*` and `store_interleaved_128_*` methods, which exchanged one 512-bit vector, have been replaced by `load_four_interleaved_*` and `store_four_interleaved_*`. The new methods exchange an array of four 128-bit vectors directly and are available for all non-mask scalar types. - -- The `new_unchecked()` function on SIMD level tokens such as `Avx2` has been renamed to `assume_supported()` and is now safe to call from contexts that already contain the appropriate `#[target_feature]` annotations. Functions without such annotations can still call `assume_supported()` with an `unsafe` block. ([#293][] by [@Shnatsel][]) +- Breaking change: the `load_interleaved_128_*` and `store_interleaved_128_*` methods, which exchanged one 512-bit vector, have been replaced by `load_four_interleaved_*` and `store_four_interleaved_*`. The new methods exchange an array of four 128-bit vectors directly and are available for all non-mask scalar types. ([#298][] by [@Shnatsel][]) +- Breaking change: the `new_unchecked()` function on SIMD level tokens such as `Avx2` has been renamed to `assume_supported()` and is now safe to call from contexts that already contain the appropriate `#[target_feature]` annotations. Functions without such annotations can still call `assume_supported()` with an `unsafe` block. ([#293][] by [@Shnatsel][]) +- Breaking change: The `fxsr` CPU feature is now required for all x86 SIMD levels. It is present in hardware on all SIMD-capable CPUs, but it is possible to disable it in some emulators combined with a custom Rust target specification. ([#270][] by [@Shnatsel][]) +- Breaking change: Operations shared by integer and floating-point vectors have moved from `SimdInt`/`SimdFloat` to `SimdBase`, so code generic over any non-mask vector can use `Add`, `Sub`, `Mul`, comparisons, zip/unzip, and interleave/deinterleave operations. ([#308][] by [@Shnatsel][]) +- Breaking change: `min`, `max`, `min_precise`, and `max_precise` have moved from `SimdInt`/`SimdFloat` to `SimdBase`, allowing generic code to use them across integer and floating-point vectors. ([#313][] by [@Shnatsel][]) - On x86_64 targets with static SSE2 support, `Level::baseline()` now returns `Sse2` instead of `Fallback`. ([#270][] by [@Shnatsel][]) -- The scalar `Fallback` backend and `Level::Fallback` variant are no longer compiled when the target has a better ambient SIMD baseline (e.g. SSE2 on x86, NEON on Aarch64). The `force_support_fallback` feature continues to make them available for testing. `disable_dispatch_sse2` no longer disables SSE2 if it is the baseline level. -- The `fxsr` CPU feature is now required for all x86 SIMD levels. It is present in hardware on all SIMD-capable CPUs, but it is possible to disable it in some emulators combined with a custom Rust target specification. ([#270][] by [@Shnatsel][]) -- All native-width non-mask vector types now share `u8s` as their byte representation, enabling `Bytes::bitcast` between arbitrary lane types in code generic over `Simd`. The byte representation of any `SimdBase` type is now also guaranteed to be an idempotent, same-token `u8` SIMD vector, so it can be manipulated directly in generic code. -- `SimdBase::Mask` now guarantees support for selecting vectors of its associated `SimdBase` type, enabling mask selection in generic code without additional bounds. -- `SimdElement` now requires `Copy`, enabling elements to be read by value from vectors in generic code without additional bounds. -- `SimdBase::Block` now declares that a 128-bit block is its own block, enabling recursive use in generic code without additional equality bounds. -- `SimdElement::Mask` now declares that a mask lane type is its own mask lane type, exposing this invariant to generic code. -- `SimdCombine` and `SimdSplit` now declare their associated vector types as inverse operations, enabling generic code to recover the original vector type without additional equality bounds. -- `SimdBase::Array` now guarantees `Copy` (and therefore `Clone`), `Debug`, by-value `IntoIterator`, `AsRef`, `AsMut`, and conversion from its vector type, while `SimdBase` guarantees construction from its associated array through `SimdFrom`. -- Breaking change: the 204 vector-specific `Simd` array conversion methods have been replaced by the `SimdBase::load_array`, `load_array_ref`, `as_array`, `as_array_ref`, `as_array_mut`, and `store_array` methods. Masks continue to use `SimdMask::from_slice` and `store_slice`. +- The scalar `Fallback` backend and `Level::Fallback` variant are no longer compiled when the target has a better ambient SIMD baseline (e.g. SSE2 on x86, NEON on Aarch64). The `force_support_fallback` feature continues to make them available for testing. `disable_dispatch_sse2` no longer disables SSE2 if it is the baseline level. ([#320][] by [@Shnatsel][]) +- Runtime CPU feature detection performed by `Level::new()` is now cached on x86. ([#278][] by [@Shnatsel][]) +- The result of integer shifts by an amount greater than or equal to the element width is now explicitly documented as platform-dependent. Scalar fallback shifts use wrapping shift amounts instead of potentially panicking in debug builds. ([#283][] by [@Shnatsel][]) +- Full-vector 8-bit shifts on x86 have been optimized, including a 2.4x faster left-shift formulation and faster signed and unsigned right shifts. ([#291][] by [@Shnatsel][]) +- All native-width non-mask vector types now share `u8s` as their byte representation, enabling `Bytes::bitcast` between arbitrary lane types in code generic over `Simd`. The byte representation of any `SimdBase` type is now also guaranteed to be an idempotent, same-token `u8` SIMD vector, so it can be manipulated directly in generic code. ([#284][] by [@Shnatsel][]) +- Generic bounds now encode existing relationships between masks, vectors, blocks, elements, and split/combined vector types. This enables mask selection, by-value element access, recursive block use, and reversible split/combine operations without additional bounds. ([#285][] by [@Shnatsel][]) +- `SimdBase::Array` now guarantees `Copy` (and therefore `Clone`), `Debug`, by-value `IntoIterator`, `AsRef`, `AsMut`, and conversion from its vector type, while `SimdBase` guarantees construction from its associated array through `SimdFrom`. ([#285][] by [@Shnatsel][]) +- `Simd` and `SimdBase` now require `Debug`, exposing implementations already provided by all tokens and vector types to generic code. ([#309][] by [@Shnatsel][]) +- The `Simd::vectorize` documentation now explains when to use it and includes an end-to-end example. ([#312][] by [@Shnatsel][]) +- Generated code and metadata have been substantially reduced, cutting x86 build time by roughly one third. ([#292][], [#317][], [#318][] by [@Shnatsel][]) ### Removed -- Breaking change: removed the low-level `reinterpret_f32_*`, `reinterpret_f64_*`, `reinterpret_i32_*`, `reinterpret_u32_*`, `reinterpret_u8_*`, `cvt_to_bytes_*`, and `cvt_from_bytes_*` methods. Use `Bytes::bitcast` for arbitrary same-width bit reinterpretation, or `Bytes::to_bytes` and `Bytes::from_bytes` for direct byte-vector conversions. +- Breaking change: removed the low-level `reinterpret_f32_*`, `reinterpret_f64_*`, `reinterpret_i32_*`, `reinterpret_u32_*`, `reinterpret_u8_*`, `cvt_to_bytes_*`, and `cvt_from_bytes_*` methods. Use `Bytes::bitcast` for arbitrary same-width bit reinterpretation, or `Bytes::to_bytes` and `Bytes::from_bytes` for direct byte-vector conversions. ([#284][] by [@Shnatsel][]) +- Breaking change: removed the `WithSimd` trait, which only delegated to the `dispatch!` macro. Use `dispatch!` directly instead. ([#306][] by [@Shnatsel][]) + +### Fixed + +- Integer negation in the scalar fallback now wraps for the minimum signed value, matching the SIMD backends instead of potentially panicking in debug builds. ([#253][] by [@Shnatsel][]) +- Fixed x86 8-bit left shifts: overflowing `u8` lanes now wrap instead of saturating, and `i8` lanes now match Rust's signed shift semantics. ([#288][], [#290][] by [@danderson][]) ## [0.6.0][] (2026-07-10) @@ -292,11 +309,37 @@ No changelog was kept for this release. [#263]: https://github.com/linebender/fearless_simd/pull/263 [#264]: https://github.com/linebender/fearless_simd/pull/264 [#266]: https://github.com/linebender/fearless_simd/pull/266 +[#253]: https://github.com/linebender/fearless_simd/pull/253 [#270]: https://github.com/linebender/fearless_simd/pull/270 +[#274]: https://github.com/linebender/fearless_simd/pull/274 +[#276]: https://github.com/linebender/fearless_simd/pull/276 +[#278]: https://github.com/linebender/fearless_simd/pull/278 +[#283]: https://github.com/linebender/fearless_simd/pull/283 +[#284]: https://github.com/linebender/fearless_simd/pull/284 +[#285]: https://github.com/linebender/fearless_simd/pull/285 +[#288]: https://github.com/linebender/fearless_simd/pull/288 +[#290]: https://github.com/linebender/fearless_simd/pull/290 +[#291]: https://github.com/linebender/fearless_simd/pull/291 +[#292]: https://github.com/linebender/fearless_simd/pull/292 [#293]: https://github.com/linebender/fearless_simd/pull/293 +[#296]: https://github.com/linebender/fearless_simd/pull/296 +[#298]: https://github.com/linebender/fearless_simd/pull/298 +[#300]: https://github.com/linebender/fearless_simd/pull/300 [#302]: https://github.com/linebender/fearless_simd/pull/302 - -[Unreleased]: https://github.com/linebender/fearless_simd/compare/v0.6.0...HEAD +[#304]: https://github.com/linebender/fearless_simd/pull/304 +[#306]: https://github.com/linebender/fearless_simd/pull/306 +[#308]: https://github.com/linebender/fearless_simd/pull/308 +[#309]: https://github.com/linebender/fearless_simd/pull/309 +[#310]: https://github.com/linebender/fearless_simd/pull/310 +[#312]: https://github.com/linebender/fearless_simd/pull/312 +[#313]: https://github.com/linebender/fearless_simd/pull/313 +[#317]: https://github.com/linebender/fearless_simd/pull/317 +[#318]: https://github.com/linebender/fearless_simd/pull/318 +[#320]: https://github.com/linebender/fearless_simd/pull/320 +[#321]: https://github.com/linebender/fearless_simd/pull/321 + +[Unreleased]: https://github.com/linebender/fearless_simd/compare/v0.7.0...HEAD +[0.7.0]: https://github.com/linebender/fearless_simd/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/linebender/fearless_simd/compare/v0.5.0...v0.6.0 [0.5.0]: https://github.com/linebender/fearless_simd/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/linebender/fearless_simd/compare/v0.4.0...v0.4.1 diff --git a/Cargo.lock b/Cargo.lock index 1365e85c..142c3562 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,7 +112,7 @@ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "fearless_simd" -version = "0.6.0" +version = "0.7.0" dependencies = [ "libm", ] diff --git a/fearless_simd/Cargo.toml b/fearless_simd/Cargo.toml index b1aa4f52..ee3fdaad 100644 --- a/fearless_simd/Cargo.toml +++ b/fearless_simd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fearless_simd" -version = "0.6.0" +version = "0.7.0" license.workspace = true edition.workspace = true repository.workspace = true diff --git a/fearless_simd/README.md b/fearless_simd/README.md index 95a0834a..f6d8e2cc 100644 --- a/fearless_simd/README.md +++ b/fearless_simd/README.md @@ -42,7 +42,7 @@ See https://linebender.org/blog/doc-include/ for related discussion. --> No matter what level of abstraction you're after, be it autovectorization and multiversioning, or portable SIMD, or safe access to raw intrinsics and nothing more, `fearless_simd` has you covered! -Zero dependencies, from-scratch build time under 1 second, safe public APIs, and [very little](https://shnatsel.github.io/safe-simd-in-rust-even-on-the-inside/) `unsafe` under the hood. +Zero dependencies, safe public APIs, and [very little](https://shnatsel.github.io/safe-simd-in-rust-even-on-the-inside/) `unsafe` under the hood. ## Automatic vectorization diff --git a/fearless_simd/src/lib.rs b/fearless_simd/src/lib.rs index 2fc71414..eba4ca1d 100644 --- a/fearless_simd/src/lib.rs +++ b/fearless_simd/src/lib.rs @@ -9,7 +9,7 @@ //! No matter what level of abstraction you're after, be it autovectorization and multiversioning, or portable SIMD, or safe access to raw //! intrinsics and nothing more, `fearless_simd` has you covered! //! -//! Zero dependencies, from-scratch build time under 1 second, safe public APIs, and [very little](https://shnatsel.github.io/safe-simd-in-rust-even-on-the-inside/) `unsafe` under the hood. +//! Zero dependencies, safe public APIs, and [very little](https://shnatsel.github.io/safe-simd-in-rust-even-on-the-inside/) `unsafe` under the hood. //! //! # Automatic vectorization //!