Working through giving example documentation to every Simd function.
The major change in this patch is using doc macros to generate
type-specific examples for each function, using a visually-apparent type
constructor. This makes it feel nicer to have twelve separate
documentation entries for reduce_product(), for example.
A simpler variant of rust-lang/portable-simd#206.
* Comparisons are moved to `SimdPartialEq`, `SimdPartialOrd`, and `SimdOrd`. The function names are prefixed with `simd_` to disambiguate from the regular `PartialEq` etc functions. With the functions on traits instead of `Simd` directly, shadowing the function names doesn't work very well.
* Floating point `Ord`-like functions are put into a `SimdFloat` trait. The intention is that eventually (some time after this PR) all floating point functions will be moved from `Simd` to `SimdFloat`, and the same goes for future `SimdInt`/`SimdUint` traits.
Sync portable-simd for bitmasks &c.
In the ideal case, where everything works easily and nothing has to be rearranged, it is as simple as:
- `git subtree pull -P library/portable-simd https://github.com/rust-lang/portable-simd - ${branch}`
- write the commit message
- `python x.py test --stage 1` to make sure it runs
- `git push` to your PR-to-rustc branch
If anything borks up this flow, you can fix it with sufficient git wizardry but you are usually better off going back to the source, fixing it, and starting over, before you open the PR.
r? `@calebzulawski`
Another approach that fixesrust-lang/portable-simd#223, as an alternative to rust-lang/portable-simd#238.
This adds the `ToBitMask` trait, which is implemented on a vector for each bitmask type it supports. This includes all unsigned integers with enough bits to contain it. The byte array variant has been separated out for now into rust-lang/portable-simd#246 and still requires `generic_const_exprs`, but the integer variants no longer require it and can make it to nightly.
* Explain unsafe contracts of core::simd
This permeates the module with remarks on safety for pub methods,
layout of the Simd type, correct use of intrinsics, et cetera.
This is mostly to help others curious about how core::simd works,
including other Rust contributors, `unsafe` library authors,
and eventually ourselves.
The way the macro expands, it may sometimes infer
"this is a uint, but doesn't impl Neg???"
Also, I made the "wrong path for intrinsics" error.
These fixes allow integration into libcore.
impl std::simd::StdFloat
This introduces an extension trait to allow use of floating point methods
that need runtime support. It is *excessively* documented because its mere
existence is quite vexing, as the entire thing constitutes a leakage of
implementation details into user observable space. Eventually the entire
thing will ideally be folded into core and restructured to match the rest
of the library, whatever that structure might look like at the time. This
is preferred in lieu of the "lang item" path because any energy the lang
items require (and it will be significant, by Simulacrum's estimation) is
better spent on implementing our libmvec.
Refactor ops.rs with wrapping shifts
This approaches reducing macro nesting in a slightly different way. Instead of just flattening details, make one macro apply another. This allows specifying all details up-front in the first macro invocation, making it easier to audit and refactor in the future.
This refactor also has some functional changes. Only one is a true behavior change, however:
- The visible one is that SIMD shifts are now wrapping, not panicking on overflow
- `core::simd` now has a lot more instances of `#[must_use]`, which merely lints
- div/rem now perform a SIMD check but remain as before, which should improve performance but be invisible
This approaches reducing macro nesting in a slightly different way.
Instead of just flattening details, make one macro apply another.
This allows specifying all details up-front in the first macro
invocation, making it easier to audit and refactor in the future.
For all other operators, we use wrapping logic where applicable.
This is another case it applies. Per rust-lang/rust#91237, we may
wish to specify this as the natural behavior of `simd_{shl,shr}`.
Generic `core::ops` for `Simd<T, _>`
In order to maintain type soundness, we need to be sure we only implement an operation for `Simd<T, _> where T: SimdElement`... and also valid for that operation in general. While we could do this purely parametrically, it is more sound to implement the operators directly for the base scalar type arguments and then use type parameters to extend the operators to the "higher order" operations.
This implements that strategy and cleans up `simd::ops` into a few submodules:
- assign.rs: `core::ops::*Assign`
- deref.rs: `core::ops` impls which "deref" borrowed versions of the arguments
- unary.rs: encloses the logic for unary operators on `Simd`, as unary ops are much simpler
This is possible since everything need not be nested in a single maze of macros anymore. The result simplifies the logic and allows reasoning about what operators are valid based on the expressed trait bounds, and also reduces the size of the trait implementation output in rustdoc, for a huge win of 4 MB off the size of `struct.Simd.html`! This addresses a common user complaint, as the original was over 5.5 MB and capable of crashing browsers!
This also carries a fix for a type-inference-related breakage, by removing the autosplatting (vector + scalar binop) impls, as unfortunately the presence of autosplatting was capable of busting type inference. We will likely need to see results from a Crater run before we can understand how to re-land autosplatting.
Unfortunately, splatting impls currently break several crates.
Rust needs more time to review possible mitigations, so
drop the impls for the `impl Add<T> for Simd<T, _>` pattern, for now.
In order to assure type soundness, these "base" impls
need to go directly on Simd<T, _> for every scalar type argument.
A bit of cleanup of ops.rs is still warranted.
Resolves my comment in #197, at least for now; #187 is pending but since these are already here, just commented, it seemed to make sense to me to re-enable them anyway.
Instead of implementing {Op}Assign traits for individual scalar type args
to Simd<_, _>, use parametric impls that reassert the bounds of the binary op.
Instead of implementing each "deref" pattern for every single scalar,
we can use type parameters for Simd operating on &Self.
We can use a macro, but keep it cleaner and more explicit.
* add `Simd::from_slice`
uses a zeroed initial array and loops so that it can be const.
unfortunately, parameterizing the assert with slice length
needs `#![feature(const_fn_fn_ptr_basics)]` to work.
This changes simd_swizzle! to a decl_macro to give it a path,
so it can be imported using a path and not the crate root.
It also adds various uses that were missed and adjusts paths.
This unsafe variant allows the thinnest API, in case LLVM cannot
perform loop-invariant code motion on a hot loop when the safe
form is used.
An unchecked variant could be added to other forms, but doesn't
seem likely to improve anything, since it would just add heavier
codegen.
Aligns module with rust-lang/library/core, creating an... unusual
architecture that is easier to pull in as a module, as core itself can
have no dependencies (as we haven't built core yet).
Add SimdArray trait and safe gather/scatter API (rust-lang/stdsimd#139)
This PR has four parts, without which it doesn't make a lot of sense:
- The introduction of the SimdArray trait for abstraction over vectors.
- The implementation of private vector-of-pointers types.
- Using these to allow constructing vectors with SimdArray::gather_{or, or_default, select}.
- Using these to allow writing vectors using SimdArray::scatter{,_select}.