Read FD and return a summary. */
| 24 | |
| 25 | /* Read FD and return a summary. */ |
| 26 | extern struct wc_lines |
| 27 | wc_lines_avx2 (int fd) |
| 28 | { |
| 29 | intmax_t lines = 0; |
| 30 | intmax_t bytes = 0; |
| 31 | |
| 32 | __m256i endlines = _mm256_set1_epi8 ('\n'); |
| 33 | |
| 34 | while (true) |
| 35 | { |
| 36 | __m256i avx_buf[IO_BUFSIZE / sizeof (__m256i)]; |
| 37 | ssize_t bytes_read = read (fd, avx_buf, sizeof avx_buf); |
| 38 | if (bytes_read <= 0) |
| 39 | return (struct wc_lines) { bytes_read == 0 ? 0 : errno, lines, bytes }; |
| 40 | |
| 41 | bytes += bytes_read; |
| 42 | __m256i *datap = avx_buf; |
| 43 | |
| 44 | while (bytes_read >= 32) |
| 45 | { |
| 46 | __m256i to_match = _mm256_load_si256 (datap); |
| 47 | __m256i matches = _mm256_cmpeq_epi8 (to_match, endlines); |
| 48 | int mask = _mm256_movemask_epi8 (matches); |
| 49 | lines += __builtin_popcount (mask); |
| 50 | datap += 1; |
| 51 | bytes_read -= 32; |
| 52 | } |
| 53 | |
| 54 | /* Finish up any left over bytes */ |
| 55 | char *end = (char *) datap + bytes_read; |
| 56 | for (char *p = (char *) datap; p < end; p++) |
| 57 | lines += *p == '\n'; |
| 58 | } |
| 59 | } |