You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Update SIMD documentation with more info on what options exist, which flags to pass, what preprocessors are available, and reword the docs to be more up-to-date with current times.
Copy file name to clipboardExpand all lines: site/source/docs/porting/simd.rst
+69-16Lines changed: 69 additions & 16 deletions
Original file line number
Diff line number
Diff line change
@@ -3,27 +3,72 @@
3
3
.. role:: raw-html(raw)
4
4
:format: html
5
5
6
-
=======================================
7
-
Porting SIMD code targeting WebAssembly
8
-
=======================================
6
+
===========================
7
+
Using SIMD with WebAssembly
8
+
===========================
9
+
10
+
Emscripten supports the `WebAssembly SIMD <https://github.com/webassembly/simd/>`_ feature. There are five different ways to leverage WebAssembly SIMD in your C/C++ programs:
11
+
12
+
# Enable LLVM/Clang SIMD autovectorizer to automatically target WebAssembly SIMD, without requiring changes to C/C++ source code.
13
+
# Write SIMD code using the GCC/Clang SIMD Vector Extensions (__attribute__((vector_size(16))))
14
+
# Write SIMD code using the WebAssembly SIMD intrinsics (wasm_simd128.h)
15
+
# Compile existing SIMD code that uses the x86 SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 or 128-bit subset of the AVX intrinsics (\*mmintrin.h)
16
+
# Compile existing SIMD code that uses the ARM NEON intrinsics (arm_neon.h)
17
+
18
+
These techniques can be freely combined in a single program.
19
+
20
+
To enable any of the five types of SIMD above, pass the WebAssembly-specific -msimd128 flag at compile time. This will also turn on LLVM's autovectorization passes. If that is not desirable, additionally pass flags -fno-vectorize -fno-slp-vectorize to disable the autovectorizer. See `Auto-Vectorization in LLVM <https://llvm.org/docs/Vectorizers.html>`_ for more information.
21
+
22
+
WebAssembly SIMD is supported by
23
+
* Chrome ≥ 91 (May 2021),
24
+
* Firefox ≥ 89 (June 2021),
25
+
* Safari ≥ 16.4 (March 2023) and
26
+
* Node.js ≥ 16.4 (June 2021).
27
+
28
+
See `WebAssembly Roadmap <https://webassembly.org/roadmap/>`_ for details about other VMs.
29
+
30
+
An upcoming `Relaxed SIMD proposal <https://github.com/WebAssembly/relaxed-simd/tree/main/proposals/relaxed-simd>`_ will add more SIMD instructions to WebAssembly.
9
31
10
-
Emscripten supports the `WebAssembly SIMD proposal <https://github.com/webassembly/simd/>`_ when using the WebAssembly LLVM backend. To enable SIMD, pass the -msimd128 flag at compile time. This will also turn on LLVM's autovectorization passes, so no source modifications are necessary to benefit from SIMD.
32
+
================================
33
+
GCC/Clang SIMD Vector Extensions
34
+
================================
11
35
12
-
At the source level, the GCC/Clang `SIMD Vector Extensions <https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html>`_ can be used and will be lowered to WebAssembly SIMD instructions where possible. In addition, there is a portable intrinsics header file that can be used.
36
+
At the source level, the GCC/Clang `SIMD Vector Extensions <https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html>`_ can be used and will be lowered to WebAssembly SIMD instructions where possible.
37
+
38
+
This enables developers to create custom wide vector types via typedefs, and use arithmetic operators (+,-,*,/) on the vectorized types, as well as allow individual lane access via the vector[i] notation. However, the `GCC vector built-in functions <https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html>`_ are not available. Instead, use the WebAssembly SIMD Intrinsics functions below.
39
+
40
+
===========================
41
+
WebAssembly SIMD Intrinsics
42
+
===========================
43
+
44
+
LLVM maintains a WebAssembly SIMD Intrinsics header file that is provided with Emscripten, and adds type definitions for the different supported vector types.
Separate documentation for the intrinsics header is a work in progress, but its usage is straightforward and its source can be found at `wasm_simd128.h <https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/wasm_simd128.h>`_. These intrinsics are under active development in parallel with the SIMD proposal and should not be considered any more stable than the proposal itself. Note that most engines will also require an extra flag to enable SIMD. For example, Node requires `--experimental-wasm-simd`.
61
+
The Wasm SIMD header can be browsed online at `wasm_simd128.h <https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/wasm_simd128.h>`_.
19
62
20
-
WebAssembly SIMD is not supported when using the Fastcomp backend.
63
+
Pass -msimd128 flag at compile time to enable targeting WebAssembly SIMD Intrinsics. C/C++ code can use the built-in preprocessor define __wasm_simd128__ to detect when building with WebAssembly SIMD enabled.
64
+
65
+
Pass -mrelaxed-simd to target WebAssembly Relaxed SIMD Intrinsics. C/C++ code can use the built-in preprocessor define __wasm_relaxed_simd__ to detect when this target is active. At the time of writing, Relaxed SIMD is experimental.
21
66
22
67
======================================
23
68
Limitations and behavioral differences
24
69
======================================
25
70
26
-
When porting native SIMD code, it should be noted that because of portability concerns, the WebAssembly SIMD specification does not expose the full native instruction sets. In particular the following changes exist:
71
+
When porting native SIMD code, it should be noted that because of portability concerns, the WebAssembly SIMD specification does not expose access to all of the native x86/ARM SIMD instructions. In particular the following changes exist:
27
72
28
73
- Emscripten does not support x86 or any other native inline SIMD assembly or building .s assembly files, so all code should be written to use SIMD intrinsic functions or compiler vector extensions.
29
74
@@ -39,14 +84,14 @@ SIMD-related bug reports are tracked in the `Emscripten bug tracker with the lab
39
84
Optimization considerations
40
85
===========================
41
86
42
-
When porting SIMD code to use WebAssembly SIMD, implementors should be aware of semantic differences between the host hardware and WebAssembly semantics; as acknowledged in the WebAssembly design documentation, "`this sometimes will lead to poor performance <https://github.com/WebAssembly/design/blob/master/Portability.md#assumptions-for-efficient-execution>`_." The following list outlines some WebAssembly SIMD instructions to look out for when performance tuning:
87
+
When developing SIMD code to use WebAssembly SIMD, implementors should be aware of semantic differences between the host hardware and WebAssembly semantics; as acknowledged in the WebAssembly design documentation, "`this sometimes will lead to poor performance <https://github.com/WebAssembly/design/blob/master/Portability.md#assumptions-for-efficient-execution>`_." The following list outlines some WebAssembly SIMD instructions to look out for when performance tuning:
43
88
44
89
.. list-table:: WebAssembly SIMD instructions with performance implications
45
90
:widths: 10 10 30
46
91
:header-rows: 1
47
92
48
93
* - WebAssembly SIMD instruction
49
-
- Hardware architecture
94
+
- Arch
50
95
- Considerations
51
96
52
97
* - [i8x16|i16x8|i32x4|i64x2].[shl|shr_s|shr_u]
@@ -86,15 +131,23 @@ When porting SIMD code to use WebAssembly SIMD, implementors should be aware of
86
131
- Included for orthogonality, these instructions have no equivalent x86 instruction and are `emulated with 10 x86 instructions in v8 <https://github.com/v8/v8/blob/b6520eda5eafc3b007a5641b37136dfc9d92f63d/src/compiler/backend/x64/code-generator-x64.cc#L2834-L2858>`_.
Emscripten supports compiling existing codebases that use x86 SSE instructions by passing the `-msimd128` flag, and additionally one of the following:
92
139
93
-
Emscripten supports compiling existing codebases that use x86 SSE by passing the `-msse` directive to the compiler, and including the header `<xmmintrin.h>`.
140
+
* SSE: pass `-msse` and `#include <xmmintrin.h>`. Use `#ifdef __SSE__` to detect if compiler currently enables targeting SSE.
141
+
* SSE2: pass `-msse2` and `#include <emmintrin.h>`. Use `#ifdef __SSE2__` to detect if compiler currently enables targeting SSE2.
142
+
* SSE3: pass `-msse3` and `#include <pmmintrin.h>`. Use `#ifdef __SSE3__` to detect if compiler currently enables targeting SSE3.
143
+
* SSSE3: pass `-mssse3` and `#include <tmmintrin.h>`. Use `#ifdef __SSSE3__` to detect if compiler currently enables targeting SSSE3.
144
+
* SSE4.1: pass `-msse4.1` and `#include <smmintrin.h>`. Use `#ifdef __SSE4_1__` to detect if compiler currently enables targeting SSE4.1.
145
+
* SSE4.2: pass `-msse4.2` and `#include <nmmintrin.h>`. Use `#ifdef __SSE4_2__` to detect if compiler currently enables targeting SSE4.2.
146
+
* AVX: pass `-mavx` and `#include <immintrin.h>`. Use `#ifdef __AVX__` to detect if compiler currently enables targeting AVX.
94
147
95
-
Currently only the SSE1, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, and 128-bit AVX instruction sets are supported.
148
+
Currently only the SSE1, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, and 128-bit AVX instruction sets are supported. Each of these instruction sets add on top of the previous ones, so e.g. when targeting SSE3, the instruction sets SSE1 and SSE2 are also available.
96
149
97
-
The following table highlights the availability and expected performance of different SSE1 intrinsics. Even if you are directly targeting the native Wasm SIMD opcodes via wasm_simd128.h header, this table can be useful for understanding the performance limitations that the Wasm SIMD specification has when running on x86 hardware.
150
+
The following tables highlight the availability and expected performance of different SSE* intrinsics. This can be useful for understanding the performance limitations that the Wasm SIMD specification has when running on x86 hardware.
98
151
99
152
For detailed information on each SSE intrinsic function, visit the excellent `Intel Intrinsics Guide on SSE1 <https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=SSE>`_.
0 commit comments