[v2] Improve string benchtests

Message ID AM6PR08MB5078BDDAEC9D062181DF131683470@AM6PR08MB5078.eurprd08.prod.outlook.com
State Committed
Headers

Commit Message

Wilco Dijkstra March 18, 2019, 5:14 p.m. UTC
  v2: Add defines for the generic variants so we print eg. generic_wcslen
in the wcslen benchmark.

Replace slow byte-oriented tests in several string benchmarks with the
generic implementations from the string/ directory so the comparisons
are more realistic and useful.

OK to commit?

ChangeLog:
2019-03-18  Wilco Dijkstra  <wdijkstr@arm.com>

        * benchtests/bench-stpcpy.c (SIMPLE_STPCPY): Remove function.
        (generic_stpcpy): New function.
        * benchtests/bench-stpncpy.c (SIMPLE_STPNCPY): Remove function.
        (generic_stpncpy): New function.
        * benchtests/bench-strcat.c (SIMPLE_STRCAT): Remove function.
        (generic_strcat): New function.
        * benchtests/bench-strcpy.c (SIMPLE_STRCPY): Remove function.
        (generic_strcpy): New function.
        * benchtests/bench-strncat.c (SIMPLE_STRNCAT): Remove function.
        (STUPID_STRNCAT): Remove function.
        (generic_strncat): New function.
        * benchtests/bench-strncpy.c (SIMPLE_STRNCPY): Remove function.
        (STUPID_STRNCPY): Remove function.
        (generic_strncpy): New function.
        * benchtests/bench-strnlen.c (SIMPLE_STRNLEN): Remove function.
        (generic_strnlen): New function.
        (memchr_strnlen): New function.
        * benchtests/bench-strlen.c (generic_strlen): Define for WIDE.
        (memchr_strlen): Likewise.
--
  

Comments

Adhemerval Zanella Netto March 22, 2019, 6:25 p.m. UTC | #1
On 18/03/2019 14:14, Wilco Dijkstra wrote:
> v2: Add defines for the generic variants so we print eg. generic_wcslen
> in the wcslen benchmark.
> 
> Replace slow byte-oriented tests in several string benchmarks with the
> generic implementations from the string/ directory so the comparisons
> are more realistic and useful.
> 
> OK to commit?
> 
> ChangeLog:
> 2019-03-18  Wilco Dijkstra  <wdijkstr@arm.com>
> 
>         * benchtests/bench-stpcpy.c (SIMPLE_STPCPY): Remove function.
>         (generic_stpcpy): New function.
>         * benchtests/bench-stpncpy.c (SIMPLE_STPNCPY): Remove function.
>         (generic_stpncpy): New function.
>         * benchtests/bench-strcat.c (SIMPLE_STRCAT): Remove function.
>         (generic_strcat): New function.
>         * benchtests/bench-strcpy.c (SIMPLE_STRCPY): Remove function.
>         (generic_strcpy): New function.
>         * benchtests/bench-strncat.c (SIMPLE_STRNCAT): Remove function.
>         (STUPID_STRNCAT): Remove function.
>         (generic_strncat): New function.
>         * benchtests/bench-strncpy.c (SIMPLE_STRNCPY): Remove function.
>         (STUPID_STRNCPY): Remove function.
>         (generic_strncpy): New function.
>         * benchtests/bench-strnlen.c (SIMPLE_STRNLEN): Remove function.
>         (generic_strnlen): New function.
>         (memchr_strnlen): New function.
>         * benchtests/bench-strlen.c (generic_strlen): Define for WIDE.
>         (memchr_strlen): Likewise.

LGTM, thanks.


> --
> 
> diff --git a/benchtests/bench-stpcpy.c b/benchtests/bench-stpcpy.c
> index 74ea54f59417d82f6f70ef20279adff96ea78238..bcea9af1bf4d251665c978abb8f60305f054caf4 100644
> --- a/benchtests/bench-stpcpy.c
> +++ b/benchtests/bench-stpcpy.c
> @@ -22,24 +22,18 @@
>  # define TEST_NAME "stpcpy"
>  #else
>  # define TEST_NAME "wcpcpy"
> +# define generic_stpcpy generic_wcpcpy
>  #endif /* WIDE */
>  #include "bench-string.h"
> -#ifndef WIDE
> -# define SIMPLE_STPCPY simple_stpcpy
> -#else
> -# define SIMPLE_STPCPY simple_wcpcpy
> -#endif /* WIDE */
> -
> -CHAR *SIMPLE_STPCPY (CHAR *, const CHAR *);
> -
> -IMPL (SIMPLE_STPCPY, 0)
> -IMPL (STPCPY, 1)
>  
>  CHAR *
> -SIMPLE_STPCPY (CHAR *dst, const CHAR *src)
> +generic_stpcpy (CHAR *dst, const CHAR *src)
>  {
> -  while ((*dst++ = *src++) != '\0');
> -  return dst - 1;
> +  size_t len = STRLEN (src);
> +  return (CHAR *) MEMCPY (dst, src, len + 1) + len;
>  }
>  
> +IMPL (STPCPY, 1)
> +IMPL (generic_stpcpy, 0)
> +
>  #include "bench-strcpy.c"

Ok.

> diff --git a/benchtests/bench-stpncpy.c b/benchtests/bench-stpncpy.c
> index 0470695889008ad679eb5131fd67826a45a05748..c4c6b65bb75b0271dadc816f7c028a042234b31f 100644
> --- a/benchtests/bench-stpncpy.c
> +++ b/benchtests/bench-stpncpy.c
> @@ -22,49 +22,22 @@
>  # define TEST_NAME "stpncpy"
>  #else
>  # define TEST_NAME "wcpncpy"
> +# define generic_stpncpy generic_wcpncpy
>  #endif /* WIDE */
>  #include "bench-string.h"
> -#ifndef WIDE
> -# define SIMPLE_STPNCPY simple_stpncpy
> -# define STUPID_STPNCPY stupid_stpncpy
> -#else
> -# define SIMPLE_STPNCPY simple_wcpncpy
> -# define STUPID_STPNCPY stupid_wcpncpy
> -#endif /* WIDE */
> -
> -CHAR *SIMPLE_STPNCPY (CHAR *, const CHAR *, size_t);
> -CHAR *STUPID_STPNCPY (CHAR *, const CHAR *, size_t);
> -
> -IMPL (STUPID_STPNCPY, 0)
> -IMPL (SIMPLE_STPNCPY, 0)
> -IMPL (STPNCPY, 1)
> -
> -CHAR *
> -SIMPLE_STPNCPY (CHAR *dst, const CHAR *src, size_t n)
> -{
> -  while (n--)
> -    if ((*dst++ = *src++) == '\0')
> -      {
> -	size_t i;
> -
> -	for (i = 0; i < n; ++i)
> -	  dst[i] = '\0';
> -	return dst - 1;
> -      }
> -  return dst;
> -}
>  
>  CHAR *
> -STUPID_STPNCPY (CHAR *dst, const CHAR *src, size_t n)
> +generic_stpncpy (CHAR *dst, const CHAR *src, size_t n)
>  {
>    size_t nc = STRNLEN (src, n);
> -  size_t i;
> -
> -  for (i = 0; i < nc; ++i)
> -    dst[i] = src[i];
> -  for (; i < n; ++i)
> -    dst[i] = '\0';
> -  return dst + nc;
> +  MEMCPY (dst, src, nc);
> +  dst += nc;
> +  if (nc == n)
> +    return dst;
> +  return MEMSET (dst, 0, n - nc);
>  }
>  
> +IMPL (STPNCPY, 1)
> +IMPL (generic_stpncpy, 0)
> +
>  #include "bench-strncpy.c"

Ok.

> diff --git a/benchtests/bench-strcat.c b/benchtests/bench-strcat.c
> index a21d94a28e1ed55734c92e3eb617705cb42549cc..39d9fefb098c194523515e10cc4f47529b3aafd9 100644
> --- a/benchtests/bench-strcat.c
> +++ b/benchtests/bench-strcat.c
> @@ -21,6 +21,7 @@
>  # define TEST_NAME "strcat"
>  #else
>  # define TEST_NAME "wcscat"
> +# define generic_strcat generic_wcscat
>  #endif /* WIDE */
>  #include "bench-string.h"
>  
> @@ -28,31 +29,25 @@
>  
>  #ifndef WIDE
>  # define sfmt "s"
> -# define SIMPLE_STRCAT simple_strcat
>  # define SMALL_CHAR 127
>  #else
>  # define sfmt "ls"
> -# define SIMPLE_STRCAT simple_wcscat
>  # define SMALL_CHAR 1273
>  #endif /* WIDE */
>  
>  
>  typedef CHAR *(*proto_t) (CHAR *, const CHAR *);
> -CHAR *SIMPLE_STRCAT (CHAR *, const CHAR *);
> -
> -IMPL (SIMPLE_STRCAT, 0)
> -IMPL (STRCAT, 1)
>  
>  CHAR *
> -SIMPLE_STRCAT (CHAR *dst, const CHAR *src)
> +generic_strcat (CHAR *dst, const CHAR *src)
>  {
> -  CHAR *ret = dst;
> -  while (*dst++ != '\0');
> -  --dst;
> -  while ((*dst++ = *src++) != '\0');
> -  return ret;
> +  STRCPY (dst + STRLEN (dst), src);
> +  return dst;
>  }
>  
> +IMPL (STRCAT, 1)
> +IMPL (generic_strcat, 0)
> +
>  static void
>  do_one_test (impl_t *impl, CHAR *dst, const CHAR *src)
>  {

Ok.

> diff --git a/benchtests/bench-strcpy.c b/benchtests/bench-strcpy.c
> index 9fe999e5f4584b9034c19fb4a90b7cbd6deccd00..7a7cf4abb2873a555c5d8c3eb9d55d2f5c44df4e 100644
> --- a/benchtests/bench-strcpy.c
> +++ b/benchtests/bench-strcpy.c
> @@ -33,26 +33,19 @@
>  #  define TEST_NAME "strcpy"
>  # else
>  #  define TEST_NAME "wcscpy"
> +#  define generic_strcpy generic_wcscpy
>  # endif
> -# include "bench-string.h"
> -# ifndef WIDE
> -#  define SIMPLE_STRCPY simple_strcpy
> -# else
> -#  define SIMPLE_STRCPY simple_wcscpy
> -# endif
> -
> -CHAR *SIMPLE_STRCPY (CHAR *, const CHAR *);
> -
> -IMPL (SIMPLE_STRCPY, 0)
> -IMPL (STRCPY, 1)
> +#include "bench-string.h"
>  
>  CHAR *
> -SIMPLE_STRCPY (CHAR *dst, const CHAR *src)
> +generic_strcpy (CHAR *dst, const CHAR *src)
>  {
> -  CHAR *ret = dst;
> -  while ((*dst++ = *src++) != '\0');
> -  return ret;
> +  return MEMCPY (dst, src, STRLEN (src) + 1);
>  }
> +
> +IMPL (STRCPY, 1)
> +IMPL (generic_strcpy, 0)
> +
>  #endif
>  
>  typedef CHAR *(*proto_t) (CHAR *, const CHAR *);

Ok.

> diff --git a/benchtests/bench-strlen.c b/benchtests/bench-strlen.c
> index f6a8bf5dff6ff4410ab46997e48a173249497e7f..47363af0f749110acdacd87bd8c58a9a676fe43c 100644
> --- a/benchtests/bench-strlen.c
> +++ b/benchtests/bench-strlen.c
> @@ -21,6 +21,8 @@
>  # define TEST_NAME "strlen"
>  #else
>  # define TEST_NAME "wcslen"
> +# define generic_strlen generic_wcslen
> +# define memchr_strlen wcschr_wcslen
>  #endif
>  #include "bench-string.h"
>  

Ok.

> diff --git a/benchtests/bench-strncat.c b/benchtests/bench-strncat.c
> index 386eafa429f1456d85cde76b308a5f0907debdca..7271626d506f7a0b71cd2f46e641759567d17645 100644
> --- a/benchtests/bench-strncat.c
> +++ b/benchtests/bench-strncat.c
> @@ -21,41 +21,33 @@
>  # define TEST_NAME "strncat"
>  #else
>  # define TEST_NAME "wcsncat"
> +# define generic_strncat generic_wcsncat
>  #endif /* WIDE */
>  #include "bench-string.h"
>  
>  #define BIG_CHAR MAX_CHAR
>  
>  #ifndef WIDE
> -# define SIMPLE_STRNCAT simple_strncat
> -# define STUPID_STRNCAT stupid_strncat
>  # define SMALL_CHAR 127
>  #else
> -# define SIMPLE_STRNCAT simple_wcsncat
> -# define STUPID_STRNCAT stupid_wcsncat
>  # define SMALL_CHAR 1273
>  #endif /* WIDE */
>  
>  typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
> -CHAR *STUPID_STRNCAT (CHAR *, const CHAR *, size_t);
> -CHAR *SIMPLE_STRNCAT (CHAR *, const CHAR *, size_t);
> -
> -IMPL (STUPID_STRNCAT, 0)
> -IMPL (STRNCAT, 2)
>  
>  CHAR *
> -STUPID_STRNCAT (CHAR *dst, const CHAR *src, size_t n)
> +generic_strncat (CHAR *dst, const CHAR *src, size_t n)
>  {
> -  CHAR *ret = dst;
> -  while (*dst++ != '\0');
> -  --dst;
> -  while (n--)
> -    if ((*dst++ = *src++) == '\0')
> -      return ret;
> -  *dst = '\0';
> -  return ret;
> +  CHAR *end = dst + STRLEN (dst);
> +  n = STRNLEN (src, n);
> +  end[n] = 0;
> +  MEMCPY (end, src, n);
> +  return dst;
>  }
>  
> +IMPL (STRNCAT, 2)
> +IMPL (generic_strncat, 0)
> +
>  static void
>  do_one_test (impl_t *impl, CHAR *dst, const CHAR *src, size_t n)
>  {

Ok.

> diff --git a/benchtests/bench-strncpy.c b/benchtests/bench-strncpy.c
> index 35744c1bd6fd32390d89b87ed81b8260822dba3f..93bd6d54bf79a287f7f1501a2135a25f02e6eeb0 100644
> --- a/benchtests/bench-strncpy.c
> +++ b/benchtests/bench-strncpy.c
> @@ -31,49 +31,22 @@
>  #  define TEST_NAME "strncpy"
>  # else
>  #  define TEST_NAME "wcsncpy"
> +#  define generic_strncpy generic_wcsncpy
>  # endif /* WIDE */
>  # include "bench-string.h"
> -# ifndef WIDE
> -#  define SIMPLE_STRNCPY simple_strncpy
> -#  define STUPID_STRNCPY stupid_strncpy
> -# else
> -#  define SIMPLE_STRNCPY simple_wcsncpy
> -#  define STUPID_STRNCPY stupid_wcsncpy
> -# endif /* WIDE */
> -
> -CHAR *SIMPLE_STRNCPY (CHAR *, const CHAR *, size_t);
> -CHAR *STUPID_STRNCPY (CHAR *, const CHAR *, size_t);
> -
> -IMPL (STUPID_STRNCPY, 0)
> -IMPL (SIMPLE_STRNCPY, 0)
> -IMPL (STRNCPY, 1)
>  
>  CHAR *
> -SIMPLE_STRNCPY (CHAR *dst, const CHAR *src, size_t n)
> +generic_strncpy (CHAR *dst, const CHAR *src, size_t n)
>  {
> -  CHAR *ret = dst;
> -  while (n--)
> -    if ((*dst++ = *src++) == '\0')
> -      {
> -	while (n--)
> -	  *dst++ = '\0';
> -	return ret;
> -      }
> -  return ret;
> +  size_t nc = STRNLEN (src, n);
> +  if (nc != n)
> +    MEMSET (dst + nc, 0, n - nc);
> +  return MEMCPY (dst, src, nc);
>  }
>  
> -CHAR *
> -STUPID_STRNCPY (CHAR *dst, const CHAR *src, size_t n)
> -{
> -  size_t nc = STRNLEN (src, n);
> -  size_t i;
> +IMPL (STRNCPY, 1)
> +IMPL (generic_strncpy, 0)
>  
> -  for (i = 0; i < nc; ++i)
> -    dst[i] = src[i];
> -  for (; i < n; ++i)
> -    dst[i] = '\0';
> -  return dst;
> -}
>  #endif /* !STRNCPY_RESULT */
>  
>  typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);

Ok.

> diff --git a/benchtests/bench-strnlen.c b/benchtests/bench-strnlen.c
> index b9039d5f3fcd27c2f37204cb9634fec55f0fe0fe..e9e51b27fc37cb152cc5ef7b3869be1709af2540 100644
> --- a/benchtests/bench-strnlen.c
> +++ b/benchtests/bench-strnlen.c
> @@ -21,6 +21,8 @@
>  # define TEST_NAME "strnlen"
>  #else
>  # define TEST_NAME "wcsnlen"
> +# define generic_strnlen generic_wcsnlen
> +# define memchr_strnlen wcschr_wcsnlen
>  #endif /* WIDE */
>  #include "bench-string.h"
>  
> @@ -28,27 +30,24 @@
>  
>  #ifndef WIDE
>  # define MIDDLE_CHAR 127
> -# define SIMPLE_STRNLEN simple_strnlen
>  #else
>  # define MIDDLE_CHAR 1121
> -# define SIMPLE_STRNLEN simple_wcsnlen
>  #endif /* WIDE */
>  
>  typedef size_t (*proto_t) (const CHAR *, size_t);
> -size_t SIMPLE_STRNLEN (const CHAR *, size_t);
> -
> -IMPL (SIMPLE_STRNLEN, 0)
> -IMPL (STRNLEN, 1)
> +size_t generic_strnlen (const CHAR *, size_t);
>  
>  size_t
> -SIMPLE_STRNLEN (const CHAR *s, size_t maxlen)
> +memchr_strnlen (const CHAR *s, size_t maxlen)
>  {
> -  size_t i;
> -
> -  for (i = 0; i < maxlen && s[i]; ++i);
> -  return i;
> +  const CHAR *s1 = MEMCHR (s, 0, maxlen);
> +  return (s1 == NULL) ? maxlen : s1 - s;
>  }
>  
> +IMPL (STRNLEN, 1)
> +IMPL (memchr_strnlen, 0)
> +IMPL (generic_strnlen, 0)
> +
>  static void
>  do_one_test (impl_t *impl, const CHAR *s, size_t maxlen, size_t exp_len)
>  {
> @@ -146,3 +145,13 @@ test_main (void)
>  }
>  
>  #include <support/test-driver.c>
> +
> +#define libc_hidden_def(X)
> +#ifndef WIDE
> +# undef STRNLEN
> +# define STRNLEN generic_strnlen
> +# include <string/strnlen.c>
> +#else
> +# define WCSNLEN generic_strnlen
> +# include <wcsmbs/wcsnlen.c>
> +#endif
> 

Ok.
  

Patch

diff --git a/benchtests/bench-stpcpy.c b/benchtests/bench-stpcpy.c
index 74ea54f59417d82f6f70ef20279adff96ea78238..bcea9af1bf4d251665c978abb8f60305f054caf4 100644
--- a/benchtests/bench-stpcpy.c
+++ b/benchtests/bench-stpcpy.c
@@ -22,24 +22,18 @@ 
 # define TEST_NAME "stpcpy"
 #else
 # define TEST_NAME "wcpcpy"
+# define generic_stpcpy generic_wcpcpy
 #endif /* WIDE */
 #include "bench-string.h"
-#ifndef WIDE
-# define SIMPLE_STPCPY simple_stpcpy
-#else
-# define SIMPLE_STPCPY simple_wcpcpy
-#endif /* WIDE */
-
-CHAR *SIMPLE_STPCPY (CHAR *, const CHAR *);
-
-IMPL (SIMPLE_STPCPY, 0)
-IMPL (STPCPY, 1)
 
 CHAR *
-SIMPLE_STPCPY (CHAR *dst, const CHAR *src)
+generic_stpcpy (CHAR *dst, const CHAR *src)
 {
-  while ((*dst++ = *src++) != '\0');
-  return dst - 1;
+  size_t len = STRLEN (src);
+  return (CHAR *) MEMCPY (dst, src, len + 1) + len;
 }
 
+IMPL (STPCPY, 1)
+IMPL (generic_stpcpy, 0)
+
 #include "bench-strcpy.c"
diff --git a/benchtests/bench-stpncpy.c b/benchtests/bench-stpncpy.c
index 0470695889008ad679eb5131fd67826a45a05748..c4c6b65bb75b0271dadc816f7c028a042234b31f 100644
--- a/benchtests/bench-stpncpy.c
+++ b/benchtests/bench-stpncpy.c
@@ -22,49 +22,22 @@ 
 # define TEST_NAME "stpncpy"
 #else
 # define TEST_NAME "wcpncpy"
+# define generic_stpncpy generic_wcpncpy
 #endif /* WIDE */
 #include "bench-string.h"
-#ifndef WIDE
-# define SIMPLE_STPNCPY simple_stpncpy
-# define STUPID_STPNCPY stupid_stpncpy
-#else
-# define SIMPLE_STPNCPY simple_wcpncpy
-# define STUPID_STPNCPY stupid_wcpncpy
-#endif /* WIDE */
-
-CHAR *SIMPLE_STPNCPY (CHAR *, const CHAR *, size_t);
-CHAR *STUPID_STPNCPY (CHAR *, const CHAR *, size_t);
-
-IMPL (STUPID_STPNCPY, 0)
-IMPL (SIMPLE_STPNCPY, 0)
-IMPL (STPNCPY, 1)
-
-CHAR *
-SIMPLE_STPNCPY (CHAR *dst, const CHAR *src, size_t n)
-{
-  while (n--)
-    if ((*dst++ = *src++) == '\0')
-      {
-	size_t i;
-
-	for (i = 0; i < n; ++i)
-	  dst[i] = '\0';
-	return dst - 1;
-      }
-  return dst;
-}
 
 CHAR *
-STUPID_STPNCPY (CHAR *dst, const CHAR *src, size_t n)
+generic_stpncpy (CHAR *dst, const CHAR *src, size_t n)
 {
   size_t nc = STRNLEN (src, n);
-  size_t i;
-
-  for (i = 0; i < nc; ++i)
-    dst[i] = src[i];
-  for (; i < n; ++i)
-    dst[i] = '\0';
-  return dst + nc;
+  MEMCPY (dst, src, nc);
+  dst += nc;
+  if (nc == n)
+    return dst;
+  return MEMSET (dst, 0, n - nc);
 }
 
+IMPL (STPNCPY, 1)
+IMPL (generic_stpncpy, 0)
+
 #include "bench-strncpy.c"
diff --git a/benchtests/bench-strcat.c b/benchtests/bench-strcat.c
index a21d94a28e1ed55734c92e3eb617705cb42549cc..39d9fefb098c194523515e10cc4f47529b3aafd9 100644
--- a/benchtests/bench-strcat.c
+++ b/benchtests/bench-strcat.c
@@ -21,6 +21,7 @@ 
 # define TEST_NAME "strcat"
 #else
 # define TEST_NAME "wcscat"
+# define generic_strcat generic_wcscat
 #endif /* WIDE */
 #include "bench-string.h"
 
@@ -28,31 +29,25 @@ 
 
 #ifndef WIDE
 # define sfmt "s"
-# define SIMPLE_STRCAT simple_strcat
 # define SMALL_CHAR 127
 #else
 # define sfmt "ls"
-# define SIMPLE_STRCAT simple_wcscat
 # define SMALL_CHAR 1273
 #endif /* WIDE */
 
 
 typedef CHAR *(*proto_t) (CHAR *, const CHAR *);
-CHAR *SIMPLE_STRCAT (CHAR *, const CHAR *);
-
-IMPL (SIMPLE_STRCAT, 0)
-IMPL (STRCAT, 1)
 
 CHAR *
-SIMPLE_STRCAT (CHAR *dst, const CHAR *src)
+generic_strcat (CHAR *dst, const CHAR *src)
 {
-  CHAR *ret = dst;
-  while (*dst++ != '\0');
-  --dst;
-  while ((*dst++ = *src++) != '\0');
-  return ret;
+  STRCPY (dst + STRLEN (dst), src);
+  return dst;
 }
 
+IMPL (STRCAT, 1)
+IMPL (generic_strcat, 0)
+
 static void
 do_one_test (impl_t *impl, CHAR *dst, const CHAR *src)
 {
diff --git a/benchtests/bench-strcpy.c b/benchtests/bench-strcpy.c
index 9fe999e5f4584b9034c19fb4a90b7cbd6deccd00..7a7cf4abb2873a555c5d8c3eb9d55d2f5c44df4e 100644
--- a/benchtests/bench-strcpy.c
+++ b/benchtests/bench-strcpy.c
@@ -33,26 +33,19 @@ 
 #  define TEST_NAME "strcpy"
 # else
 #  define TEST_NAME "wcscpy"
+#  define generic_strcpy generic_wcscpy
 # endif
-# include "bench-string.h"
-# ifndef WIDE
-#  define SIMPLE_STRCPY simple_strcpy
-# else
-#  define SIMPLE_STRCPY simple_wcscpy
-# endif
-
-CHAR *SIMPLE_STRCPY (CHAR *, const CHAR *);
-
-IMPL (SIMPLE_STRCPY, 0)
-IMPL (STRCPY, 1)
+#include "bench-string.h"
 
 CHAR *
-SIMPLE_STRCPY (CHAR *dst, const CHAR *src)
+generic_strcpy (CHAR *dst, const CHAR *src)
 {
-  CHAR *ret = dst;
-  while ((*dst++ = *src++) != '\0');
-  return ret;
+  return MEMCPY (dst, src, STRLEN (src) + 1);
 }
+
+IMPL (STRCPY, 1)
+IMPL (generic_strcpy, 0)
+
 #endif
 
 typedef CHAR *(*proto_t) (CHAR *, const CHAR *);
diff --git a/benchtests/bench-strlen.c b/benchtests/bench-strlen.c
index f6a8bf5dff6ff4410ab46997e48a173249497e7f..47363af0f749110acdacd87bd8c58a9a676fe43c 100644
--- a/benchtests/bench-strlen.c
+++ b/benchtests/bench-strlen.c
@@ -21,6 +21,8 @@ 
 # define TEST_NAME "strlen"
 #else
 # define TEST_NAME "wcslen"
+# define generic_strlen generic_wcslen
+# define memchr_strlen wcschr_wcslen
 #endif
 #include "bench-string.h"
 
diff --git a/benchtests/bench-strncat.c b/benchtests/bench-strncat.c
index 386eafa429f1456d85cde76b308a5f0907debdca..7271626d506f7a0b71cd2f46e641759567d17645 100644
--- a/benchtests/bench-strncat.c
+++ b/benchtests/bench-strncat.c
@@ -21,41 +21,33 @@ 
 # define TEST_NAME "strncat"
 #else
 # define TEST_NAME "wcsncat"
+# define generic_strncat generic_wcsncat
 #endif /* WIDE */
 #include "bench-string.h"
 
 #define BIG_CHAR MAX_CHAR
 
 #ifndef WIDE
-# define SIMPLE_STRNCAT simple_strncat
-# define STUPID_STRNCAT stupid_strncat
 # define SMALL_CHAR 127
 #else
-# define SIMPLE_STRNCAT simple_wcsncat
-# define STUPID_STRNCAT stupid_wcsncat
 # define SMALL_CHAR 1273
 #endif /* WIDE */
 
 typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
-CHAR *STUPID_STRNCAT (CHAR *, const CHAR *, size_t);
-CHAR *SIMPLE_STRNCAT (CHAR *, const CHAR *, size_t);
-
-IMPL (STUPID_STRNCAT, 0)
-IMPL (STRNCAT, 2)
 
 CHAR *
-STUPID_STRNCAT (CHAR *dst, const CHAR *src, size_t n)
+generic_strncat (CHAR *dst, const CHAR *src, size_t n)
 {
-  CHAR *ret = dst;
-  while (*dst++ != '\0');
-  --dst;
-  while (n--)
-    if ((*dst++ = *src++) == '\0')
-      return ret;
-  *dst = '\0';
-  return ret;
+  CHAR *end = dst + STRLEN (dst);
+  n = STRNLEN (src, n);
+  end[n] = 0;
+  MEMCPY (end, src, n);
+  return dst;
 }
 
+IMPL (STRNCAT, 2)
+IMPL (generic_strncat, 0)
+
 static void
 do_one_test (impl_t *impl, CHAR *dst, const CHAR *src, size_t n)
 {
diff --git a/benchtests/bench-strncpy.c b/benchtests/bench-strncpy.c
index 35744c1bd6fd32390d89b87ed81b8260822dba3f..93bd6d54bf79a287f7f1501a2135a25f02e6eeb0 100644
--- a/benchtests/bench-strncpy.c
+++ b/benchtests/bench-strncpy.c
@@ -31,49 +31,22 @@ 
 #  define TEST_NAME "strncpy"
 # else
 #  define TEST_NAME "wcsncpy"
+#  define generic_strncpy generic_wcsncpy
 # endif /* WIDE */
 # include "bench-string.h"
-# ifndef WIDE
-#  define SIMPLE_STRNCPY simple_strncpy
-#  define STUPID_STRNCPY stupid_strncpy
-# else
-#  define SIMPLE_STRNCPY simple_wcsncpy
-#  define STUPID_STRNCPY stupid_wcsncpy
-# endif /* WIDE */
-
-CHAR *SIMPLE_STRNCPY (CHAR *, const CHAR *, size_t);
-CHAR *STUPID_STRNCPY (CHAR *, const CHAR *, size_t);
-
-IMPL (STUPID_STRNCPY, 0)
-IMPL (SIMPLE_STRNCPY, 0)
-IMPL (STRNCPY, 1)
 
 CHAR *
-SIMPLE_STRNCPY (CHAR *dst, const CHAR *src, size_t n)
+generic_strncpy (CHAR *dst, const CHAR *src, size_t n)
 {
-  CHAR *ret = dst;
-  while (n--)
-    if ((*dst++ = *src++) == '\0')
-      {
-	while (n--)
-	  *dst++ = '\0';
-	return ret;
-      }
-  return ret;
+  size_t nc = STRNLEN (src, n);
+  if (nc != n)
+    MEMSET (dst + nc, 0, n - nc);
+  return MEMCPY (dst, src, nc);
 }
 
-CHAR *
-STUPID_STRNCPY (CHAR *dst, const CHAR *src, size_t n)
-{
-  size_t nc = STRNLEN (src, n);
-  size_t i;
+IMPL (STRNCPY, 1)
+IMPL (generic_strncpy, 0)
 
-  for (i = 0; i < nc; ++i)
-    dst[i] = src[i];
-  for (; i < n; ++i)
-    dst[i] = '\0';
-  return dst;
-}
 #endif /* !STRNCPY_RESULT */
 
 typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
diff --git a/benchtests/bench-strnlen.c b/benchtests/bench-strnlen.c
index b9039d5f3fcd27c2f37204cb9634fec55f0fe0fe..e9e51b27fc37cb152cc5ef7b3869be1709af2540 100644
--- a/benchtests/bench-strnlen.c
+++ b/benchtests/bench-strnlen.c
@@ -21,6 +21,8 @@ 
 # define TEST_NAME "strnlen"
 #else
 # define TEST_NAME "wcsnlen"
+# define generic_strnlen generic_wcsnlen
+# define memchr_strnlen wcschr_wcsnlen
 #endif /* WIDE */
 #include "bench-string.h"
 
@@ -28,27 +30,24 @@ 
 
 #ifndef WIDE
 # define MIDDLE_CHAR 127
-# define SIMPLE_STRNLEN simple_strnlen
 #else
 # define MIDDLE_CHAR 1121
-# define SIMPLE_STRNLEN simple_wcsnlen
 #endif /* WIDE */
 
 typedef size_t (*proto_t) (const CHAR *, size_t);
-size_t SIMPLE_STRNLEN (const CHAR *, size_t);
-
-IMPL (SIMPLE_STRNLEN, 0)
-IMPL (STRNLEN, 1)
+size_t generic_strnlen (const CHAR *, size_t);
 
 size_t
-SIMPLE_STRNLEN (const CHAR *s, size_t maxlen)
+memchr_strnlen (const CHAR *s, size_t maxlen)
 {
-  size_t i;
-
-  for (i = 0; i < maxlen && s[i]; ++i);
-  return i;
+  const CHAR *s1 = MEMCHR (s, 0, maxlen);
+  return (s1 == NULL) ? maxlen : s1 - s;
 }
 
+IMPL (STRNLEN, 1)
+IMPL (memchr_strnlen, 0)
+IMPL (generic_strnlen, 0)
+
 static void
 do_one_test (impl_t *impl, const CHAR *s, size_t maxlen, size_t exp_len)
 {
@@ -146,3 +145,13 @@  test_main (void)
 }
 
 #include <support/test-driver.c>
+
+#define libc_hidden_def(X)
+#ifndef WIDE
+# undef STRNLEN
+# define STRNLEN generic_strnlen
+# include <string/strnlen.c>
+#else
+# define WCSNLEN generic_strnlen
+# include <wcsmbs/wcsnlen.c>
+#endif