silk.simd.wasm.
WebAssembly SIMD instructions that the portable silk.simd.simd operations do not express: byte
swizzles, dot products, and saturating narrows.
When to use#
Use this module in kernels such as UTF-8 validation and base64 decoding, where one of these
instructions replaces several portable steps. Use silk.simd.simd for everything else.
Details#
Each function names the instruction it stands for and the feature that instruction needs.
When the build targets wasm32 with that feature, the function compiles to the one
instruction. Otherwise it computes the same lanes with portable code, which is correct on
every target but slower. WebAssembly cannot detect features at run time, so a module built
without simd128 always uses the portable code.
Examples#
Swizzle bytes#
import silk.simd.wasm
import silk.simd.u8x16
pub fn main() -> i32 {
let lanes = u8x16.fromArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
let picked = wasm.swizzle(lanes, u8x16.splat(7))
if u8x16.extract(picked, 9) != 7 || u8x16.extract(wasm.swizzle(lanes, u8x16.splat(99)), 0) != 0 {
return 1
}
return 0
}Import as wasm with import silk.simd.wasm as wasm.
Public declarations: 5.
swizzle#
pub fn swizzle(table: simd<u8, 16>, indices: simd<u8, 16>) -> simd<u8, 16>i8x16.swizzle (simd128): lane i is table[indices[i]], or 0 when indices[i] is 16 or
more.
When the build targets wasm32 with the simd128 feature, it compiles to this one instruction.
Otherwise it computes the same lanes with portable code, which is correct but slower.
WebAssembly cannot detect features at run time.
relaxedSwizzle#
pub fn relaxedSwizzle(table: simd<u8, 16>, indices: simd<u8, 16>) -> simd<u8, 16>i8x16.relaxed_swizzle (relaxed-simd): lane i is table[indices[i]] when indices[i] is
below 16. A lane whose index is 16 or more is unspecified and may differ between engines; the
portable code makes it 0. Use swizzle when such a lane must be 0.
When the build targets wasm32 with the relaxed-simd feature, it compiles to this one
instruction. Otherwise it computes the same lanes with portable code, which is correct but
slower. WebAssembly cannot detect features at run time.
dot#
pub fn dot(left: simd<i16, 8>, right: simd<i16, 8>) -> simd<i32, 4>i32x4.dot_i16x8_s (simd128): each lane of left times that of right, with each adjacent
pair of products summed into one i32 lane. The sum wraps only for four lanes of -32768.
When the build targets wasm32 with the simd128 feature, it compiles to this one instruction.
Otherwise it computes the same lanes with portable code, which is correct but slower.
WebAssembly cannot detect features at run time.
narrowUnsigned#
pub fn narrowUnsigned(left: simd<i16, 8>, right: simd<i16, 8>) -> simd<u8, 16>i8x16.narrow_i16x8_u (simd128): the lanes of left, then of right, each clamped to
0..=255.
When the build targets wasm32 with the simd128 feature, it compiles to this one instruction.
Otherwise it computes the same lanes with portable code, which is correct but slower.
WebAssembly cannot detect features at run time.
narrowSigned#
pub fn narrowSigned(left: simd<i16, 8>, right: simd<i16, 8>) -> simd<i8, 16>i8x16.narrow_i16x8_s (simd128): the lanes of left, then of right, each clamped to the
i8 range.
When the build targets wasm32 with the simd128 feature, it compiles to this one instruction.
Otherwise it computes the same lanes with portable code, which is correct but slower.
WebAssembly cannot detect features at run time.
Category: SIMD.
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, wasm32-wasip1, wasm32-wasip2.