[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.