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);