Find the last occurrence of a @b single-character needle in an arbitrary length haystack. * This implementation uses hardware-agnostic SWAR technique, to process 8 characters at a time. * Identical to `memrchr(haystack, needle[0], haystack_length)`. */
| 415 | * Identical to `memrchr(haystack, needle[0], haystack_length)`. |
| 416 | */ |
| 417 | sz_cptr_t sz_rfind_byte_serial(sz_cptr_t h_chars, sz_size_t h_length, sz_cptr_t n_chars) { |
| 418 | |
| 419 | if (!h_length) return SZ_NULL_CHAR; |
| 420 | // Reinterpret as unsigned bytes so the SWAR broadcast below cannot sign-extend |
| 421 | // on platforms where `char` is signed (e.g. `-fsigned-char`). See issue #306. |
| 422 | sz_u8_t const *const h_start = (sz_u8_t const *)h_chars; |
| 423 | sz_u8_t const *const n = (sz_u8_t const *)n_chars; |
| 424 | |
| 425 | // Reposition the `h` pointer to the end, as we will be walking backwards. |
| 426 | sz_u8_t const *h = h_start + h_length - 1; |
| 427 | |
| 428 | #if !SZ_IS_BIG_ENDIAN_ // Use SWAR only on little-endian platforms for brevity. |
| 429 | #if !SZ_USE_MISALIGNED_LOADS // Process the misaligned head, to void UB on unaligned 64-bit loads. |
| 430 | for (; ((sz_size_t)(h + 1) & 7ull) && h >= h_start; --h) |
| 431 | if (*h == *n) return (sz_cptr_t)h; |
| 432 | #endif |
| 433 | |
| 434 | // Broadcast the n into every byte of a 64-bit integer to use SWAR |
| 435 | // techniques and process eight characters at a time. |
| 436 | sz_u64_vec_t h_vec, n_vec, match_vec; |
| 437 | n_vec.u64 = (sz_u64_t)*n * 0x0101010101010101ull; |
| 438 | for (; h >= h_start + 7; h -= 8) { |
| 439 | h_vec.u64 = *(sz_u64_t const *)(h - 7); |
| 440 | match_vec = sz_u64_each_byte_equal_(h_vec, n_vec); |
| 441 | if (match_vec.u64) return (sz_cptr_t)(h - sz_u64_clz(match_vec.u64) / 8); |
| 442 | } |
| 443 | #endif |
| 444 | |
| 445 | for (; h >= h_start; --h) |
| 446 | if (*h == *n) return (sz_cptr_t)h; |
| 447 | return SZ_NULL_CHAR; |
| 448 | } |
| 449 | |
| 450 | /** |
| 451 | * @brief 2Byte-level equality comparison between two 64-bit integers. |
no test coverage detected
searching dependent graphs…