master
1#include <string.h>
2
3#ifdef __wasm_simd128__
4#include <wasm_simd128.h>
5#endif
6
7void *__memrchr(const void *m, int c, size_t n)
8{
9#if defined(__wasm_simd128__) && defined(__wasilibc_simd_string)
10 // memrchr is allowed to read up to n bytes from the object.
11 // Search backward for the last matching character.
12 const v128_t *v = (v128_t *)((char *)m + n);
13 const v128_t vc = wasm_i8x16_splat(c);
14 for (; n >= sizeof(v128_t); n -= sizeof(v128_t)) {
15 const v128_t cmp = wasm_i8x16_eq(wasm_v128_load(--v), vc);
16 // Bitmask is slow on AArch64, any_true is much faster.
17 if (wasm_v128_any_true(cmp)) {
18 // Find the offset of the last one bit (little-endian).
19 // The leading 16 bits of the bitmask are always zero,
20 // and to be ignored.
21 size_t clz = __builtin_clz(wasm_i8x16_bitmask(cmp)) - 16;
22 return (char *)(v + 1) - (clz + 1);
23 }
24 }
25#endif
26
27 const unsigned char *s = m;
28 c = (unsigned char)c;
29 while (n--) if (s[n]==c) return (void *)(s+n);
30 return 0;
31}
32
33weak_alias(__memrchr, memrchr);