about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCaleb Zulawski <caleb.zulawski@gmail.com>2023-09-10 17:05:08 -0400
committerGitHub <noreply@github.com>2023-09-10 17:05:08 -0400
commit7ce6ec9d40288937ca5d49e0ebb2444c1e92cee5 (patch)
tree694e19e143ae98ba8b29e1fa1e299c6855402f2d
parentf2ac32f21f33da6b9bfb76f3678b4c987fc1b4d7 (diff)
parent3da60554e59f0e9ffe85c717253dd0c3c681296b (diff)
downloadrust-7ce6ec9d40288937ca5d49e0ebb2444c1e92cee5.tar.gz
rust-7ce6ec9d40288937ca5d49e0ebb2444c1e92cee5.zip
Merge pull request #359 from rust-lang/what-is-portable
Define portability
-rw-r--r--crates/core_simd/src/core_simd_docs.md35
-rw-r--r--crates/core_simd/src/mod.rs3
2 files changed, 37 insertions, 1 deletions
diff --git a/crates/core_simd/src/core_simd_docs.md b/crates/core_simd/src/core_simd_docs.md
index 15e8ed0253e..8acdeb04427 100644
--- a/crates/core_simd/src/core_simd_docs.md
+++ b/crates/core_simd/src/core_simd_docs.md
@@ -2,3 +2,38 @@ Portable SIMD module.
 
 This module offers a portable abstraction for SIMD operations
 that is not bound to any particular hardware architecture.
+
+# What is "portable"?
+
+This module provides a SIMD implementation that is fast and predictable on any target.
+
+### Portable SIMD works on every target
+
+Unlike target-specific SIMD in `std::arch`, portable SIMD compiles for every target.
+In this regard, it is just like "regular" Rust.
+
+### Portable SIMD is consistent between targets
+
+A program using portable SIMD can expect identical behavior on any target.
+In most regards, [`Simd<T, N>`] can be thought of as a parallelized `[T; N]` and operates like a sequence of `T`.
+
+This has one notable exception: a handful of older architectures (e.g. `armv7` and `powerpc`) flush [subnormal](`f32::is_subnormal`) `f32` values to zero.
+On these architectures, subnormal `f32` input values are replaced with zeros, and any operation producing subnormal `f32` values produces zeros instead.
+This doesn't affect most architectures or programs.
+
+### Operations use the best instructions available
+
+Operations provided by this module compile to the best available SIMD instructions.
+
+Portable SIMD is not a low-level vendor library, and operations in portable SIMD _do not_ necessarily map to a single instruction.
+Instead, they map to a reasonable implementation of the operation for the target.
+
+Consistency between targets is not compromised to use faster or fewer instructions.
+In some cases, `std::arch` will provide a faster function that has slightly different behavior than the `std::simd` equivalent.
+For example, [`_mm_min_ps`](`core::arch::x86_64::_mm_min_ps`)[^1] can be slightly faster than [`SimdFloat::simd_min`], but does not conform to the IEEE standard also used by [`f32::min`].
+When necessary, [`Simd<T, N>`] can be converted to the types provided by `std::arch` to make use of target-specific functions.
+
+Many targets simply don't have SIMD, or don't support SIMD for a particular element type.
+In those cases, regular scalar operations are generated instead.
+
+[^1]: `_mm_min_ps(x, y)` is equivalent to `x.simd_lt(y).select(x, y)`
diff --git a/crates/core_simd/src/mod.rs b/crates/core_simd/src/mod.rs
index f9891a3b7c1..dd954b7cc48 100644
--- a/crates/core_simd/src/mod.rs
+++ b/crates/core_simd/src/mod.rs
@@ -21,8 +21,9 @@ mod swizzle_dyn;
 mod vector;
 mod vendor;
 
-#[doc = include_str!("core_simd_docs.md")]
 pub mod simd {
+    #![doc = include_str!("core_simd_docs.md")]
+
     pub mod prelude;
 
     pub(crate) use crate::core_simd::intrinsics;