Auto merge of #89167 - workingjubilee:use-simd, r=MarkSimulacrum

pub use core::simd;

A portable abstraction over SIMD has been a major pursuit in recent years for several programming languages. In Rust, `std::arch` offers explicit SIMD acceleration via compiler intrinsics, but it does so at the cost of having to individually maintain each and every single such API, and is almost completely `unsafe` to use.  `core::simd` offers safe abstractions that are resolved to the appropriate SIMD instructions by LLVM during compilation, including scalar instructions if that is all that is available.

`core::simd` is enabled by the `#![portable_simd]` nightly feature tracked in https://github.com/rust-lang/rust/issues/86656 and is introduced here by pulling in the https://github.com/rust-lang/portable-simd repository as a subtree. We built the repository out-of-tree to allow faster compilation and a stochastic test suite backed by the proptest crate to verify that different targets, features, and optimizations produce the same result, so that using this library does not introduce any surprises. As these tests are technically non-deterministic, and thus can introduce overly interesting Heisenbugs if included in the rustc CI, they are visible in the commit history of the subtree but do nothing here. Some tests **are** introduced via the documentation, but these use deterministic asserts.

There are multiple unsolved problems with the library at the current moment, including a want for better documentation, technical issues with LLVM scalarizing and lowering to libm, room for improvement for the APIs, and so far I have not added the necessary plumbing for allowing the more experimental or libm-dependent APIs to be used. However, I thought it would be prudent to open this for review in its current condition, as it is both usable and it is likely I am going to learn something else needs to be fixed when bors tries this out.

The major types are
- `core::simd::Simd<T, N>`
- `core::simd::Mask<T, N>`

There is also the `LaneCount` struct, which, together with the SimdElement and SupportedLaneCount traits, limit the implementation's maximum support to vectors we know will actually compile and provide supporting logic for bitmasks. I'm hoping to simplify at least some of these out of the way as the compiler and library evolve.
This commit is contained in:
bors 2021-11-13 02:17:20 +00:00
commit 032dfe4360
89 changed files with 7631 additions and 0 deletions

View file

@ -0,0 +1,21 @@
#![crate_type = "rlib"]
#![no_std]
#![feature(portable_simd)]
use core::simd::f32x4;
// For SIMD float ops, the LLIR version which is used to implement the portable
// forms of them may become calls to math.h AKA libm. So, we can't guarantee
// we can compile them for #![no_std] crates.
// Someday we may solve this.
// Until then, this test at least guarantees these functions require std.
fn guarantee_no_std_nolibm_calls() -> f32x4 {
let x = f32x4::from_array([0.1, 0.5, 0.6, -1.5]);
let x2 = x + x;
let _xc = x.ceil(); //~ ERROR E0599
let _xf = x.floor(); //~ ERROR E0599
let _xr = x.round(); //~ ERROR E0599
let _xt = x.trunc(); //~ ERROR E0599
let _xfma = x.mul_add(x, x); //~ ERROR E0599
let _xsqrt = x.sqrt(); //~ ERROR E0599
x2.abs() * x2
}

View file

@ -0,0 +1,39 @@
error[E0599]: no method named `ceil` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:14:17
|
LL | let _xc = x.ceil();
| ^^^^ method not found in `Simd<f32, 4_usize>`
error[E0599]: no method named `floor` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:15:17
|
LL | let _xf = x.floor();
| ^^^^^ method not found in `Simd<f32, 4_usize>`
error[E0599]: no method named `round` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:16:17
|
LL | let _xr = x.round();
| ^^^^^ method not found in `Simd<f32, 4_usize>`
error[E0599]: no method named `trunc` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:17:17
|
LL | let _xt = x.trunc();
| ^^^^^ method not found in `Simd<f32, 4_usize>`
error[E0599]: no method named `mul_add` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:18:19
|
LL | let _xfma = x.mul_add(x, x);
| ^^^^^^^ method not found in `Simd<f32, 4_usize>`
error[E0599]: no method named `sqrt` found for struct `Simd` in the current scope
--> $DIR/libm_no_std_cant_float.rs:19:20
|
LL | let _xsqrt = x.sqrt();
| ^^^^ method not found in `Simd<f32, 4_usize>`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0599`.

View file

@ -0,0 +1,8 @@
// May not matter, since people can use them with a nightly feature.
// However this tests to guarantee they don't leak out via portable_simd,
// and thus don't accidentally get stabilized.
use std::simd::intrinsics; //~ERROR E0603
fn main() {
()
}

View file

@ -0,0 +1,15 @@
error[E0603]: module `intrinsics` is private
--> $DIR/portable-intrinsics-arent-exposed.rs:4:16
|
LL | use std::simd::intrinsics;
| ^^^^^^^^^^ private module
|
note: the module `intrinsics` is defined here
--> $SRC_DIR/core/src/lib.rs:LL:COL
|
LL | pub use crate::core_simd::simd::*;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0603`.

View file

@ -4,6 +4,9 @@ error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
LL | let _: &[i8] = data.into();
| ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
|
= help: the following implementations were found:
<[T; LANES] as From<Simd<T, LANES>>>
<[bool; LANES] as From<Mask<T, LANES>>>
= note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]`
error: aborting due to previous error

View file

@ -60,6 +60,7 @@ fn filter_dirs(path: &Path) -> bool {
"compiler/rustc_codegen_gcc",
"src/llvm-project",
"library/backtrace",
"library/portable-simd",
"library/stdarch",
"src/tools/cargo",
"src/tools/clippy",