Check sse2neon licensing
mastersse2neon is freely redistributable under the MIT License.repository·master·Indexed 23 days ago
https://github.com/dltcollab/sse2neonA header-only C/C++ library that provides an emulation layer for x86 SSE intrinsics on Arm/Aarch64 architectures. It translates Intel SSE intrinsics (including MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, and AES) to Arm NEON intrinsics, allowing developers to port x86-optimized SIMD codebases to Arm platforms with minimal changes. The library supports precision configuration via compile-time macros and provides performance tiering analysis for AArch64.
sse2neon is freely redistributable under the MIT License.sse2neon is a C/C++ header file that translates Intel SSE intrinsics to Arm NEON intrinsics. This allows you to port x86 SIMD code to Arm platforms by replacing standard Intel headers with sse2neon.h, preserving the original semantics of the code.
Supported extensions include:
<mmintrin.h>)<xmmintrin.h>)<emmintrin.h>)<pmmintrin.h>)<tmmintrin.h>)<smmintrin.h>)<nmmintrin.h>)<wmmintrin.h>)// Before
#include <xmmintrin.h>
#include <emmintrin.h>
// After
#include "sse2neon.h"If sse2neon does not meet your specific requirements, several other projects provide SIMD emulation or mapping for different architectures and languages:
SSE2NEON performance on AArch64 is classified into four tiers based on the complexity of the NEON emulation required for each SSE intrinsic. When porting performance-critical code, identify which tier your intrinsics fall into to estimate overhead.
| Tier | NEON Ops | Estimated Cycles | Description |
|---|---|---|---|
| T1 | 1-2 | 1-3 | Direct NEON mapping, near-native performance |
| T2 | 3-5 | 4-8 | Few NEON operations, slight overhead |
| T3 | 6-10 | 8-15 | Moderate emulation, noticeable overhead |
| T4 | 10+ or special | 15-50+ | Complex/algorithmic, significant overhead |
An intrinsic is promoted to T4 if it meets any of the following:
_mm_shuffle_epi8)._mm_crc32_u16 without hardware CRC support).scripts/analyze-tiers.py to perform detailed analysis of how SSE intrinsics map to NEON instructions on AArch64. This tool helps identify the complexity of different intrinsic implementations.The perf-tier.md report is automatically generated. If you need to update the report, run the generation script using Python 3.
python3 scripts/gen-perf-report.py > perf-tier.md| Compiler | Minimum Version | Notes |
|---|---|---|
| GCC | 10+ | Earlier versions have vector instruction bugs |
| Clang | 11+ | Earlier versions have vector instruction bugs |
| MSVC | 2019+ (v142) | ARM64 and ARM64EC targets supported |
| Apple Clang | 12+ | macOS ARM64 (Apple Silicon) |
When using MSVC with the _M_ARM64EC target, sse2neon.h automatically skips <intrin.h> to avoid type conflicts. Note that sse2neon's __m128 type is not ABI-compatible with x64 code; use MSVC's softintrin if you require cross-ABI SIMD interop.
You can run the included tests using make.
Basic test run:
make checkTesting with specific features (e.g., crypto and CRC):
make FEATURE=crypto+crc checkTesting for a specific CPU target:
make ARCH_CFLAGS="-mcpu=cortex-a53 -mfpu=neon-vfpv4" checkCross-compilation testing (requires QEMU):
# ARMv8-A AArch64
make CROSS_COMPILE=aarch64-linux-gnu- check
# ARMv7-A
make CROSS_COMPILE=arm-linux-gnueabihf- check
# ARMv8-A AArch32
make CROSS_COMPILE=arm-linux-gnueabihf- ARCH_CFLAGS="-mcpu=cortex-a32 -mfpu=neon-fp-armv8" checkBy default, sse2neon prioritizes performance, which may lead to differences in IEEE-754 handling (e.g., NaNs and denormals) compared to native SSE. To achieve higher precision and closer compatibility with x86, define the following macros as 1 before including sse2neon.h:
| Macro | Effect |
|---|---|
SSE2NEON_PRECISE_MINMAX | Correct NaN handling in _mm_min_{ps,pd} and _mm_max_{ps,pd} |
SSE2NEON_PRECISE_DIV | Extra Newton-Raphson iteration for _mm_rcp_ps and _mm_div_ps |
SSE2NEON_PRECISE_SQRT | Extra Newton-Raphson iteration for _mm_sqrt_ps and _mm_rsqrt_ps |
SSE2NEON_PRECISE_DP | Conditional multiplication in _mm_dp_pd |
SSE2NEON_UNDEFINED_ZERO | Force zero for _mm_undefined_{ps,pd,si128} |
Recommended configurations by use case:
MINMAX, SQRT (and DIV if using rcp)MINMAX, SQRT, DPMINMAX (prevents NaN propagation)MINMAX (for determinism)#define SSE2NEON_PRECISE_MINMAX 1
#define SSE2NEON_PRECISE_SQRT 1
#include "sse2neon.h"Since ARM lacks a direct userspace equivalent for x86 address-range monitoring, _mm_monitor is a no-op. The behavior of _mm_mwait is controlled by the SSE2NEON_MWAIT_POLICY macro:
| Value | Behavior |
|---|---|
0 (default) | yield - Safe everywhere, never blocks |
1 | wfe - Event wait, may trap in EL0 |
2 | wfi - Interrupt wait, may trap in EL0 |
Note: Policies 1 and 2 do not provide "wake on store" semantics and may cause traps on Linux, iOS, or macOS.
Tier 1 (T1) intrinsics map directly to single NEON instructions and offer near-native performance. Examples include:
_mm_abs_epi16, _mm_abs_epi32, _mm_abs_epi8, _mm_abs_pi16, _mm_abs_pi32, _mm_abs_pi8, _mm_add_epi16, _mm_add_epi32, etc._mm_cmpeq_epi16, _mm_cmpeq_epi32, _mm_cmpeq_epi64, _mm_cmpeq_epi8, _mm_cmpeq_pd, _mm_cmpeq_ps, _mm_cmpgt_epi16, _mm_cmpgt_epi32, etc._mm_and_pd, _mm_and_ps, _mm_and_si128, _mm_andnot_pd, _mm_andnot_ps, _mm_andnot_si128, _mm_floor_pd, _mm_floor_ps, etc._mm_load1_pd, _mm_load1_ps, _mm_load_pd, _mm_load_ps, _mm_load_si128, _mm_loadu_ps, _mm_loadu_si128, _mm_set1_epi16, etc._mm_cvt_ps2pi, _mm_cvt_si2ss, _mm_cvt_ss2si, _mm_cvtepi32_ps, _mm_cvtps_epi32, _mm_cvtps_pi16, _mm_cvtsd_f64, _mm_cvtsd_si32, etc._mm_ceil_pd, _mm_ceil_ps, _mm_floor_pd, _mm_floor_ps, _mm_max_epi16, _mm_max_epi32, _mm_max_epi8, _mm_max_epu16, etc.When working with SIMD intrinsics, the following resources are recommended for technical accuracy and implementation guidance:
sse2neon header file for Windows on Arm development.