Skip to content

WASM SIMD implementations of SSE #86

Description

@nemequ

We should add WASM simd128 implementations of as many SSE/SSE2/etc. functions as possible.

If a function has a WASM implementation, please check it off the list.

Not all functions will have reasonable WASM equivalents. If you find a function which you don't think can be implemented better than the portable fallbacks do, please just change it from a checklist item to a regular list item and move it to the end of the list for that particular ISA extension.

Note that GitHub doesn't tend to handle massive lists very well; it will probably be better to edit this comment and just put an x inside of the square brackets for list items to check them off.

If you don't have permission to edit this comment but would like to help out, please just add a comment and I'll add you to the project.

There are already a lot of functions in SIMDe which have WASM implementations but haven't been checked off of this list, so the first step is probably to go through the code and check off the functions which already have WASM implementations. It shouldn't be too hard, just grep for "wasm_" and check off the relevant function(s) for each result. When you do this for an ISA extension, please check it off of this first list:

  • SSE
  • SSE2
  • SSE3
  • SSSE3
  • SSE4.1

SSE:

  • _mm_max_pi16
  • _m_pmaxsw
  • _mm_max_pu8
  • _m_pmaxub
  • _mm_min_pi16
  • _m_pminsw
  • _mm_min_pu8
  • _m_pminub
  • _mm_mulhi_pu16
  • _m_pmulhuw
  • _mm_avg_pu8
  • _m_pavgb
  • _mm_avg_pu16
  • _m_pavgw
  • _mm_sad_pu8
  • _m_psadbw
  • _mm_cvtsi32_ss
  • _mm_cvt_si2ss
  • _mm_cvtsi64_ss
  • _mm_cvtpi32_ps
  • _mm_cvt_pi2ps
  • _mm_cvtpi16_ps
  • _mm_cvtpu16_ps
  • _mm_cvtpi8_ps
  • _mm_cvtpu8_ps
  • _mm_cvtpi32x2_ps
  • _mm_stream_pi
  • _mm_maskmove_si64
  • _m_maskmovq
  • _mm_extract_pi16
  • _m_pextrw
  • _mm_insert_pi16
  • _m_pinsrw
  • _mm_movemask_pi8
  • _m_pmovmskb
  • _mm_shuffle_pi16
  • _m_pshufw
  • _mm_add_ps
  • _mm_sub_ss
  • _mm_sub_ps
  • _mm_mul_ss
  • _mm_mul_ps
  • _mm_div_ss
  • _mm_div_ps
  • _mm_sqrt_ss
  • _mm_sqrt_ps
  • _mm_rcp_ss
  • _mm_rcp_ps
  • _mm_rsqrt_ss
  • _mm_rsqrt_ps
  • _mm_min_ss
  • _mm_min_ps
  • _mm_max_ss
  • _mm_max_ps
  • _mm_and_ps
  • _mm_andnot_ps
  • _mm_or_ps
  • _mm_xor_ps
  • _mm_cmpeq_ss
  • _mm_cmpeq_ps
  • _mm_cmplt_ss
  • _mm_cmplt_ps
  • _mm_cmple_ss
  • _mm_cmple_ps
  • _mm_cmpgt_ss
  • _mm_cmpgt_ps
  • _mm_cmpge_ss
  • _mm_cmpge_ps
  • _mm_cmpneq_ss
  • _mm_cmpneq_ps
  • _mm_cmpnlt_ss
  • _mm_cmpnlt_ps
  • _mm_cmpnle_ss
  • _mm_cmpnle_ps
  • _mm_cmpngt_ss
  • _mm_cmpngt_ps
  • _mm_cmpnge_ss
  • _mm_cmpnge_ps
  • _mm_cmpord_ss
  • _mm_cmpord_ps
  • _mm_cmpunord_ss
  • _mm_cmpunord_ps
  • _mm_comieq_ss
  • _mm_comilt_ss
  • _mm_comile_ss
  • _mm_comigt_ss
  • _mm_comige_ss
  • _mm_comineq_ss
  • _mm_ucomieq_ss
  • _mm_ucomilt_ss
  • _mm_ucomile_ss
  • _mm_ucomigt_ss
  • _mm_ucomige_ss
  • _mm_ucomineq_ss
  • _mm_cvtss_si32
  • _mm_cvt_ss2si
  • _mm_cvtss_si64
  • _mm_cvtss_f32
  • _mm_cvtps_pi32
  • _mm_cvt_ps2pi
  • _mm_cvttss_si32
  • _mm_cvtt_ss2si
  • _mm_cvttss_si64
  • _mm_cvttps_pi32
  • _mm_cvtt_ps2pi
  • _mm_cvtps_pi16
  • _mm_cvtps_pi8
  • _mm_set_ss
  • _mm_set1_ps
  • _mm_set_ps1
  • _mm_set_ps
  • _mm_setr_ps
  • _mm_setzero_ps
  • _mm_loadh_pi
  • _mm_loadl_pi
  • _mm_load_ss
  • _mm_load1_ps
  • _mm_load_ps1
  • _mm_load_ps
  • _mm_loadu_ps
  • _mm_loadr_ps
  • _mm_stream_ps
  • _mm_storeh_pi
  • _mm_storel_pi
  • _mm_store_ss
  • _mm_store1_ps
  • _mm_store_ps1
  • _mm_store_ps
  • _mm_storeu_ps
  • _mm_storer_ps
  • _mm_move_ss
  • _mm_shuffle_ps
  • _mm_unpackhi_ps
  • _mm_unpacklo_ps
  • _mm_movehl_ps
  • _mm_movelh_ps
  • _mm_movemask_ps
  • _mm_malloc
  • _mm_free
  • _mm_undefined_ps
  • _mm_storeu_si16
  • _mm_loadu_si64
  • _mm_storeu_si64
  • _mm_loadu_si16
  • _mm_add_ss
  • _mm_getcsr
  • _mm_setcsr
  • _mm_prefetch
  • _mm_sfence

SSE2:

  • _mm_undefined_pd
  • _mm_undefined_si128
  • _mm_loadu_si32
  • _mm_storeu_si32
  • _mm_pause
  • _mm_clflush
  • _mm_lfence
  • _mm_mfence
  • _mm_add_epi8
  • _mm_add_epi16
  • _mm_add_epi32
  • _mm_add_si64
  • _mm_add_epi64
  • _mm_adds_epi8
  • _mm_adds_epi16
  • _mm_adds_epu8
  • _mm_adds_epu16
  • _mm_avg_epu8
  • _mm_avg_epu16
  • _mm_madd_epi16
  • _mm_max_epi16
  • _mm_max_epu8
  • _mm_min_epi16
  • _mm_min_epu8
  • _mm_mulhi_epi16
  • _mm_mulhi_epu16
  • _mm_mullo_epi16
  • _mm_mul_su32
  • _mm_mul_epu32
  • _mm_sad_epu8
  • _mm_sub_epi8
  • _mm_sub_epi16
  • _mm_sub_epi32
  • _mm_sub_si64
  • _mm_sub_epi64
  • _mm_subs_epi8
  • _mm_subs_epi16
  • _mm_subs_epu8
  • _mm_subs_epu16
  • _mm_slli_si128
  • _mm_bslli_si128
  • _mm_bsrli_si128
  • _mm_slli_epi16
  • _mm_sll_epi16
  • _mm_slli_epi32
  • _mm_sll_epi32
  • _mm_slli_epi64
  • _mm_sll_epi64
  • _mm_srai_epi16
  • _mm_sra_epi16
  • _mm_srai_epi32
  • _mm_sra_epi32
  • _mm_srli_si128
  • _mm_srli_epi16
  • _mm_srl_epi16
  • _mm_srli_epi32
  • _mm_srl_epi32
  • _mm_srli_epi64
  • _mm_srl_epi64
  • _mm_and_si128
  • _mm_andnot_si128
  • _mm_or_si128
  • _mm_xor_si128
  • _mm_cmpeq_epi8
  • _mm_cmpeq_epi16
  • _mm_cmpeq_epi32
  • _mm_cmpgt_epi8
  • _mm_cmpgt_epi16
  • _mm_cmpgt_epi32
  • _mm_cmplt_epi8
  • _mm_cmplt_epi16
  • _mm_cmplt_epi32
  • _mm_cvtepi32_pd
  • _mm_cvtsi32_sd
  • _mm_cvtsi64_sd
  • _mm_cvtsi64x_sd
  • _mm_cvtepi32_ps
  • _mm_cvtpi32_pd
  • _mm_cvtsi32_si128
  • _mm_cvtsi64_si128
  • _mm_cvtsi64x_si128
  • _mm_cvtsi128_si32
  • _mm_cvtsi128_si64
  • _mm_cvtsi128_si64x
  • _mm_set_epi64
  • _mm_set_epi64x
  • _mm_set_epi32
  • _mm_set_epi16
  • _mm_set_epi8
  • _mm_set1_epi64
  • _mm_set1_epi64x
  • _mm_set1_epi32
  • _mm_set1_epi16
  • _mm_set1_epi8
  • _mm_setr_epi64
  • _mm_setr_epi32
  • _mm_setr_epi16
  • _mm_setr_epi8
  • _mm_setzero_si128
  • _mm_loadl_epi64
  • _mm_load_si128
  • _mm_loadu_si128
  • _mm_maskmoveu_si128
  • _mm_store_si128
  • _mm_storeu_si128
  • _mm_storel_epi64
  • _mm_stream_si128
  • _mm_stream_si32
  • _mm_stream_si64
  • _mm_movepi64_pi64
  • _mm_movpi64_epi64
  • _mm_move_epi64
  • _mm_packs_epi16
  • _mm_packs_epi32
  • _mm_packus_epi16
  • _mm_extract_epi16
  • _mm_insert_epi16
  • _mm_movemask_epi8
  • _mm_shuffle_epi32
  • _mm_shufflehi_epi16
  • _mm_shufflelo_epi16
  • _mm_unpackhi_epi8
  • _mm_unpackhi_epi16
  • _mm_unpackhi_epi32
  • _mm_unpackhi_epi64
  • _mm_unpacklo_epi8
  • _mm_unpacklo_epi16
  • _mm_unpacklo_epi32
  • _mm_unpacklo_epi64
  • _mm_add_sd
  • _mm_add_pd
  • _mm_div_sd
  • _mm_div_pd
  • _mm_max_sd
  • _mm_max_pd
  • _mm_min_sd
  • _mm_min_pd
  • _mm_mul_sd
  • _mm_mul_pd
  • _mm_sqrt_sd
  • _mm_sqrt_pd
  • _mm_sub_sd
  • _mm_sub_pd
  • _mm_and_pd
  • _mm_andnot_pd
  • _mm_or_pd
  • _mm_xor_pd
  • _mm_cmpeq_sd
  • _mm_cmplt_sd
  • _mm_cmple_sd
  • _mm_cmpgt_sd
  • _mm_cmpge_sd
  • _mm_cmpord_sd
  • _mm_cmpunord_sd
  • _mm_cmpneq_sd
  • _mm_cmpnlt_sd
  • _mm_cmpnle_sd
  • _mm_cmpngt_sd
  • _mm_cmpnge_sd
  • _mm_cmpeq_pd
  • _mm_cmplt_pd
  • _mm_cmple_pd
  • _mm_cmpgt_pd
  • _mm_cmpge_pd
  • _mm_cmpord_pd
  • _mm_cmpunord_pd
  • _mm_cmpneq_pd
  • _mm_cmpnlt_pd
  • _mm_cmpnle_pd
  • _mm_cmpngt_pd
  • _mm_cmpnge_pd
  • _mm_comieq_sd
  • _mm_comilt_sd
  • _mm_comile_sd
  • _mm_comigt_sd
  • _mm_comige_sd
  • _mm_comineq_sd
  • _mm_ucomieq_sd
  • _mm_ucomilt_sd
  • _mm_ucomile_sd
  • _mm_ucomigt_sd
  • _mm_ucomige_sd
  • _mm_ucomineq_sd
  • _mm_cvtpd_ps
  • _mm_cvtps_pd
  • _mm_cvtpd_epi32
  • _mm_cvtsd_si32
  • _mm_cvtsd_si64
  • _mm_cvtsd_si64x
  • _mm_cvtsd_ss
  • _mm_cvtsd_f64
  • _mm_cvtss_sd
  • _mm_cvttpd_epi32
  • _mm_cvttsd_si32
  • _mm_cvttsd_si64
  • _mm_cvttsd_si64x
  • _mm_cvtps_epi32
  • _mm_cvttps_epi32
  • _mm_cvtpd_pi32
  • _mm_cvttpd_pi32
  • _mm_set_sd
  • _mm_set1_pd
  • _mm_set_pd1
  • _mm_set_pd
  • _mm_setr_pd
  • _mm_setzero_pd
  • _mm_load_pd
  • _mm_load1_pd
  • _mm_load_pd1
  • _mm_loadr_pd
  • _mm_loadu_pd
  • _mm_load_sd
  • _mm_loadh_pd
  • _mm_loadl_pd
  • _mm_stream_pd
  • _mm_store_sd
  • _mm_store1_pd
  • _mm_store_pd1
  • _mm_store_pd
  • _mm_storeu_pd
  • _mm_storer_pd
  • _mm_storeh_pd
  • _mm_storel_pd
  • _mm_unpackhi_pd
  • _mm_unpacklo_pd
  • _mm_movemask_pd
  • _mm_shuffle_pd
  • _mm_move_sd
  • _mm_castpd_ps
  • _mm_castpd_si128
  • _mm_castps_pd
  • _mm_castps_si128
  • _mm_castsi128_pd
  • _mm_castsi128_ps

SSE3:

  • _mm_addsub_ps
  • _mm_addsub_pd
  • _mm_hadd_pd
  • _mm_hadd_ps
  • _mm_hsub_pd
  • _mm_hsub_ps
  • _mm_lddqu_si128
  • _mm_movedup_pd
  • _mm_loaddup_pd
  • _mm_movehdup_ps
  • _mm_moveldup_ps

SSSE3:

  • _mm_abs_pi8
  • _mm_abs_epi8
  • _mm_abs_pi16
  • _mm_abs_epi16
  • _mm_abs_pi32
  • _mm_abs_epi32
  • _mm_shuffle_epi8
  • _mm_shuffle_pi8
  • _mm_alignr_epi8
  • _mm_alignr_pi8
  • _mm_hadd_epi16
  • _mm_hadds_epi16
  • _mm_hadd_epi32
  • _mm_hadd_pi16
  • _mm_hadd_pi32
  • _mm_hadds_pi16
  • _mm_hsub_epi16
  • _mm_hsubs_epi16
  • _mm_hsub_epi32
  • _mm_hsub_pi16
  • _mm_hsub_pi32
  • _mm_hsubs_pi16
  • _mm_maddubs_epi16
  • _mm_maddubs_pi16
  • _mm_mulhrs_epi16
  • _mm_mulhrs_pi16
  • _mm_sign_epi8
  • _mm_sign_epi16
  • _mm_sign_epi32
  • _mm_sign_pi8
  • _mm_sign_pi16
  • _mm_sign_pi32

SSE4.1:

  • _mm_blend_pd
  • _mm_blend_ps
  • _mm_blendv_pd
  • _mm_blendv_ps
  • _mm_blendv_epi8
  • _mm_blend_epi16
  • _mm_dp_pd
  • _mm_dp_ps
  • _mm_extract_ps
  • _mm_extract_epi8
  • _mm_extract_epi32
  • _mm_extract_epi64
  • _mm_insert_ps
  • _mm_insert_epi8
  • _mm_insert_epi32
  • _mm_insert_epi64
  • _mm_max_epi8
  • _mm_max_epi32
  • _mm_max_epu32
  • _mm_max_epu16
  • _mm_min_epi8
  • _mm_min_epi32
  • _mm_min_epu32
  • _mm_min_epu16
  • _mm_packus_epi32
  • _mm_cmpeq_epi64
  • _mm_cvtepi8_epi16
  • _mm_cvtepi8_epi32
  • _mm_cvtepi8_epi64
  • _mm_cvtepi16_epi32
  • _mm_cvtepi16_epi64
  • _mm_cvtepi32_epi64
  • _mm_cvtepu8_epi16
  • _mm_cvtepu8_epi32
  • _mm_cvtepu8_epi64
  • _mm_cvtepu16_epi32
  • _mm_cvtepu16_epi64
  • _mm_cvtepu32_epi64
  • _mm_mul_epi32
  • _mm_mullo_epi32
  • _mm_testz_si128
  • _mm_testc_si128
  • _mm_testnzc_si128
  • _mm_test_all_zeros
  • _mm_test_mix_ones_zeros
  • _mm_test_all_ones
  • _mm_round_pd
  • _mm_floor_pd
  • _mm_ceil_pd
  • _mm_round_ps
  • _mm_floor_ps
  • _mm_ceil_ps
  • _mm_round_sd
  • _mm_floor_sd
  • _mm_ceil_sd
  • _mm_round_ss
  • _mm_floor_ss
  • _mm_ceil_ss
  • _mm_minpos_epu16
  • _mm_mpsadbw_epu8
  • _mm_stream_load_si128

Some of the functions won't see much, if any, improvements since we already have GCC-style vector extension and OpenMP SIMD support. The real benefit will be for the functions that can't use GCC-style vectors. For example, saturated operations, min/max, etc. And of course there will be a lot of cases where maybe the compiler can autovectorize and maybe it can't (especially if operating at -O2 instead of -O3), and explicitly calling the simd128 versions is more likely to result in vectorized versions.

The implementation shouldn't be too difficult. We'll need to add a v128_t entry to the simde_m128_private, simde_m128i_private, simde_m128d_private, and of course properly detect WASM SIMD in simde-arch.h then use that in the headers like sse.h and sse2.h. Other than that it should generally just be a matter of adding an #elif defined(SIMDE_ARCH_WASM_SIMD128) and an implementation.

Right now we don't have an emscripten build in CI; we'll have to figure out how to add it back in. I removed it because emscripten was running out of memory (it works fine on my desktop with 24 GiB RAM, but kept getting killed on the little VM workres). Adding in some optimization flags may help reduce the memory requirement; I hadn't done that because emscripten was generating an internal compiler error, but that may be fixed now (at least using tot, hopefully there will be a release soon); if not, I should be reporting them to emscripten so they can be fixed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    GSoC/Outreachy-ideasIdeas for Google Summer of Code or Outreachy projectsaccelerated-implementationAn implementation of one ISA extension with another (e.g., implementing SSE using NEON)good first issueThis is perfect if you're new to the project and looking to help.help wantedWe lack either the expertise or time for this. Basically, "patches welcome".

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions