[PATCH v2 2/3] string: simplify find_zero_ne_all

Matt Turner <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
Build the mask from the raw difference when HAVE_BITOPTS_WORKING, as
find_ne_all () now does.  index_first () and index_last () then use
stdc_trailing_zeros () and stdc_leading_zeros (), which 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.  It saves nothing on powerpc, where orc folds the complement of
cmpb into the or, so that one keeps its existing form.  alpha and riscv
are unaffected, neither having reached this code with the generic
index_first ().
---
 sysdeps/arm/armv6t2/string-fza.h | 6 ++++++
 sysdeps/generic/string-fza.h     | 7 +++++++
 2 files changed, 13 insertions(+)

diff --git ./sysdeps/arm/armv6t2/string-fza.h ./sysdeps/arm/armv6t2/string-fza.h
index 0ae4c79f7d..ecbd08fd04 100644
--- ./sysdeps/arm/armv6t2/string-fza.h
+++ ./sysdeps/arm/armv6t2/string-fza.h
@@ -57,9 +57,15 @@ 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; 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);
+#else
   /* 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);
+#endif
 }
 
 /* Identify bytes that are not equal between X1 and X2.  */
diff --git ./sysdeps/generic/string-fza.h ./sysdeps/generic/string-fza.h
index 3296b09748..073aec15dd 100644
--- ./sysdeps/generic/string-fza.h
+++ ./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
-- 
2.54.0
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.