| 1061 | } |
| 1062 | |
| 1063 | SZ_PUBLIC sz_cptr_t sz_find_haswell(sz_cptr_t h, sz_size_t h_length, sz_cptr_t n, sz_size_t n_length) { |
| 1064 | |
| 1065 | // This almost never fires, but it's better to be safe than sorry. |
| 1066 | if (h_length < n_length || !n_length) return SZ_NULL_CHAR; |
| 1067 | if (n_length == 1) return sz_find_byte_haswell(h, h_length, n); |
| 1068 | |
| 1069 | // Pick the parts of the needle that are worth comparing. |
| 1070 | sz_size_t offset_first, offset_mid, offset_last; |
| 1071 | sz_locate_needle_anomalies_(n, n_length, &offset_first, &offset_mid, &offset_last); |
| 1072 | |
| 1073 | // Broadcast those characters into YMM registers. |
| 1074 | sz_u32_vec_t matches_vec; |
| 1075 | sz_u256_vec_t h_first_vec, h_mid_vec, h_last_vec, n_first_vec, n_mid_vec, n_last_vec; |
| 1076 | n_first_vec.ymm = _mm256_set1_epi8(n[offset_first]); |
| 1077 | n_mid_vec.ymm = _mm256_set1_epi8(n[offset_mid]); |
| 1078 | n_last_vec.ymm = _mm256_set1_epi8(n[offset_last]); |
| 1079 | |
| 1080 | // Scan through the string. |
| 1081 | for (; h_length >= n_length + 32; h += 32, h_length -= 32) { |
| 1082 | h_first_vec.ymm = _mm256_lddqu_si256((__m256i const *)(h + offset_first)); |
| 1083 | h_mid_vec.ymm = _mm256_lddqu_si256((__m256i const *)(h + offset_mid)); |
| 1084 | h_last_vec.ymm = _mm256_lddqu_si256((__m256i const *)(h + offset_last)); |
| 1085 | matches_vec.i32 = // |
| 1086 | _mm256_movemask_epi8(_mm256_cmpeq_epi8(h_first_vec.ymm, n_first_vec.ymm)) & |
| 1087 | _mm256_movemask_epi8(_mm256_cmpeq_epi8(h_mid_vec.ymm, n_mid_vec.ymm)) & |
| 1088 | _mm256_movemask_epi8(_mm256_cmpeq_epi8(h_last_vec.ymm, n_last_vec.ymm)); |
| 1089 | while (matches_vec.u32) { |
| 1090 | int potential_offset = sz_u32_ctz(matches_vec.u32); |
| 1091 | if (sz_equal_haswell(h + potential_offset, n, n_length)) return h + potential_offset; |
| 1092 | matches_vec.u32 &= matches_vec.u32 - 1; |
| 1093 | } |
| 1094 | } |
| 1095 | |
| 1096 | return sz_find_serial(h, h_length, n, n_length); |
| 1097 | } |
| 1098 | |
| 1099 | SZ_PUBLIC sz_cptr_t sz_rfind_haswell(sz_cptr_t h, sz_size_t h_length, sz_cptr_t n, sz_size_t n_length) { |
| 1100 |
no test coverage detected
searching dependent graphs…