rust-lang / rust-lang/portable-simd

`wasm32-unknown-unknown` doesn't use simd instructions (at least, for one particular example, but plausibly more)

Open
#320 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
1.1k
Forks
108
Avg merge
22h 53m
Merged PRs (30d)
3

Description

Godbolt link: https://godbolt.org/z/KEsaM8sbh.

This function is fully scalarized to bytes under --target=wasm32-unknown-unknown -Ctarget-features=+simd128:

pub fn all_ascii_simd_std(s: &[u8; 32]) -> bool {
    use core::simd::*;
    const ALL_HI: u8x32 = u8x32::from_array([0x80; 32]);
    const ZERO: u8x32 = u8x32::from_array([0; 32]);
    (u8x32::from_array(*s) & ALL_HI).simd_eq(ZERO).all()
}

I tried:

  • Adding #[target_feature(enable = "simd128")] to it, which does not help.
  • Rewriting it to 2 vectors of native width (e.g. [u8x16; 2]), which also does not help (this is also included in the example).
  • Changing it in a couple other ways.

And none of it helped.

This is unfortunate because WebAssembly's SIMD should be pretty efficient here -- u8x16_bitmask already only looks at the high bit, so it can avoid masking with u8x16_splat(0x80). Ideally, I'd get the same thing as:

#[target_feature(enable = "simd128")]
pub fn all_ascii_simd_wasm(s: &[u8; 32]) -> bool {
    use core::arch::wasm32::*;
    let a = unsafe { v128_load(s.as_ptr().cast()) };
    let b = unsafe { v128_load(s.as_ptr().add(16).cast()) };
    u8x16_bitmask(v128_or(a, b)) == 0
}

Or you know, something vectorized? Or even a fallback to usize SWAR? Sadly, we get nothing like that.

It is concerning that the function it does load the vectors, but then goes out of its way to convert them to bytes that the rest of the operations are performed on. This implies to me that none of the operations here are supported, meaning that core::simd doesn't use simd128 on wasm targets at all... Which might mean it's an easy fix (flip a bool somewhere?) or something to report upstream.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Godbolt example linked in the issue and compare the generated code for core::simd on wasm32-unknown-unknown with the explicit core::arch::wasm32 version. Check the listed target features and alternative vector-width examples, then determine whether core::simd operations are unsupported or incorrectly lowered; done means the example produces vectorized output or the limitation is clearly identified.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, wasm
Domain
compilers, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.