[glibc] string: simplify find_zero_ne_all
Adhemerval Zanella via Glibc-cvs <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=40cf4504a8290a18a1249e2233ccdedf0a30d985 commit 40cf4504a8290a18a1249e2233ccdedf0a30d985 Author: Matt Turner <[email protected]> Date: Fri Aug 14 12:11:34 2026 -0400 string: simplify find_zero_ne_all Build the mask from the raw difference, as find_ne_all () now does. index_first () and index_last () only need to know which byte holds the first or the last set bit, and find_zero_all () marks only the bytes that were zero, so each term of the or marks only its own bytes. That drops one of the two carry chains from strcmp () and strncmp () on targets using the generic string-fza.h, and one of the two uqsub8 on armv6t2. As in find_ne_all (), only the generic implementation tests HAVE_BITOPTS_WORKING. powerpc keeps its existing form, where orc folds the complement of cmpb into the or and the raw difference saves nothing. alpha and riscv do not reach this code with the generic index_first (). Reviewed-by: Wilco Dijkstra <[email protected]> Diff: --- sysdeps/arm/armv6t2/string-fza.h | 6 +++--- sysdeps/generic/string-fza.h | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sysdeps/arm/armv6t2/string-fza.h b/sysdeps/arm/armv6t2/string-fza.h index 3ff9c31461..d5221a99c7 100644 --- a/sysdeps/arm/armv6t2/string-fza.h +++ b/sysdeps/arm/armv6t2/string-fza.h @@ -54,9 +54,9 @@ find_zero_eq_all (op_t x1, op_t x2) static __always_inline find_t find_zero_ne_all (op_t x1, op_t x2) { - /* Make use of the fact that we'll already have ONES in a register. */ - op_t ones = repeat_bytes (0x01); - return find_zero_all (x1) | (find_zero_all (x1 ^ x2) ^ ones); + /* As in find_ne_all; find_zero_all () sets only 0x01 in a byte that was + zero, so each term of the or marks only its own bytes. */ + return (x1 ^ x2) | find_zero_all (x1); } /* Identify bytes that are not equal between X1 and X2. */ diff --git a/sysdeps/generic/string-fza.h b/sysdeps/generic/string-fza.h index e569d0aa41..d9af795bbf 100644 --- a/sysdeps/generic/string-fza.h +++ b/sysdeps/generic/string-fza.h @@ -89,11 +89,18 @@ find_zero_eq_all (op_t x1, op_t x2) static __always_inline find_t find_zero_ne_all (op_t x1, op_t x2) { +#if HAVE_BITOPTS_WORKING + /* As in find_ne_all, the difference does not have to be reduced to one + bit per byte. find_zero_all () sets only 0x80 in a byte that was + zero, so each term marks only its own bytes. */ + return (x1 ^ x2) | find_zero_all (x1); +#else op_t m = repeat_bytes (0x7f); op_t eq = x1 ^ x2; op_t nz1 = ((x1 & m) + m) | x1; op_t ne2 = ((eq & m) + m) | eq; return (ne2 | ~nz1) & ~m; +#endif } /* With similar caveats, identify bytes that are not equal between X1