Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wasm32 SIMD Rust implementation #341

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ default = ["std"]
# implementation uses C intrinsics and requires a C compiler.
neon = []

# The Wasm SIMD implementation does not participate in dynamic feature detection,
# which is currently x86-only. If "wasm_simd" is on, Wasm SIMD support is assumed.
# Note that not all Wasm implementation may support Wasm SIMD specification.
wasm32_simd = []

# This crate uses libstd for std::io trait implementations, and also for
# runtime CPU feature detection. This feature is enabled by default. If you use
# --no-default-features, the only way to use the SIMD implementations in this
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ This repository is the official implementation of BLAKE3. It includes:

* The [`blake3`](https://crates.io/crates/blake3) Rust crate, which
includes optimized implementations for SSE2, SSE4.1, AVX2, AVX-512,
and NEON, with automatic runtime CPU feature detection on x86. The
`rayon` feature provides multithreading.
NEON and Wasm SIMD, with automatic runtime CPU feature detection on x86.
The `rayon` feature provides multithreading.

* The [`b3sum`](https://crates.io/crates/b3sum) Rust crate, which
provides a command line interface. It uses multithreading by default,
Expand Down
20 changes: 20 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ fn is_no_neon() -> bool {
defined("CARGO_FEATURE_NO_NEON")
}

fn is_wasm32_simd() -> bool {
defined("CARGO_FEATURE_WASM32_SIMD")
}

fn is_ci() -> bool {
defined("BLAKE3_CI")
}
Expand Down Expand Up @@ -60,6 +64,11 @@ fn is_armv7() -> bool {
target_components()[0] == "armv7"
}

fn is_wasm32() -> bool {
target_components()[0] == "wasm32"
}


fn endianness() -> String {
let endianness = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap();
assert!(endianness == "little" || endianness == "big");
Expand Down Expand Up @@ -239,6 +248,13 @@ fn build_neon_c_intrinsics() {
build.compile("blake3_neon");
}

fn build_wasm32_simd() {
assert!(is_wasm32());
// No C code to compile here. Set the cfg flags that enable the Wasm SIMD.
// The regular Cargo build will compile it.
println!("cargo:rustc-cfg=blake3_wasm32_simd");
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
if is_pure() && is_neon() {
panic!("It doesn't make sense to enable both \"pure\" and \"neon\".");
Expand Down Expand Up @@ -278,6 +294,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
build_neon_c_intrinsics();
}

if is_wasm32() && is_wasm32_simd() {
build_wasm32_simd();
}

// The `cc` crate doesn't automatically emit rerun-if directives for the
// environment variables it supports, in particular for $CC. We expect to
// do a lot of benchmarking across different compilers, so we explicitly
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ mod sse41;
#[path = "ffi_sse41.rs"]
mod sse41;

#[cfg(blake3_wasm32_simd)]
#[path = "wasm32_simd.rs"]
mod wasm32_simd;

#[cfg(feature = "traits-preview")]
pub mod traits;

Expand Down
41 changes: 41 additions & 0 deletions src/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ cfg_if::cfg_if! {
}
} else if #[cfg(blake3_neon)] {
pub const MAX_SIMD_DEGREE: usize = 4;
} else if #[cfg(blake3_wasm32_simd)] {
pub const MAX_SIMD_DEGREE: usize = 4;
} else {
pub const MAX_SIMD_DEGREE: usize = 1;
}
Expand All @@ -32,6 +34,8 @@ cfg_if::cfg_if! {
}
} else if #[cfg(blake3_neon)] {
pub const MAX_SIMD_DEGREE_OR_2: usize = 4;
} else if #[cfg(blake3_wasm32_simd)] {
pub const MAX_SIMD_DEGREE_OR_2: usize = 4;
} else {
pub const MAX_SIMD_DEGREE_OR_2: usize = 2;
}
Expand All @@ -51,6 +55,9 @@ pub enum Platform {
AVX512,
#[cfg(blake3_neon)]
NEON,
#[cfg(blake3_wasm32_simd)]
#[allow(non_camel_case_types)]
WASM32_SIMD,
}

impl Platform {
Expand Down Expand Up @@ -80,6 +87,10 @@ impl Platform {
{
return Platform::NEON;
}
#[cfg(blake3_wasm32_simd)]
{
return Platform::WASM32_SIMD;
}
Platform::Portable
}

Expand All @@ -97,6 +108,8 @@ impl Platform {
Platform::AVX512 => 16,
#[cfg(blake3_neon)]
Platform::NEON => 4,
#[cfg(blake3_wasm32_simd)]
Platform::WASM32_SIMD => 4,
};
debug_assert!(degree <= MAX_SIMD_DEGREE);
degree
Expand Down Expand Up @@ -131,6 +144,10 @@ impl Platform {
// No NEON compress_in_place() implementation yet.
#[cfg(blake3_neon)]
Platform::NEON => portable::compress_in_place(cv, block, block_len, counter, flags),
#[cfg(blake3_wasm32_simd)]
Platform::WASM32_SIMD => {
crate::wasm32_simd::compress_in_place(cv, block, block_len, counter, flags)
}
}
}

Expand Down Expand Up @@ -163,6 +180,10 @@ impl Platform {
// No NEON compress_xof() implementation yet.
#[cfg(blake3_neon)]
Platform::NEON => portable::compress_xof(cv, block, block_len, counter, flags),
#[cfg(blake3_wasm32_simd)]
Platform::WASM32_SIMD => {
crate::wasm32_simd::compress_xof(cv, block, block_len, counter, flags)
}
}
}

Expand Down Expand Up @@ -269,6 +290,20 @@ impl Platform {
out,
)
},
// Assumed to be safe if the "wasm32_simd" feature is on.
#[cfg(blake3_wasm32_simd)]
Platform::WASM32_SIMD => unsafe {
crate::wasm32_simd::hash_many(
inputs,
key,
counter,
increment_counter,
flags,
flags_start,
flags_end,
out,
)
},
}
}

Expand Down Expand Up @@ -320,6 +355,12 @@ impl Platform {
// Assumed to be safe if the "neon" feature is on.
Some(Self::NEON)
}

#[cfg(blake3_wasm32_simd)]
pub fn wasm32_simd() -> Option<Self> {
// Assumed to be safe if the "wasm32_simd" feature is on.
Some(Self::WASM32_SIMD)
}
}

// Note that AVX-512 is divided into multiple featuresets, and we use two of
Expand Down