| 1484 | } |
| 1485 | |
| 1486 | SZ_PUBLIC sz_size_t sz_utf8_count_neon(sz_cptr_t text, sz_size_t length) { |
| 1487 | sz_u128_vec_t text_vec, headers_vec, continuation_vec; |
| 1488 | uint8x16_t continuation_mask_vec = vdupq_n_u8(0xC0); |
| 1489 | uint8x16_t continuation_pattern_vec = vdupq_n_u8(0x80); |
| 1490 | sz_u8_t const *text_u8 = (sz_u8_t const *)text; |
| 1491 | uint64x2_t char_count_vec = vdupq_n_u64(0); |
| 1492 | while (length >= 16) { |
| 1493 | text_vec.u8x16 = vld1q_u8(text_u8); |
| 1494 | headers_vec.u8x16 = vandq_u8(text_vec.u8x16, continuation_mask_vec); |
| 1495 | continuation_vec.u8x16 = vceqq_u8(headers_vec.u8x16, continuation_pattern_vec); |
| 1496 | // Convert 0xFF/0x00 into 1/0 and sum. |
| 1497 | uint8x16_t start_flags = vshrq_n_u8(vmvnq_u8(continuation_vec.u8x16), 7); |
| 1498 | uint16x8_t sum16 = vpaddlq_u8(start_flags); |
| 1499 | uint32x4_t sum32 = vpaddlq_u16(sum16); |
| 1500 | uint64x2_t sum64 = vpaddlq_u32(sum32); |
| 1501 | char_count_vec = vaddq_u64(char_count_vec, sum64); |
| 1502 | text_u8 += 16; |
| 1503 | length -= 16; |
| 1504 | } |
| 1505 | |
| 1506 | sz_size_t char_count = vgetq_lane_u64(char_count_vec, 0) + vgetq_lane_u64(char_count_vec, 1); |
| 1507 | if (length) char_count += sz_utf8_count_serial((sz_cptr_t)text_u8, length); |
| 1508 | return char_count; |
| 1509 | } |
| 1510 | |
| 1511 | SZ_PUBLIC sz_cptr_t sz_utf8_find_nth_neon(sz_cptr_t text, sz_size_t length, sz_size_t n) { |
| 1512 | // TODO: Implement a NEON-accelerated version of sz_utf8_find_nth in absence of PDEP instruction. |
no test coverage detected
searching dependent graphs…