blob: 7a2821e3546e73de2fce143e1ff37cc3e5c2a21b [file] [edit]
--- a/core/iwasm/interpreter/wasm_interp_fast.c
+++ b/core/iwasm/interpreter/wasm_interp_fast.c
@@ -23,6 +23,11 @@
#if WASM_ENABLE_SIMDE != 0
#include "simde/wasm/simd128.h"
+#endif
+#if defined(__aarch64__) && defined(__ARM_NEON)
+#include <arm_neon.h>
+#elif defined(__SSSE3__)
+#include <tmmintrin.h>
#endif
/* rive patch: sw-bounds artifacts (Luau) must never unwind through hardware
@@ -6666,9 +6671,10 @@
/* TODO: Add a faster SIMD implementation */
HANDLE_SIMD_OP(SIMD_v8x16_shuffle)
{
+ /* rive patch: one table lookup over both operands;
+ lane indices were validated to 0..31 at load */
V128 indices;
- bh_memcpy_s(&indices, sizeof(V128), frame_ip,
- sizeof(V128));
+ memcpy(&indices, frame_ip, sizeof(V128));
frame_ip += sizeof(V128);
V128 v2 = POP_V128();
@@ -6676,6 +6682,29 @@
addr_ret = GET_OFFSET();
V128 result;
+#if defined(__aarch64__) && defined(__ARM_NEON)
+ {
+ uint8x16x2_t table;
+ table.val[0] = vld1q_u8((const uint8_t *)&v1);
+ table.val[1] = vld1q_u8((const uint8_t *)&v2);
+ vst1q_u8((uint8_t *)&result,
+ vqtbl2q_u8(table, vld1q_u8((const uint8_t *)&indices)));
+ }
+#elif defined(__SSSE3__)
+ {
+ __m128i idx = _mm_loadu_si128((const __m128i *)&indices);
+ __m128i a = _mm_loadu_si128((const __m128i *)&v1);
+ __m128i b = _mm_loadu_si128((const __m128i *)&v2);
+ /* pshufb zeroes lanes whose index has bit 7 set */
+ __m128i from_b = _mm_cmpgt_epi8(idx, _mm_set1_epi8(15));
+ __m128i pick_a = _mm_shuffle_epi8(a, _mm_or_si128(idx, from_b));
+ __m128i pick_b = _mm_shuffle_epi8(
+ b, _mm_or_si128(
+ _mm_andnot_si128(from_b, _mm_set1_epi8((char)0x80)),
+ _mm_sub_epi8(idx, _mm_set1_epi8(16))));
+ _mm_storeu_si128((__m128i *)&result, _mm_or_si128(pick_a, pick_b));
+ }
+#else
for (int i = 0; i < 16; i++) {
uint8_t index = indices.i8x16[i];
if (index < 16) {
@@ -6685,6 +6714,7 @@
result.i8x16[i] = v2.i8x16[index - 16];
}
}
+#endif
PUT_V128_TO_ADDR(frame_lp + addr_ret, result);
HANDLE_SIMD_OP_END();