sse2neon

repository·master·Indexed 23 days ago

https://github.com/dltcollab/sse2neon

A 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.

Tokens
2.2K
Snippets
3
Records
13
Agent score
31%

What's inside sse2neon

  1. Port x86 SSE code to Arm NEON with sse2neon

    master

    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:

    • MMX (<mmintrin.h>)
    • SSE (<xmmintrin.h>)
    • SSE2 (<emmintrin.h>)
    • SSE3 (<pmmintrin.h>)
    • SSSE3 (<tmmintrin.h>)
    • SSE4.1 (<smmintrin.h>)
    • SSE4.2 (<nmmintrin.h>)
    • AES (<wmmintrin.h>)
    // Before
    #include <xmmintrin.h>
    #include <emmintrin.h>
    
    // After
    #include "sse2neon.h"
  2. Explore related SIMD porting projects

    master

    If sse2neon does not meet your specific requirements, several other projects provide SIMD emulation or mapping for different architectures and languages:

    • SIMDe: Fast and portable implementations of SIMD intrinsics on non-native hardware (e.g., SSE on ARM).
    • AvxToNeon: Specifically for converting AVX to NEON.
    • sse2rvv: Converts Intel SSE to RISC-V Vector intrinsics.
    • sse2msa: Converts Intel SSE to MIPS/MIPS64 MSA intrinsics.
    • sse2zig: Maps Intel SSE to Zig vector extensions.
    • ARM_NEON_2_x86_SSE: A project for mapping NEON to x86 SSE.
    • neon_sim: ARM NEON Intrinsics implementation in C.
  3. Understand SSE2NEON performance tiers on AArch64

    master

    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.

    Performance Tiers

    TierNEON OpsEstimated CyclesDescription
    T11-21-3Direct NEON mapping, near-native performance
    T23-54-8Few NEON operations, slight overhead
    T36-108-15Moderate emulation, noticeable overhead
    T410+ or special15-50+Complex/algorithmic, significant overhead

    T4 Classification Criteria

    An intrinsic is promoted to T4 if it meets any of the following:

    • High raw NEON instruction count (10+).
    • Algorithmic complexity (e.g., table lookups like _mm_shuffle_epi8).
    • Pure scalar fallbacks (e.g., _mm_crc32_u16 without hardware CRC support).
    • Loop-based implementations.
    • Mixed scalar+NEON with high effective cost.
  4. Requirements and Compiler Compatibility for sse2neon

    master

    Architecture

    • Little-endian ARM only. Big-endian ARM is not supported and will cause a compile-time error.

    Supported Compilers

    CompilerMinimum VersionNotes
    GCC10+Earlier versions have vector instruction bugs
    Clang11+Earlier versions have vector instruction bugs
    MSVC2019+ (v142)ARM64 and ARM64EC targets supported
    Apple Clang12+macOS ARM64 (Apple Silicon)

    Windows ARM64EC (Hybrid ABI)

    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.

  5. Run the sse2neon built-in test suite

    master

    You can run the included tests using make.

    Basic test run:

    make check

    Testing with specific features (e.g., crypto and CRC):

    make FEATURE=crypto+crc check

    Testing for a specific CPU target:

    make ARCH_CFLAGS="-mcpu=cortex-a53 -mfpu=neon-vfpv4" check

    Cross-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" check
  6. Configure sse2neon precision via compile-time macros

    master

    By 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:

    MacroEffect
    SSE2NEON_PRECISE_MINMAXCorrect NaN handling in _mm_min_{ps,pd} and _mm_max_{ps,pd}
    SSE2NEON_PRECISE_DIVExtra Newton-Raphson iteration for _mm_rcp_ps and _mm_div_ps
    SSE2NEON_PRECISE_SQRTExtra Newton-Raphson iteration for _mm_sqrt_ps and _mm_rsqrt_ps
    SSE2NEON_PRECISE_DPConditional multiplication in _mm_dp_pd
    SSE2NEON_UNDEFINED_ZEROForce zero for _mm_undefined_{ps,pd,si128}

    Recommended configurations by use case:

    • Graphics/Rendering: MINMAX, SQRT (and DIV if using rcp)
    • Scientific/Numerical: MINMAX, SQRT, DP
    • Game Physics: MINMAX (prevents NaN propagation)
    • Machine Learning (Inference): MINMAX (for determinism)
    • DSP/Audio/Cryptography: Use defaults (no flags) for maximum throughput.
    #define SSE2NEON_PRECISE_MINMAX 1
    #define SSE2NEON_PRECISE_SQRT 1
    #include "sse2neon.h"
  7. Set the MONITOR/MWAIT policy for ARM

    master

    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:

    ValueBehavior
    0 (default)yield - Safe everywhere, never blocks
    1wfe - Event wait, may trap in EL0
    2wfi - 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.

  8. Reference efficient SSE intrinsics (T1)

    master

    Tier 1 (T1) intrinsics map directly to single NEON instructions and offer near-native performance. Examples include:

    • Arithmetic: _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.
    • Comparison: _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.
    • Logical: _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.
    • Load/Store: _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.
    • Conversion: _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.
    • Math: _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.
  9. Reference materials for SIMD and SSE/NEON

    master

    When working with SIMD intrinsics, the following resources are recommended for technical accuracy and implementation guidance:

    Instruction Set References

    • Intel Intrinsics Guide: The authoritative source for x86 intrinsics.
    • Microsoft x86 intrinsics list: Documentation for Microsoft-specific x86 intrinsics.
    • Arm Neon Intrinsics Reference: The official reference for Arm NEON.
    • NEON Programmer's Guide: Detailed guidance for Armv8-A and general NEON programming.

    Implementation & Porting Guides

    • qemu/target/i386/ops_sse.h: A comprehensive SSE instruction emulation in C, useful for semantic checks.
    • Porting with SSE2Neon and SIMDe: Official Arm documentation on using these tools for porting.
    • Application porting to Windows on Snapdragon: Qualcomm's guide on using the sse2neon header file for Windows on Arm development.