diff options
author | Siddhesh Poyarekar <siddhesh@redhat.com> | 2013-06-04 16:48:56 +0530 |
---|---|---|
committer | Siddhesh Poyarekar <siddhesh@redhat.com> | 2013-06-11 15:08:13 +0530 |
commit | 9702047480d9002522936c5e1e1ebe16f696880d (patch) | |
tree | 9b37e288e4d57012a6186c280fd8837deca6dd4c /benchtests | |
parent | c1f75dc386d533806d29b7e94118363a7b50eed8 (diff) | |
download | glibc-9702047480d9002522936c5e1e1ebe16f696880d.tar.gz glibc-9702047480d9002522936c5e1e1ebe16f696880d.tar.xz glibc-9702047480d9002522936c5e1e1ebe16f696880d.zip |
Copy over string performance tests into benchtests
Copy over already existing string performance tests into benchtests. Bits not related to performance measurements have been omitted.
Diffstat (limited to 'benchtests')
61 files changed, 4991 insertions, 1 deletions
diff --git a/benchtests/Makefile b/benchtests/Makefile index 27d83f45a7..5023c7c9c2 100644 --- a/benchtests/Makefile +++ b/benchtests/Makefile @@ -24,7 +24,10 @@ bench := acos acosh asin asinh atan atanh cos cosh exp log modf pow rint sin \ sinh tan tanh # String function benchmarks. -string-bench := memcpy +string-bench := bcopy bzero memccpy memchr memcmp memmem memmove mempcpy \ + memset rawmemchr stpcpy stpncpy strcasecmp strcasestr strcat \ + strchr strchrnul strcmp strcpy strcspn strlen strncasecmp \ + strncat strncmp strncpy strnlen strpbrk strrchr strspn strstr string-bench-ifunc := $(addsuffix -ifunc, $(string-bench)) string-bench-all := $(string-bench) $(string-bench-ifunc) diff --git a/benchtests/bench-bcopy-ifunc.c b/benchtests/bench-bcopy-ifunc.c new file mode 100644 index 0000000000..66020e9387 --- /dev/null +++ b/benchtests/bench-bcopy-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of bcopy function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-bcopy.c" diff --git a/benchtests/bench-bcopy.c b/benchtests/bench-bcopy.c new file mode 100644 index 0000000000..4d0d055906 --- /dev/null +++ b/benchtests/bench-bcopy.c @@ -0,0 +1,20 @@ +/* Measure bcopy functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_BCOPY +#include "bench-memmove.c" diff --git a/benchtests/bench-bzero-ifunc.c b/benchtests/bench-bzero-ifunc.c new file mode 100644 index 0000000000..84f1354dce --- /dev/null +++ b/benchtests/bench-bzero-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of bzero function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-bzero.c" diff --git a/benchtests/bench-bzero.c b/benchtests/bench-bzero.c new file mode 100644 index 0000000000..18e7d17461 --- /dev/null +++ b/benchtests/bench-bzero.c @@ -0,0 +1,19 @@ +/* Measure bzero functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ +#define TEST_BZERO +#include "bench-memset.c" diff --git a/benchtests/bench-memccpy-ifunc.c b/benchtests/bench-memccpy-ifunc.c new file mode 100644 index 0000000000..b61050f8b7 --- /dev/null +++ b/benchtests/bench-memccpy-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of memccpy function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-memccpy.c" diff --git a/benchtests/bench-memccpy.c b/benchtests/bench-memccpy.c new file mode 100644 index 0000000000..612513c68d --- /dev/null +++ b/benchtests/bench-memccpy.c @@ -0,0 +1,169 @@ +/* Measure memccpy functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "memccpy" +#include "bench-string.h" + +void *simple_memccpy (void *, const void *, int, size_t); +void *stupid_memccpy (void *, const void *, int, size_t); + +IMPL (stupid_memccpy, 0) +IMPL (simple_memccpy, 0) +IMPL (memccpy, 1) + +void * +simple_memccpy (void *dst, const void *src, int c, size_t n) +{ + const char *s = src; + char *d = dst; + + while (n-- > 0) + if ((*d++ = *s++) == (char) c) + return d; + + return NULL; +} + +void * +stupid_memccpy (void *dst, const void *src, int c, size_t n) +{ + void *p = memchr (src, c, n); + + if (p != NULL) + return mempcpy (dst, src, p - src + 1); + + memcpy (dst, src, n); + return NULL; +} + +typedef void *(*proto_t) (void *, const void *, int c, size_t); + +static void +do_one_test (impl_t *impl, void *dst, const void *src, int c, size_t len, + size_t n) +{ + void *expect = len > n ? NULL : (char *) dst + len; + if (CALL (impl, dst, src, c, n) != expect) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + CALL (impl, dst, src, c, n), expect); + ret = 1; + return; + } + + if (memcmp (dst, src, len > n ? n : len) != 0) + { + error (0, 0, "Wrong result in function %s", impl->name); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute__ ((unused)); + hp_timing_t stop __attribute__ ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, dst, src, c, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, int c, size_t len, size_t n, + int max_char) +{ + size_t i; + char *s1, *s2; + + align1 &= 7; + if (align1 + len >= page_size) + return; + + align2 &= 7; + if (align2 + len >= page_size) + return; + + s1 = (char *) (buf1 + align1); + s2 = (char *) (buf2 + align2); + + for (i = 0; i < len - 1; ++i) + { + s1[i] = 32 + 23 * i % (max_char - 32); + if (s1[i] == (char) c) + --s1[i]; + } + s1[len - 1] = c; + for (i = len; i + align1 < page_size && i < len + 64; ++i) + s1[i] = 32 + 32 * i % (max_char - 32); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, n %4zd, char %d, alignment %2zd/%2zd:", len, n, c, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, s1, c, len, n); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%28s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (i, i, 12, 16, 16, 127); + do_test (i, i, 23, 16, 16, 255); + do_test (i, 2 * i, 28, 16, 16, 127); + do_test (2 * i, i, 31, 16, 16, 255); + do_test (8 - i, 2 * i, 1, 1 << i, 2 << i, 127); + do_test (2 * i, 8 - i, 17, 2 << i, 1 << i, 127); + do_test (8 - i, 2 * i, 0, 1 << i, 2 << i, 255); + do_test (2 * i, 8 - i, i, 2 << i, 1 << i, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, i, 4 << i, 8 << i, 127); + do_test (0, 0, i, 16 << i, 8 << i, 127); + do_test (8 - i, 2 * i, i, 4 << i, 8 << i, 127); + do_test (8 - i, 2 * i, i, 16 << i, 8 << i, 127); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-memchr-ifunc.c b/benchtests/bench-memchr-ifunc.c new file mode 100644 index 0000000000..dd2c39f22f --- /dev/null +++ b/benchtests/bench-memchr-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of memchr function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-memchr.c" diff --git a/benchtests/bench-memchr.c b/benchtests/bench-memchr.c new file mode 100644 index 0000000000..5470ce6c5b --- /dev/null +++ b/benchtests/bench-memchr.c @@ -0,0 +1,137 @@ +/* Measure memchr functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "memchr" +#include "bench-string.h" + +typedef char *(*proto_t) (const char *, int, size_t); +char *simple_memchr (const char *, int, size_t); + +IMPL (simple_memchr, 0) +IMPL (memchr, 1) + +char * +simple_memchr (const char *s, int c, size_t n) +{ + while (n--) + if (*s++ == (char) c) + return (char *) s - 1; + return NULL; +} + +static void +do_one_test (impl_t *impl, const char *s, int c, size_t n, char *exp_res) +{ + char *res = CALL (impl, s, c, n); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len, int seek_char) +{ + size_t i; + char *result; + + align &= 7; + if (align + len >= page_size) + return; + + for (i = 0; i < len; ++i) + { + buf1[align + i] = 1 + 23 * i % 127; + if (buf1[align + i] == seek_char) + buf1[align + i] = seek_char + 1; + } + buf1[align + len] = 0; + + if (pos < len) + { + buf1[align + pos] = seek_char; + buf1[align + len] = -seek_char; + result = (char *) (buf1 + align + pos); + } + else + { + result = NULL; + buf1[align + len] = seek_char; + } + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", pos, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, (char *) (buf1 + align), seek_char, len, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 23); + do_test (i, 64, 256, 23); + do_test (0, 16 << i, 2048, 0); + do_test (i, 64, 256, 0); + } + for (i = 1; i < 32; ++i) + { + do_test (0, i, i + 1, 23); + do_test (0, i, i + 1, 0); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-memcmp-ifunc.c b/benchtests/bench-memcmp-ifunc.c new file mode 100644 index 0000000000..44671641fa --- /dev/null +++ b/benchtests/bench-memcmp-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of memcmp function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-memcmp.c" diff --git a/benchtests/bench-memcmp.c b/benchtests/bench-memcmp.c new file mode 100644 index 0000000000..053bb50567 --- /dev/null +++ b/benchtests/bench-memcmp.c @@ -0,0 +1,183 @@ +/* Measure memcmp functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#ifdef WIDE +# define TEST_NAME "wmemcmp" +#else +# define TEST_NAME "memcmp" +#endif +#include "bench-string.h" +#ifdef WIDE +# include <inttypes.h> +# include <wchar.h> + +# define MEMCMP wmemcmp +# define MEMCPY wmemcpy +# define SIMPLE_MEMCMP simple_wmemcmp +# define CHAR wchar_t +# define UCHAR wchar_t +# define CHARBYTES 4 +# define CHAR__MIN WCHAR_MIN +# define CHAR__MAX WCHAR_MAX +int +simple_wmemcmp (const wchar_t *s1, const wchar_t *s2, size_t n) +{ + int ret = 0; + /* Warning! + wmemcmp has to use SIGNED comparison for elements. + memcmp has to use UNSIGNED comparison for elemnts. + */ + while (n-- && (ret = *s1 < *s2 ? -1 : *s1 == *s2 ? 0 : 1) == 0) {s1++; s2++;} + return ret; +} +#else +# include <limits.h> + +# define MEMCMP memcmp +# define MEMCPY memcpy +# define SIMPLE_MEMCMP simple_memcmp +# define CHAR char +# define MAX_CHAR 255 +# define UCHAR unsigned char +# define CHARBYTES 1 +# define CHAR__MIN CHAR_MIN +# define CHAR__MAX CHAR_MAX + +int +simple_memcmp (const char *s1, const char *s2, size_t n) +{ + int ret = 0; + + while (n-- && (ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) == 0); + return ret; +} +#endif + +typedef int (*proto_t) (const CHAR *, const CHAR *, size_t); + +IMPL (SIMPLE_MEMCMP, 0) +IMPL (MEMCMP, 1) + +static void +do_one_test (impl_t *impl, const CHAR *s1, const CHAR *s2, size_t len, + int exp_result) +{ + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2, len); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, int exp_result) +{ + size_t i; + CHAR *s1, *s2; + + if (len == 0) + return; + + align1 &= 63; + if (align1 + (len + 1) * CHARBYTES >= page_size) + return; + + align2 &= 63; + if (align2 + (len + 1) * CHARBYTES >= page_size) + return; + + s1 = (CHAR *) (buf1 + align1); + s2 = (CHAR *) (buf2 + align2); + + for (i = 0; i < len; i++) + s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % CHAR__MAX; + + s1[len] = align1; + s2[len] = align2; + s2[len - 1] -= exp_result; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, len, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 16; ++i) + { + do_test (i * CHARBYTES, i * CHARBYTES, i, 0); + do_test (i * CHARBYTES, i * CHARBYTES, i, 1); + do_test (i * CHARBYTES, i * CHARBYTES, i, -1); + } + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, 0); + do_test (0, 0, i, 1); + do_test (0, 0, i, -1); + } + + for (i = 1; i < 10; ++i) + { + do_test (0, 0, 2 << i, 0); + do_test (0, 0, 2 << i, 1); + do_test (0, 0, 2 << i, -1); + do_test (0, 0, 16 << i, 0); + do_test ((8 - i) * CHARBYTES, (2 * i) * CHARBYTES, 16 << i, 0); + do_test (0, 0, 16 << i, 1); + do_test (0, 0, 16 << i, -1); + } + + for (i = 1; i < 8; ++i) + { + do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, 0); + do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, 1); + do_test (i * CHARBYTES, 2 * (i * CHARBYTES), 8 << i, -1); + } + + return ret; +} +#include "../test-skeleton.c" diff --git a/benchtests/bench-memmem-ifunc.c b/benchtests/bench-memmem-ifunc.c new file mode 100644 index 0000000000..6b951d8084 --- /dev/null +++ b/benchtests/bench-memmem-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of memmem function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-memmem.c" diff --git a/benchtests/bench-memmem.c b/benchtests/bench-memmem.c new file mode 100644 index 0000000000..ca758a84f2 --- /dev/null +++ b/benchtests/bench-memmem.c @@ -0,0 +1,172 @@ +/* Measure memmem functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "memmem" +#define BUF1PAGES 20 +#define ITERATIONS 500 +#include "bench-string.h" + +typedef char *(*proto_t) (const void *, size_t, const void *, size_t); +void *simple_memmem (const void *, size_t, const void *, size_t); + +IMPL (simple_memmem, 0) +IMPL (memmem, 1) + +void * +simple_memmem (const void *haystack, size_t haystack_len, const void *needle, + size_t needle_len) +{ + const char *begin; + const char *const last_possible + = (const char *) haystack + haystack_len - needle_len; + + if (needle_len == 0) + /* The first occurrence of the empty string is deemed to occur at + the beginning of the string. */ + return (void *) haystack; + + /* Sanity check, otherwise the loop might search through the whole + memory. */ + if (__builtin_expect (haystack_len < needle_len, 0)) + return NULL; + + for (begin = (const char *) haystack; begin <= last_possible; ++begin) + if (begin[0] == ((const char *) needle)[0] && + !memcmp ((const void *) &begin[1], + (const void *) ((const char *) needle + 1), + needle_len - 1)) + return (void *) begin; + + return NULL; +} + +static void +do_one_test (impl_t *impl, const void *haystack, size_t haystack_len, + const void *needle, size_t needle_len, const void *expected) +{ + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, haystack, haystack_len, needle, needle_len); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (const char *str, size_t len, size_t idx) +{ + char tmpbuf[len]; + + memcpy (tmpbuf, buf1 + idx, len); + memcpy (buf1 + idx, str, len); + + if (HP_TIMING_AVAIL) + printf ("String %s, offset %zd:", str, idx); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, buf1, BUF1PAGES * page_size, str, len, buf1 + idx); + + memcpy (buf1 + idx, tmpbuf, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_random_tests (void) +{ + for (size_t n = 0; n < ITERATIONS; ++n) + { + char tmpbuf[32]; + + size_t shift = random () % 11; + size_t rel = random () % ((2 << (shift + 1)) * 64); + size_t idx = MIN ((2 << shift) * 64 + rel, BUF1PAGES * page_size - 2); + size_t len = random () % (sizeof (tmpbuf) - 1) + 1; + len = MIN (len, BUF1PAGES * page_size - idx - 1); + memcpy (tmpbuf, buf1 + idx, len); + for (size_t i = random () % len / 2 + 1; i > 0; --i) + { + size_t off = random () % len; + char ch = '0' + random () % 10; + + buf1[idx + off] = ch; + } + + if (HP_TIMING_AVAIL) + printf ("String %.*s, offset %zd:", (int) len, buf1 + idx, idx); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, buf1, BUF1PAGES * page_size, buf1 + idx, len, + buf1 + idx); + + if (HP_TIMING_AVAIL) + putchar ('\n'); + + memcpy (buf1 + idx, tmpbuf, len); + } +} + +static const char *const strs[] = + { + "00000", "00112233", "0123456789", "0000111100001111", + "00000111110000022222", "012345678901234567890", + "abc0", "aaaa0", "abcabc0" + }; + + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < BUF1PAGES * page_size; ++i) + buf1[i] = 60 + random () % 32; + + for (i = 0; i < sizeof (strs) / sizeof (strs[0]); ++i) + for (size_t j = 0; j < 120; j += 7) + { + size_t len = strlen (strs[i]); + + do_test (strs[i], len, j); + } + + do_random_tests (); + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-memmove-ifunc.c b/benchtests/bench-memmove-ifunc.c new file mode 100644 index 0000000000..345e594331 --- /dev/null +++ b/benchtests/bench-memmove-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of memmove function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-memmove.c" diff --git a/benchtests/bench-memmove.c b/benchtests/bench-memmove.c new file mode 100644 index 0000000000..dccde5d14e --- /dev/null +++ b/benchtests/bench-memmove.c @@ -0,0 +1,187 @@ +/* Measure memmove functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#ifdef TEST_BCOPY +# define TEST_NAME "bcopy" +#else +# define TEST_NAME "memmove" +#endif +#include "bench-string.h" + +char *simple_memmove (char *, const char *, size_t); + +#ifdef TEST_BCOPY +typedef void (*proto_t) (const char *, char *, size_t); +void simple_bcopy (const char *, char *, size_t); + +IMPL (simple_bcopy, 0) +IMPL (bcopy, 1) + +void +simple_bcopy (const char *src, char *dst, size_t n) +{ + simple_memmove (dst, src, n); +} +#else +typedef char *(*proto_t) (char *, const char *, size_t); + +IMPL (simple_memmove, 0) +IMPL (memmove, 1) +#endif + +char * +simple_memmove (char *dst, const char *src, size_t n) +{ + char *ret = dst; + if (src < dst) + { + dst += n; + src += n; + while (n--) + *--dst = *--src; + } + else + while (n--) + *dst++ = *src++; + return ret; +} + +static void +do_one_test (impl_t *impl, char *dst, char *src, const char *orig_src, + size_t len) +{ + memcpy (src, orig_src, len); +#ifdef TEST_BCOPY + CALL (impl, src, dst, len); +#else + char *res; + + res = CALL (impl, dst, src, len); + if (res != dst) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, dst); + ret = 1; + return; + } +#endif + + if (memcmp (dst, orig_src, len) != 0) + { + error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"", + impl->name, dst, src); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); +#ifdef TEST_BCOPY + CALL (impl, src, dst, len); +#else + CALL (impl, dst, src, len); +#endif + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len) +{ + size_t i, j; + char *s1, *s2; + + align1 &= 63; + if (align1 + len >= page_size) + return; + + align2 &= 63; + if (align2 + len >= page_size) + return; + + s1 = (char *) (buf1 + align1); + s2 = (char *) (buf2 + align2); + + for (i = 0, j = 1; i < len; i++, j += 23) + s1[i] = j; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, (char *) (buf2 + align1), s1, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 14; ++i) + { + do_test (0, 32, 1 << i); + do_test (32, 0, 1 << i); + do_test (0, i, 1 << i); + do_test (i, 0, 1 << i); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, 32, i); + do_test (32, 0, i); + do_test (0, i, i); + do_test (i, 0, i); + } + + for (i = 3; i < 32; ++i) + { + if ((i & (i - 1)) == 0) + continue; + do_test (0, 32, 16 * i); + do_test (32, 0, 16 * i); + do_test (0, i, 16 * i); + do_test (i, 0, 16 * i); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-mempcpy-ifunc.c b/benchtests/bench-mempcpy-ifunc.c new file mode 100644 index 0000000000..4fa93e0722 --- /dev/null +++ b/benchtests/bench-mempcpy-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of mempcpy function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-mempcpy.c" diff --git a/benchtests/bench-mempcpy.c b/benchtests/bench-mempcpy.c new file mode 100644 index 0000000000..0e0e3b9e47 --- /dev/null +++ b/benchtests/bench-mempcpy.c @@ -0,0 +1,37 @@ +/* Measure mempcpy functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define MEMCPY_RESULT(dst, len) (dst) + (len) +#define TEST_MAIN +#define TEST_NAME "mempcpy" +#include "bench-string.h" + +char *simple_mempcpy (char *, const char *, size_t); + +IMPL (simple_mempcpy, 0) +IMPL (mempcpy, 1) + +char * +simple_mempcpy (char *dst, const char *src, size_t n) +{ + while (n--) + *dst++ = *src++; + return dst; +} + +#include "bench-memcpy.c" diff --git a/benchtests/bench-memset-ifunc.c b/benchtests/bench-memset-ifunc.c new file mode 100644 index 0000000000..1d43eef3c9 --- /dev/null +++ b/benchtests/bench-memset-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of memset function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-memset.c" diff --git a/benchtests/bench-memset.c b/benchtests/bench-memset.c new file mode 100644 index 0000000000..92e34f0d61 --- /dev/null +++ b/benchtests/bench-memset.c @@ -0,0 +1,169 @@ +/* Measure memset functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#ifdef TEST_BZERO +# define TEST_NAME "bzero" +#else +# define TEST_NAME "memset" +#endif +#define MIN_PAGE_SIZE 131072 +#include "bench-string.h" + +char *simple_memset (char *, int, size_t); + +#ifdef TEST_BZERO +typedef void (*proto_t) (char *, size_t); +void simple_bzero (char *, size_t); +void builtin_bzero (char *, size_t); + +IMPL (simple_bzero, 0) +IMPL (builtin_bzero, 0) +IMPL (bzero, 1) + +void +simple_bzero (char *s, size_t n) +{ + simple_memset (s, 0, n); +} + +void +builtin_bzero (char *s, size_t n) +{ + __builtin_bzero (s, n); +} +#else +typedef char *(*proto_t) (char *, int, size_t); +char *builtin_memset (char *, int, size_t); + +IMPL (simple_memset, 0) +IMPL (builtin_memset, 0) +IMPL (memset, 1) + +char * +builtin_memset (char *s, int c, size_t n) +{ + return __builtin_memset (s, c, n); +} +#endif + +char * +simple_memset (char *s, int c, size_t n) +{ + char *r = s, *end = s + n; + while (r < end) + *r++ = c; + return s; +} + +static void +do_one_test (impl_t *impl, char *s, int c __attribute ((unused)), size_t n) +{ + char tstbuf[n]; +#ifdef TEST_BZERO + simple_bzero (tstbuf, n); + CALL (impl, s, n); + if (memcmp (s, tstbuf, n) != 0) +#else + char *res = CALL (impl, s, c, n); + if (res != s + || simple_memset (tstbuf, c, n) != tstbuf + || memcmp (s, tstbuf, n) != 0) +#endif + { + error (0, 0, "Wrong result in function %s", impl->name); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); +#ifdef TEST_BZERO + CALL (impl, s, n); +#else + CALL (impl, s, c, n); +#endif + + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, int c, size_t len) +{ + align &= 7; + if (align + len > page_size) + return; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd, c %2d:", len, align, c); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, (char *) buf1 + align, c, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + int c = 0; + + test_init (); + + printf ("%24s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + +#ifndef TEST_BZERO + for (c = -65; c <= 130; c += 65) +#endif + { + for (i = 0; i < 18; ++i) + do_test (0, c, 1 << i); + for (i = 1; i < 32; ++i) + { + do_test (i, c, i); + if (i & (i - 1)) + do_test (0, c, i); + } + do_test (1, c, 14); + do_test (3, c, 1024); + do_test (4, c, 64); + do_test (2, c, 25); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-rawmemchr-ifunc.c b/benchtests/bench-rawmemchr-ifunc.c new file mode 100644 index 0000000000..b1e86f1f2f --- /dev/null +++ b/benchtests/bench-rawmemchr-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of rawmemchr function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-rawmemchr.c" diff --git a/benchtests/bench-rawmemchr.c b/benchtests/bench-rawmemchr.c new file mode 100644 index 0000000000..a6b29d7ae3 --- /dev/null +++ b/benchtests/bench-rawmemchr.c @@ -0,0 +1,133 @@ +/* Measure memchr functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <assert.h> + +#define TEST_MAIN +#define TEST_NAME "rawmemchr" +#include "bench-string.h" + +typedef char *(*proto_t) (const char *, int); +char *simple_rawmemchr (const char *, int); + +IMPL (simple_rawmemchr, 0) +IMPL (rawmemchr, 1) + +char * +simple_rawmemchr (const char *s, int c) +{ + while (1) + if (*s++ == (char) c) + return (char *) s - 1; + return NULL; +} + +static void +do_one_test (impl_t *impl, const char *s, int c, char *exp_res) +{ + char *res = CALL (impl, s, c); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len, int seek_char) +{ + size_t i; + char *result; + + align &= 7; + if (align + len >= page_size) + return; + + for (i = 0; i < len; ++i) + { + buf1[align + i] = 1 + 23 * i % 127; + if (buf1[align + i] == seek_char) + buf1[align + i] = seek_char + 1; + } + buf1[align + len] = 0; + + assert (pos < len); + + buf1[align + pos] = seek_char; + buf1[align + len] = -seek_char; + result = (char *) (buf1 + align + pos); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", pos, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, (char *) (buf1 + align), seek_char, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 7; ++i) + { + do_test (0, 16 << i, 2048, 23); + do_test (i, 64, 256, 23); + do_test (0, 16 << i, 2048, 0); + do_test (i, 64, 256, 0); + } + for (i = 1; i < 32; ++i) + { + do_test (0, i, i + 1, 23); + do_test (0, i, i + 1, 0); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-stpcpy-ifunc.c b/benchtests/bench-stpcpy-ifunc.c new file mode 100644 index 0000000000..d36bcb2c06 --- /dev/null +++ b/benchtests/bench-stpcpy-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of stpcpy function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-stpcpy.c" diff --git a/benchtests/bench-stpcpy.c b/benchtests/bench-stpcpy.c new file mode 100644 index 0000000000..0645298471 --- /dev/null +++ b/benchtests/bench-stpcpy.c @@ -0,0 +1,36 @@ +/* Measure stpcpy functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define STRCPY_RESULT(dst, len) ((dst) + (len)) +#define TEST_MAIN +#define TEST_NAME "stpcpy" +#include "bench-string.h" + +char *simple_stpcpy (char *, const char *); + +IMPL (simple_stpcpy, 0) +IMPL (stpcpy, 1) + +char * +simple_stpcpy (char *dst, const char *src) +{ + while ((*dst++ = *src++) != '\0'); + return dst - 1; +} + +#include "bench-strcpy.c" diff --git a/benchtests/bench-stpncpy-ifunc.c b/benchtests/bench-stpncpy-ifunc.c new file mode 100644 index 0000000000..736cac0429 --- /dev/null +++ b/benchtests/bench-stpncpy-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of stpncpy function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-stpncpy.c" diff --git a/benchtests/bench-stpncpy.c b/benchtests/bench-stpncpy.c new file mode 100644 index 0000000000..65ed800074 --- /dev/null +++ b/benchtests/bench-stpncpy.c @@ -0,0 +1,59 @@ +/* Measure stpncpy functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define STRNCPY_RESULT(dst, len, n) ((dst) + ((len) > (n) ? (n) : (len))) +#define TEST_MAIN +#define TEST_NAME "stpncpy" +#include "bench-string.h" + +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) +{ + 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; +} + +#include "bench-strncpy.c" diff --git a/benchtests/bench-strcasecmp-ifunc.c b/benchtests/bench-strcasecmp-ifunc.c new file mode 100644 index 0000000000..bdeb8c5808 --- /dev/null +++ b/benchtests/bench-strcasecmp-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strcasecmp function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strcasecmp.c" diff --git a/benchtests/bench-strcasecmp.c b/benchtests/bench-strcasecmp.c new file mode 100644 index 0000000000..27250bb447 --- /dev/null +++ b/benchtests/bench-strcasecmp.c @@ -0,0 +1,183 @@ +/* Measure strcasecmp functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ctype.h> +#define TEST_MAIN +#define TEST_NAME "strcasecmp" +#include "bench-string.h" + +typedef int (*proto_t) (const char *, const char *); +static int simple_strcasecmp (const char *, const char *); +static int stupid_strcasecmp (const char *, const char *); + +IMPL (stupid_strcasecmp, 0) +IMPL (simple_strcasecmp, 0) +IMPL (strcasecmp, 1) + +static int +simple_strcasecmp (const char *s1, const char *s2) +{ + int ret; + + while ((ret = ((unsigned char) tolower (*s1) + - (unsigned char) tolower (*s2))) == 0 + && *s1++) + ++s2; + return ret; +} + +static int +stupid_strcasecmp (const char *s1, const char *s2) +{ + size_t ns1 = strlen (s1) + 1, ns2 = strlen (s2) + 1; + size_t n = ns1 < ns2 ? ns1 : ns2; + int ret = 0; + + while (n--) + { + if ((ret = ((unsigned char) tolower (*s1) + - (unsigned char) tolower (*s2))) != 0) + break; + ++s1; + ++s2; + } + return ret; +} + +static void +do_one_test (impl_t *impl, const char *s1, const char *s2, int exp_result) +{ + int result = CALL (impl, s1, s2); + if ((exp_result == 0 && result != 0) + || (exp_result < 0 && result >= 0) + || (exp_result > 0 && result <= 0)) + { + error (0, 0, "Wrong result in function %s %d %d", impl->name, + result, exp_result); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, int max_char, + int exp_result) +{ + size_t i; + char *s1, *s2; + + if (len == 0) + return; + + align1 &= 7; + if (align1 + len + 1 >= page_size) + return; + + align2 &= 7; + if (align2 + len + 1 >= page_size) + return; + + s1 = (char *) (buf1 + align1); + s2 = (char *) (buf2 + align2); + + for (i = 0; i < len; i++) + { + s1[i] = toupper (1 + 23 * i % max_char); + s2[i] = tolower (s1[i]); + } + + s1[len] = s2[len] = 0; + s1[len + 1] = 23; + s2[len + 1] = 24 + exp_result; + if ((s2[len - 1] == 'z' && exp_result == -1) + || (s2[len - 1] == 'a' && exp_result == 1)) + s1[len - 1] += exp_result; + else + s2[len - 1] -= exp_result; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 16; ++i) + { + do_test (i, i, i, 127, 0); + do_test (i, i, i, 127, 1); + do_test (i, i, i, 127, -1); + } + + for (i = 1; i < 10; ++i) + { + do_test (0, 0, 2 << i, 127, 0); + do_test (0, 0, 2 << i, 254, 0); + do_test (0, 0, 2 << i, 127, 1); + do_test (0, 0, 2 << i, 254, 1); + do_test (0, 0, 2 << i, 127, -1); + do_test (0, 0, 2 << i, 254, -1); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, 8 << i, 127, 0); + do_test (2 * i, i, 8 << i, 254, 0); + do_test (i, 2 * i, 8 << i, 127, 1); + do_test (2 * i, i, 8 << i, 254, 1); + do_test (i, 2 * i, 8 << i, 127, -1); + do_test (2 * i, i, 8 << i, 254, -1); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strcasestr-ifunc.c b/benchtests/bench-strcasestr-ifunc.c new file mode 100644 index 0000000000..645f5041f9 --- /dev/null +++ b/benchtests/bench-strcasestr-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strcasestr function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strcasestr.c" diff --git a/benchtests/bench-strcasestr.c b/benchtests/bench-strcasestr.c new file mode 100644 index 0000000000..289b490746 --- /dev/null +++ b/benchtests/bench-strcasestr.c @@ -0,0 +1,186 @@ +/* Measure strcasestr functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "strcasestr" +#include "bench-string.h" + + +#define STRCASESTR simple_strcasestr +#define NO_ALIAS +#define __strncasecmp strncasecmp +#include "../string/strcasestr.c" + + +static char * +stupid_strcasestr (const char *s1, const char *s2) +{ + ssize_t s1len = strlen (s1); + ssize_t s2len = strlen (s2); + + if (s2len > s1len) + return NULL; + + for (ssize_t i = 0; i <= s1len - s2len; ++i) + { + size_t j; + for (j = 0; j < s2len; ++j) + if (tolower (s1[i + j]) != tolower (s2[j])) + break; + if (j == s2len) + return (char *) s1 + i; + } + + return NULL; +} + + +typedef char *(*proto_t) (const char *, const char *); + +IMPL (stupid_strcasestr, 0) +IMPL (simple_strcasestr, 0) +IMPL (strcasestr, 1) + + +static void +do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result) +{ + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~(hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + + +static void +do_test (size_t align1, size_t align2, size_t len1, size_t len2, + int fail) +{ + char *s1 = (char *) (buf1 + align1); + char *s2 = (char *) (buf2 + align2); + + static const char d[] = "1234567890abcxyz"; +#define dl (sizeof (d) - 1) + char *ss2 = s2; + for (size_t l = len2; l > 0; l = l > dl ? l - dl : 0) + { + size_t t = l > dl ? dl : l; + ss2 = mempcpy (ss2, d, t); + } + s2[len2] = '\0'; + + if (fail) + { + char *ss1 = s1; + for (size_t l = len1; l > 0; l = l > dl ? l - dl : 0) + { + size_t t = l > dl ? dl : l; + memcpy (ss1, d, t); + ++ss1[len2 > 7 ? 7 : len2 - 1]; + ss1 += t; + } + } + else + { + memset (s1, '0', len1); + for (size_t i = 0; i < len2; ++i) + s1[len1 - len2 + i] = toupper (s2[i]); + } + s1[len1] = '\0'; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%zd, alignment %2zd/%2zd, %s:", + len1, len2, align1, align2, fail ? "fail" : "found"); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, fail ? NULL : s1 + len1 - len2); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static int +test_main (void) +{ + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (size_t klen = 2; klen < 32; ++klen) + for (size_t hlen = 2 * klen; hlen < 16 * klen; hlen += klen) + { + do_test (0, 0, hlen, klen, 0); + do_test (0, 0, hlen, klen, 1); + do_test (0, 3, hlen, klen, 0); + do_test (0, 3, hlen, klen, 1); + do_test (0, 9, hlen, klen, 0); + do_test (0, 9, hlen, klen, 1); + do_test (0, 15, hlen, klen, 0); + do_test (0, 15, hlen, klen, 1); + + do_test (3, 0, hlen, klen, 0); + do_test (3, 0, hlen, klen, 1); + do_test (3, 3, hlen, klen, 0); + do_test (3, 3, hlen, klen, 1); + do_test (3, 9, hlen, klen, 0); + do_test (3, 9, hlen, klen, 1); + do_test (3, 15, hlen, klen, 0); + do_test (3, 15, hlen, klen, 1); + + do_test (9, 0, hlen, klen, 0); + do_test (9, 0, hlen, klen, 1); + do_test (9, 3, hlen, klen, 0); + do_test (9, 3, hlen, klen, 1); + do_test (9, 9, hlen, klen, 0); + do_test (9, 9, hlen, klen, 1); + do_test (9, 15, hlen, klen, 0); + do_test (9, 15, hlen, klen, 1); + + do_test (15, 0, hlen, klen, 0); + do_test (15, 0, hlen, klen, 1); + do_test (15, 3, hlen, klen, 0); + do_test (15, 3, hlen, klen, 1); + do_test (15, 9, hlen, klen, 0); + do_test (15, 9, hlen, klen, 1); + do_test (15, 15, hlen, klen, 0); + do_test (15, 15, hlen, klen, 1); + } + + do_test (0, 0, page_size - 1, 16, 0); + do_test (0, 0, page_size - 1, 16, 1); + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strcat-ifunc.c b/benchtests/bench-strcat-ifunc.c new file mode 100644 index 0000000000..003dc38568 --- /dev/null +++ b/benchtests/bench-strcat-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strcat function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strcat.c" diff --git a/benchtests/bench-strcat.c b/benchtests/bench-strcat.c new file mode 100644 index 0000000000..b70a272109 --- /dev/null +++ b/benchtests/bench-strcat.c @@ -0,0 +1,155 @@ +/* Measure strcat functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "strcat" +#include "bench-string.h" + +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) +{ + char *ret = dst; + while (*dst++ != '\0'); + --dst; + while ((*dst++ = *src++) != '\0'); + return ret; +} + +static void +do_one_test (impl_t *impl, char *dst, const char *src) +{ + size_t k = strlen (dst); + if (CALL (impl, dst, src) != dst) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + CALL (impl, dst, src), dst); + ret = 1; + return; + } + + if (strcmp (dst + k, src) != 0) + { + error (0, 0, "Wrong result in function %s dst \"%s\" src \"%s\"", + impl->name, dst, src); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + dst[k] = '\0'; + HP_TIMING_NOW (start); + CALL (impl, dst, src); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len1, size_t len2, int max_char) +{ + size_t i; + char *s1, *s2; + + align1 &= 7; + if (align1 + len1 >= page_size) + return; + + align2 &= 7; + if (align2 + len1 + len2 >= page_size) + return; + + s1 = (char *) (buf1 + align1); + s2 = (char *) (buf2 + align2); + + for (i = 0; i < len1; ++i) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len1] = '\0'; + + for (i = 0; i < len2; i++) + s2[i] = 32 + 23 * i % (max_char - 32); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len1, len2, align1, align2); + + FOR_EACH_IMPL (impl, 0) + { + s2[len2] = '\0'; + do_one_test (impl, s2, s1); + } + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%28s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, i, 127); + do_test (0, 0, i, i, 255); + do_test (0, i, i, i, 127); + do_test (i, 0, i, i, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, 8 << i, 127); + do_test (8 - i, 2 * i, 8 << i, 8 << i, 127); + do_test (0, 0, 8 << i, 2 << i, 127); + do_test (8 - i, 2 * i, 8 << i, 2 << i, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, 8 << i, 1, 127); + do_test (2 * i, i, 8 << i, 1, 255); + do_test (i, i, 8 << i, 10, 127); + do_test (i, i, 8 << i, 10, 255); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strchr-ifunc.c b/benchtests/bench-strchr-ifunc.c new file mode 100644 index 0000000000..0ef13987d6 --- /dev/null +++ b/benchtests/bench-strchr-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strchr function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strchr.c" diff --git a/benchtests/bench-strchr.c b/benchtests/bench-strchr.c new file mode 100644 index 0000000000..710b59203d --- /dev/null +++ b/benchtests/bench-strchr.c @@ -0,0 +1,206 @@ +/* Measure STRCHR functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#ifndef WIDE +# ifdef USE_FOR_STRCHRNUL +# define TEST_NAME "strchrnul" +# else +# define TEST_NAME "strchr" +# endif +#else +# define TEST_NAME "wcschr" +#endif +#include "bench-string.h" + +#ifndef WIDE +# ifdef USE_FOR_STRCHRNUL +# define STRCHR strchrnul +# define stupid_STRCHR stupid_STRCHRNUL +# define simple_STRCHR simple_STRCHRNUL +# else +# define STRCHR strchr +# endif +# define STRLEN strlen +# define CHAR char +# define BIG_CHAR CHAR_MAX +# define MIDDLE_CHAR 127 +# define SMALL_CHAR 23 +# define UCHAR unsigned char +#else +# include <wchar.h> +# define STRCHR wcschr +# define STRLEN wcslen +# define CHAR wchar_t +# define BIG_CHAR WCHAR_MAX +# define MIDDLE_CHAR 1121 +# define SMALL_CHAR 851 +# define UCHAR wchar_t +#endif + +#ifdef USE_FOR_STRCHRNUL +# define NULLRET(endptr) endptr +#else +# define NULLRET(endptr) NULL +#endif + + +typedef CHAR *(*proto_t) (const CHAR *, int); + +CHAR * +simple_STRCHR (const CHAR *s, int c) +{ + for (; *s != (CHAR) c; ++s) + if (*s == '\0') + return NULLRET ((CHAR *) s); + return (CHAR *) s; +} + +CHAR * +stupid_STRCHR (const CHAR *s, int c) +{ + size_t n = STRLEN (s) + 1; + + while (n--) + if (*s++ == (CHAR) c) + return (CHAR *) s - 1; + return NULLRET ((CHAR *) s - 1); +} + +IMPL (stupid_STRCHR, 0) +IMPL (simple_STRCHR, 0) +IMPL (STRCHR, 1) + +static void +do_one_test (impl_t *impl, const CHAR *s, int c, const CHAR *exp_res) +{ + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) +/* For wcschr: align here means align not in bytes, + but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) + len for wcschr here isn't in bytes but it's number of wchar_t symbols. */ +{ + size_t i; + CHAR *result; + CHAR *buf = (CHAR *) buf1; + align &= 15; + if ((align + len) * sizeof (CHAR) >= page_size) + return; + + for (i = 0; i < len; ++i) + { + buf[align + i] = 32 + 23 * i % max_char; + if (buf[align + i] == seek_char) + buf[align + i] = seek_char + 1; + else if (buf[align + i] == 0) + buf[align + i] = 1; + } + buf[align + len] = 0; + + if (pos < len) + { + buf[align + pos] = seek_char; + result = buf + align + pos; + } + else if (seek_char == 0) + result = buf + align + len; + else + result = NULLRET (buf + align + len); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment in bytes %2zd:", + pos, align * sizeof (CHAR)); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, buf + align, seek_char, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, SMALL_CHAR, MIDDLE_CHAR); + do_test (i, 16 << i, 2048, SMALL_CHAR, MIDDLE_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 64, 256, SMALL_CHAR, MIDDLE_CHAR); + do_test (i, 64, 256, SMALL_CHAR, BIG_CHAR); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, i, i + 1, SMALL_CHAR, MIDDLE_CHAR); + do_test (0, i, i + 1, SMALL_CHAR, BIG_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 0, MIDDLE_CHAR); + do_test (i, 16 << i, 2048, 0, MIDDLE_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 64, 256, 0, MIDDLE_CHAR); + do_test (i, 64, 256, 0, BIG_CHAR); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, i, i + 1, 0, MIDDLE_CHAR); + do_test (0, i, i + 1, 0, BIG_CHAR); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strchrnul-ifunc.c b/benchtests/bench-strchrnul-ifunc.c new file mode 100644 index 0000000000..35c7cb1531 --- /dev/null +++ b/benchtests/bench-strchrnul-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strchrnul function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strchrnul.c" diff --git a/benchtests/bench-strchrnul.c b/benchtests/bench-strchrnul.c new file mode 100644 index 0000000000..db5680c2f3 --- /dev/null +++ b/benchtests/bench-strchrnul.c @@ -0,0 +1,20 @@ +/* Measure strchrnul function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define USE_FOR_STRCHRNUL 1 +#include "bench-strchr.c" diff --git a/benchtests/bench-strcmp-ifunc.c b/benchtests/bench-strcmp-ifunc.c new file mode 100644 index 0000000000..01a80958d3 --- /dev/null +++ b/benchtests/bench-strcmp-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strcmp function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strcmp.c" diff --git a/benchtests/bench-strcmp.c b/benchtests/bench-strcmp.c new file mode 100644 index 0000000000..63a3cd4999 --- /dev/null +++ b/benchtests/bench-strcmp.c @@ -0,0 +1,247 @@ +/* Measure strcmp and wcscmp functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#ifdef WIDE +# define TEST_NAME "wcscmp" +#else +# define TEST_NAME "strcmp" +#endif +#include "bench-string.h" + +#ifdef WIDE +# include <wchar.h> + +# define L(str) L##str +# define STRCMP wcscmp +# define STRCPY wcscpy +# define STRLEN wcslen +# define MEMCPY wmemcpy +# define SIMPLE_STRCMP simple_wcscmp +# define STUPID_STRCMP stupid_wcscmp +# define CHAR wchar_t +# define UCHAR wchar_t +# define CHARBYTES 4 +# define CHARBYTESLOG 2 +# define CHARALIGN __alignof__ (CHAR) +# define MIDCHAR 0x7fffffff +# define LARGECHAR 0xfffffffe +# define CHAR__MAX WCHAR_MAX +# define CHAR__MIN WCHAR_MIN + +/* Wcscmp uses signed semantics for comparison, not unsigned */ +/* Avoid using substraction since possible overflow */ + +int +simple_wcscmp (const wchar_t *s1, const wchar_t *s2) +{ + wchar_t c1, c2; + do + { + c1 = *s1++; + c2 = *s2++; + if (c2 == L'\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 < c2 ? -1 : 1; +} + +int +stupid_wcscmp (const wchar_t *s1, const wchar_t *s2) +{ + size_t ns1 = wcslen (s1) + 1; + size_t ns2 = wcslen (s2) + 1; + size_t n = ns1 < ns2 ? ns1 : ns2; + int ret = 0; + + wchar_t c1, c2; + + while (n--) { + c1 = *s1++; + c2 = *s2++; + if ((ret = c1 < c2 ? -1 : c1 == c2 ? 0 : 1) != 0) + break; + } + return ret; +} + +#else +# include <limits.h> + +# define L(str) str +# define STRCMP strcmp +# define STRCPY strcpy +# define STRLEN strlen +# define MEMCPY memcpy +# define SIMPLE_STRCMP simple_strcmp +# define STUPID_STRCMP stupid_strcmp +# define CHAR char +# define UCHAR unsigned char +# define CHARBYTES 1 +# define CHARBYTESLOG 0 +# define CHARALIGN 1 +# define MIDCHAR 0x7f +# define LARGECHAR 0xfe +# define CHAR__MAX CHAR_MAX +# define CHAR__MIN CHAR_MIN + +/* Strcmp uses unsigned semantics for comparison. */ +int +simple_strcmp (const char *s1, const char *s2) +{ + int ret; + + while ((ret = *(unsigned char *) s1 - *(unsigned char*) s2++) == 0 && *s1++); + return ret; +} + +int +stupid_strcmp (const char *s1, const char *s2) +{ + size_t ns1 = strlen (s1) + 1; + size_t ns2 = strlen (s2) + 1; + size_t n = ns1 < ns2 ? ns1 : ns2; + int ret = 0; + + while (n--) + if ((ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) != 0) + break; + return ret; +} +#endif + +typedef int (*proto_t) (const CHAR *, const CHAR *); + +IMPL (STUPID_STRCMP, 1) +IMPL (SIMPLE_STRCMP, 1) +IMPL (STRCMP, 1) + +static void +do_one_test (impl_t *impl, + const CHAR *s1, const CHAR *s2, + int exp_result) +{ + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, int max_char, + int exp_result) +{ + size_t i; + + CHAR *s1, *s2; + + if (len == 0) + return; + + align1 &= 63; + if (align1 + (len + 1) * CHARBYTES >= page_size) + return; + + align2 &= 63; + if (align2 + (len + 1) * CHARBYTES >= page_size) + return; + + /* Put them close to the end of page. */ + i = align1 + CHARBYTES * (len + 2); + s1 = (CHAR *) (buf1 + ((page_size - i) / 16 * 16) + align1); + i = align2 + CHARBYTES * (len + 2); + s2 = (CHAR *) (buf2 + ((page_size - i) / 16 * 16) + align2); + + for (i = 0; i < len; i++) + s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char; + + s1[len] = s2[len] = 0; + s1[len + 1] = 23; + s2[len + 1] = 24 + exp_result; + s2[len - 1] -= exp_result; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 32; ++i) + { + do_test (CHARBYTES * i, CHARBYTES * i, i, MIDCHAR, 0); + do_test (CHARBYTES * i, CHARBYTES * i, i, MIDCHAR, 1); + do_test (CHARBYTES * i, CHARBYTES * i, i, MIDCHAR, -1); + } + + for (i = 1; i < 10 + CHARBYTESLOG; ++i) + { + do_test (0, 0, 2 << i, MIDCHAR, 0); + do_test (0, 0, 2 << i, LARGECHAR, 0); + do_test (0, 0, 2 << i, MIDCHAR, 1); + do_test (0, 0, 2 << i, LARGECHAR, 1); + do_test (0, 0, 2 << i, MIDCHAR, -1); + do_test (0, 0, 2 << i, LARGECHAR, -1); + do_test (0, CHARBYTES * i, 2 << i, MIDCHAR, 1); + do_test (CHARBYTES * i, CHARBYTES * (i + 1), 2 << i, LARGECHAR, 1); + } + + for (i = 1; i < 8; ++i) + { + do_test (CHARBYTES * i, 2 * CHARBYTES * i, 8 << i, MIDCHAR, 0); + do_test (2 * CHARBYTES * i, CHARBYTES * i, 8 << i, LARGECHAR, 0); + do_test (CHARBYTES * i, 2 * CHARBYTES * i, 8 << i, MIDCHAR, 1); + do_test (2 * CHARBYTES * i, CHARBYTES * i, 8 << i, LARGECHAR, 1); + do_test (CHARBYTES * i, 2 * CHARBYTES * i, 8 << i, MIDCHAR, -1); + do_test (2 * CHARBYTES * i, CHARBYTES * i, 8 << i, LARGECHAR, -1); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strcpy-ifunc.c b/benchtests/bench-strcpy-ifunc.c new file mode 100644 index 0000000000..d27a4f92db --- /dev/null +++ b/benchtests/bench-strcpy-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strcpy function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strcpy.c" diff --git a/benchtests/bench-strcpy.c b/benchtests/bench-strcpy.c new file mode 100644 index 0000000000..4e024d406f --- /dev/null +++ b/benchtests/bench-strcpy.c @@ -0,0 +1,183 @@ +/* Measure strcpy functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifdef WIDE +# include <wchar.h> +# define CHAR wchar_t +# define UCHAR wchar_t +# define sfmt "ls" +# define BIG_CHAR WCHAR_MAX +# define SMALL_CHAR 1273 +# define STRCMP wcscmp +# define MEMCMP wmemcmp +# define MEMSET wmemset +#else +# define CHAR char +# define UCHAR unsigned char +# define sfmt "s" +# define BIG_CHAR CHAR_MAX +# define SMALL_CHAR 127 +# define STRCMP strcmp +# define MEMCMP memcmp +# define MEMSET memset +#endif + +#ifndef STRCPY_RESULT +# define STRCPY_RESULT(dst, len) dst +# define TEST_MAIN +# ifndef WIDE +# define TEST_NAME "strcpy" +# else +# define TEST_NAME "wcscpy" +# endif +# include "bench-string.h" +# ifndef WIDE +# define SIMPLE_STRCPY simple_strcpy +# define STRCPY strcpy +# else +# define SIMPLE_STRCPY simple_wcscpy +# define STRCPY wcscpy +# endif + +CHAR *SIMPLE_STRCPY (CHAR *, const CHAR *); + +IMPL (SIMPLE_STRCPY, 0) +IMPL (STRCPY, 1) + +CHAR * +SIMPLE_STRCPY (CHAR *dst, const CHAR *src) +{ + CHAR *ret = dst; + while ((*dst++ = *src++) != '\0'); + return ret; +} +#endif + +typedef CHAR *(*proto_t) (CHAR *, const CHAR *); + +static void +do_one_test (impl_t *impl, CHAR *dst, const CHAR *src, + size_t len __attribute__((unused))) +{ + if (CALL (impl, dst, src) != STRCPY_RESULT (dst, len)) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + CALL (impl, dst, src), STRCPY_RESULT (dst, len)); + ret = 1; + return; + } + + if (STRCMP (dst, src) != 0) + { + error (0, 0, + "Wrong result in function %s dst \"%" sfmt "\" src \"%" sfmt "\"", + impl->name, dst, src); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused));; + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, dst, src); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, int max_char) +{ + size_t i; + CHAR *s1, *s2; +/* For wcscpy: align1 and align2 here mean alignment not in bytes, + but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) + len for wcschr here isn't in bytes but it's number of wchar_t symbols. */ + align1 &= 7; + if ((align1 + len) * sizeof(CHAR) >= page_size) + return; + + align2 &= 7; + if ((align2 + len) * sizeof(CHAR) >= page_size) + return; + + s1 = (CHAR *) (buf1) + align1; + s2 = (CHAR *) (buf2) + align2; + + for (i = 0; i < len; i++) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len] = 0; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignments in bytes %2zd/%2zd:", len, align1 * sizeof(CHAR), align2 * sizeof(CHAR)); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, s1, len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 16; ++i) + { + do_test (0, 0, i, SMALL_CHAR); + do_test (0, 0, i, BIG_CHAR); + do_test (0, i, i, SMALL_CHAR); + do_test (i, 0, i, BIG_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, SMALL_CHAR); + do_test (8 - i, 2 * i, 8 << i, SMALL_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, 8 << i, SMALL_CHAR); + do_test (2 * i, i, 8 << i, BIG_CHAR); + do_test (i, i, 8 << i, SMALL_CHAR); + do_test (i, i, 8 << i, BIG_CHAR); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strcspn-ifunc.c b/benchtests/bench-strcspn-ifunc.c new file mode 100644 index 0000000000..e257c9b4e3 --- /dev/null +++ b/benchtests/bench-strcspn-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strcspn function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strcspn.c" diff --git a/benchtests/bench-strcspn.c b/benchtests/bench-strcspn.c new file mode 100644 index 0000000000..22b3b84957 --- /dev/null +++ b/benchtests/bench-strcspn.c @@ -0,0 +1,59 @@ +/* Measure strcspn functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define STRPBRK_RESULT(s, pos) (pos) +#define RES_TYPE size_t +#define TEST_MAIN +#define TEST_NAME "strcspn" +#include "bench-string.h" + +typedef size_t (*proto_t) (const char *, const char *); +size_t simple_strcspn (const char *, const char *); +size_t stupid_strcspn (const char *, const char *); + +IMPL (stupid_strcspn, 0) +IMPL (simple_strcspn, 0) +IMPL (strcspn, 1) + +size_t +simple_strcspn (const char *s, const char *rej) +{ + const char *r, *str = s; + char c; + + while ((c = *s++) != '\0') + for (r = rej; *r != '\0'; ++r) + if (*r == c) + return s - str - 1; + return s - str - 1; +} + +size_t +stupid_strcspn (const char *s, const char *rej) +{ + size_t ns = strlen (s), nrej = strlen (rej); + size_t i, j; + + for (i = 0; i < ns; ++i) + for (j = 0; j < nrej; ++j) + if (s[i] == rej[j]) + return i; + return i; +} + +#include "bench-strpbrk.c" diff --git a/benchtests/bench-strlen-ifunc.c b/benchtests/bench-strlen-ifunc.c new file mode 100644 index 0000000000..fcd45929f6 --- /dev/null +++ b/benchtests/bench-strlen-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strlen function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strlen.c" diff --git a/benchtests/bench-strlen.c b/benchtests/bench-strlen.c new file mode 100644 index 0000000000..63b1e9368b --- /dev/null +++ b/benchtests/bench-strlen.c @@ -0,0 +1,149 @@ +/* Measure STRLEN functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#ifndef WIDE +# define TEST_NAME "strlen" +#else +# define TEST_NAME "wcslen" +#endif +#include "bench-string.h" + +#ifndef WIDE +# define STRLEN strlen +# define CHAR char +# define MAX_CHAR CHAR_MAX +#else +# include <wchar.h> +# define STRLEN wcslen +# define CHAR wchar_t +# define MAX_CHAR WCHAR_MAX +#endif + +typedef size_t (*proto_t) (const CHAR *); + +size_t +simple_STRLEN (const CHAR *s) +{ + const CHAR *p; + + for (p = s; *p; ++p); + return p - s; +} + +#ifndef WIDE +size_t +builtin_strlen (const CHAR *p) +{ + return __builtin_strlen (p); +} +IMPL (builtin_strlen, 0) +#endif + +IMPL (simple_STRLEN, 0) +IMPL (STRLEN, 1) + + +static void +do_one_test (impl_t *impl, const CHAR *s, size_t exp_len) +{ + size_t len = CALL (impl, s); + if (len != exp_len) + { + error (0, 0, "Wrong result in function %s %zd %zd", impl->name, + len, exp_len); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t len) +{ + size_t i; + + align &= 63; + if (align + sizeof(CHAR) * len >= page_size) + return; + + CHAR *buf = (CHAR *) (buf1); + + for (i = 0; i < len; ++i) + buf[align + i] = 1 + 11111 * i % MAX_CHAR; + buf[align + len] = 0; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", len, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, (CHAR *) (buf + align), len); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + /* Checking with only 4 * N alignments for wcslen, other alignments are wrong for wchar_t type arrays*/ + + for (i = 1; i < 8; ++i) + { + do_test (sizeof(CHAR) * i, i); + do_test (0, i); + } + + for (i = 2; i <= 12; ++i) + { + do_test (0, 1 << i); + do_test (sizeof(CHAR) * 7, 1 << i); + do_test (sizeof(CHAR) * i, 1 << i); + do_test (sizeof(CHAR) * i, (size_t)((1 << i) / 1.5)); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strncasecmp-ifunc.c b/benchtests/bench-strncasecmp-ifunc.c new file mode 100644 index 0000000000..df796e265e --- /dev/null +++ b/benchtests/bench-strncasecmp-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strncasecmp function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strncasecmp.c" diff --git a/benchtests/bench-strncasecmp.c b/benchtests/bench-strncasecmp.c new file mode 100644 index 0000000000..5fa9220cb0 --- /dev/null +++ b/benchtests/bench-strncasecmp.c @@ -0,0 +1,213 @@ +/* Measure strncasecmp functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ctype.h> +#define TEST_MAIN +#define TEST_NAME "strncasecmp" +#include "bench-string.h" + +typedef int (*proto_t) (const char *, const char *, size_t); +static int simple_strncasecmp (const char *, const char *, size_t); +static int stupid_strncasecmp (const char *, const char *, size_t); + +IMPL (stupid_strncasecmp, 0) +IMPL (simple_strncasecmp, 0) +IMPL (strncasecmp, 1) + +static int +simple_strncasecmp (const char *s1, const char *s2, size_t n) +{ + int ret; + + if (n == 0) + return 0; + + while ((ret = ((unsigned char) tolower (*s1) + - (unsigned char) tolower (*s2))) == 0 + && *s1++) + { + if (--n == 0) + return 0; + ++s2; + } + return ret; +} + +static int +stupid_strncasecmp (const char *s1, const char *s2, size_t max) +{ + size_t ns1 = strlen (s1) + 1; + size_t ns2 = strlen (s2) + 1; + size_t n = ns1 < ns2 ? ns1 : ns2; + if (n > max) + n = max; + int ret = 0; + + while (n--) + { + if ((ret = ((unsigned char) tolower (*s1) + - (unsigned char) tolower (*s2))) != 0) + break; + ++s1; + ++s2; + } + return ret; +} + +static void +do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n, + int exp_result) +{ + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t n, size_t len, int max_char, + int exp_result) +{ + size_t i; + char *s1, *s2; + + if (len == 0) + return; + + align1 &= 7; + if (align1 + len + 1 >= page_size) + return; + + align2 &= 7; + if (align2 + len + 1 >= page_size) + return; + + s1 = (char *) (buf1 + align1); + s2 = (char *) (buf2 + align2); + + for (i = 0; i < len; i++) + { + s1[i] = toupper (1 + 23 * i % max_char); + s2[i] = tolower (s1[i]); + } + + s1[len] = s2[len] = 0; + s1[len + 1] = 23; + s2[len + 1] = 24 + exp_result; + if ((s2[len - 1] == 'z' && exp_result == -1) + || (s2[len - 1] == 'a' && exp_result == 1)) + s1[len - 1] += exp_result; + else + s2[len - 1] -= exp_result; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, n, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 16; ++i) + { + do_test (i, i, i - 1, i, 127, 0); + + do_test (i, i, i, i, 127, 0); + do_test (i, i, i, i, 127, 1); + do_test (i, i, i, i, 127, -1); + + do_test (i, i, i + 1, i, 127, 0); + do_test (i, i, i + 1, i, 127, 1); + do_test (i, i, i + 1, i, 127, -1); + } + + for (i = 1; i < 10; ++i) + { + do_test (0, 0, (2 << i) - 1, 2 << i, 127, 0); + do_test (0, 0, 2 << i, 2 << i, 254, 0); + do_test (0, 0, (2 << i) + 1, 2 << i, 127, 0); + + do_test (0, 0, (2 << i) + 1, 2 << i, 254, 0); + + do_test (0, 0, 2 << i, 2 << i, 127, 1); + do_test (0, 0, (2 << i) + 10, 2 << i, 127, 1); + + do_test (0, 0, 2 << i, 2 << i, 254, 1); + do_test (0, 0, (2 << i) + 10, 2 << i, 254, 1); + + do_test (0, 0, 2 << i, 2 << i, 127, -1); + do_test (0, 0, (2 << i) + 10, 2 << i, 127, -1); + + do_test (0, 0, 2 << i, 2 << i, 254, -1); + do_test (0, 0, (2 << i) + 10, 2 << i, 254, -1); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, (8 << i) - 1, 8 << i, 127, 0); + do_test (i, 2 * i, 8 << i, 8 << i, 127, 0); + do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 0); + + do_test (2 * i, i, (8 << i) - 1, 8 << i, 254, 0); + do_test (2 * i, i, 8 << i, 8 << i, 254, 0); + do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 0); + + do_test (i, 2 * i, 8 << i, 8 << i, 127, 1); + do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, 1); + + do_test (2 * i, i, 8 << i, 8 << i, 254, 1); + do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, 1); + + do_test (i, 2 * i, 8 << i, 8 << i, 127, -1); + do_test (i, 2 * i, (8 << i) + 100, 8 << i, 127, -1); + + do_test (2 * i, i, 8 << i, 8 << i, 254, -1); + do_test (2 * i, i, (8 << i) + 100, 8 << i, 254, -1); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strncat-ifunc.c b/benchtests/bench-strncat-ifunc.c new file mode 100644 index 0000000000..adcfd22fb7 --- /dev/null +++ b/benchtests/bench-strncat-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strncat function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strncat.c" diff --git a/benchtests/bench-strncat.c b/benchtests/bench-strncat.c new file mode 100644 index 0000000000..904daa7b7e --- /dev/null +++ b/benchtests/bench-strncat.c @@ -0,0 +1,168 @@ +/* Measure strncat functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "strncat" +#include "bench-string.h" + +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) +{ + char *ret = dst; + while (*dst++ != '\0'); + --dst; + while (n--) + if ( (*dst++ = *src++) == '\0') + return ret; + *dst = '\0'; + return ret; +} + +static void +do_one_test (impl_t *impl, char *dst, const char *src, size_t n) +{ + size_t k = strlen (dst); + if (CALL (impl, dst, src, n) != dst) + { + error (0, 0, "Wrong result in function %s %p != %p", impl->name, + CALL (impl, dst, src, n), dst); + ret = 1; + return; + } + + size_t len = strlen (src); + if (memcmp (dst + k, src, len + 1 > n ? n : len + 1) != 0) + { + error (0, 0, "Incorrect cancatination in function %s", + impl->name); + ret = 1; + return; + } + if (n < len && dst[k + n] != '\0') + { + error (0, 0, "There is no zero in the end of output string in %s", + impl->name); + ret = 1; + return; + } + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + dst[k] = '\0'; + HP_TIMING_NOW (start); + CALL (impl, dst, src, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len1, size_t len2, + size_t n, int max_char) +{ + size_t i; + char *s1, *s2; + + align1 &= 7; + if (align1 + len1 >= page_size) + return; + if (align1 + n > page_size) + return; + align2 &= 7; + if (align2 + len1 + len2 >= page_size) + return; + if (align2 + len1 + n > page_size) + return; + s1 = (char *) (buf1 + align1); + s2 = (char *) (buf2 + align2); + + for (i = 0; i < len1; ++i) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len1] = '\0'; + + for (i = 0; i < len2; i++) + s2[i] = 32 + 23 * i % (max_char - 32); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%4zd, alignment %2zd/%2zd, N %4zd:", + len1, len2, align1, align2, n); + + FOR_EACH_IMPL (impl, 0) + { + s2[len2] = '\0'; + do_one_test (impl, s2, s1, n); + } + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +main (void) +{ + size_t i, n; + + test_init (); + + printf ("%28s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (n = 2; n <= 2048; n*=4) + { + do_test (0, 2, 2, 2, n, 127); + do_test (0, 0, 4, 4, n, 127); + do_test (4, 0, 4, 4, n, 255); + do_test (0, 0, 8, 8, n, 127); + do_test (0, 8, 8, 8, n, 127); + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, 8 << i, n, 127); + do_test (8 - i, 2 * i, 8 << i, 8 << i, n, 127); + do_test (0, 0, 8 << i, 2 << i, n, 127); + do_test (8 - i, 2 * i, 8 << i, 2 << i, n, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 2 * i, 8 << i, 1, n, 127); + do_test (2 * i, i, 8 << i, 1, n, 255); + do_test (i, i, 8 << i, 10, n, 127); + } + } + + return ret; +} diff --git a/benchtests/bench-strncmp-ifunc.c b/benchtests/bench-strncmp-ifunc.c new file mode 100644 index 0000000000..1cae32b528 --- /dev/null +++ b/benchtests/bench-strncmp-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strncmp function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strncmp.c" diff --git a/benchtests/bench-strncmp.c b/benchtests/bench-strncmp.c new file mode 100644 index 0000000000..b3af0f98e3 --- /dev/null +++ b/benchtests/bench-strncmp.c @@ -0,0 +1,249 @@ +/* Measure strncmp functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "strncmp" +#include "bench-string.h" + +typedef int (*proto_t) (const char *, const char *, size_t); +int simple_strncmp (const char *, const char *, size_t); +int stupid_strncmp (const char *, const char *, size_t); + +IMPL (stupid_strncmp, 0) +IMPL (simple_strncmp, 0) +IMPL (strncmp, 1) + +int +simple_strncmp (const char *s1, const char *s2, size_t n) +{ + int ret = 0; + + while (n-- && (ret = *(unsigned char *) s1 - * (unsigned char *) s2++) == 0 + && *s1++); + return ret; +} + +int +stupid_strncmp (const char *s1, const char *s2, size_t n) +{ + size_t ns1 = strnlen (s1, n) + 1, ns2 = strnlen (s2, n) + 1; + int ret = 0; + + n = ns1 < n ? ns1 : n; + n = ns2 < n ? ns2 : n; + while (n-- && (ret = *(unsigned char *) s1++ - * (unsigned char *) s2++) == 0); + return ret; +} + +static void +do_one_test (impl_t *impl, const char *s1, const char *s2, size_t n, + int exp_result) +{ + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test_limit (size_t align1, size_t align2, size_t len, size_t n, int max_char, + int exp_result) +{ + size_t i, align_n; + char *s1, *s2; + + if (n == 0) + { + s1 = (char*)(buf1 + page_size); + s2 = (char*)(buf2 + page_size); + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%4zd:", len, n); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, n, 0); + + if (HP_TIMING_AVAIL) + putchar ('\n'); + + return; + } + + align1 &= 15; + align2 &= 15; + align_n = (page_size - n) & 15; + + s1 = (char*)(buf1 + page_size - n); + s2 = (char*)(buf2 + page_size - n); + + if (align1 < align_n) + s1 -= (align_n - align1); + + if (align2 < align_n) + s2 -= (align_n - align2); + + for (i = 0; i < n; i++) + s1[i] = s2[i] = 1 + 23 * i % max_char; + + if (len < n) + { + s1[len] = 0; + s2[len] = 0; + if (exp_result < 0) + s2[len] = 32; + else if (exp_result > 0) + s1[len] = 64; + } + + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, n, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static void +do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char, + int exp_result) +{ + size_t i; + char *s1, *s2; + + if (n == 0) + return; + + align1 &= 7; + if (align1 + n + 1 >= page_size) + return; + + align2 &= 7; + if (align2 + n + 1 >= page_size) + return; + + s1 = (char*)(buf1 + align1); + s2 = (char*)(buf2 + align2); + + for (i = 0; i < n; i++) + s1[i] = s2[i] = 1 + 23 * i % max_char; + + s1[n] = 24 + exp_result; + s2[n] = 23; + s1[len] = 0; + s2[len] = 0; + if (exp_result < 0) + s2[len] = 32; + else if (exp_result > 0) + s1[len] = 64; + if (len >= n) + s2[n - 1] -= exp_result; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%4zd, alignment %2zd/%2zd:", len, n, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, (char*)s1, (char*)s2, n, exp_result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i =0; i < 16; ++i) + { + do_test (0, 0, 8, i, 127, 0); + do_test (0, 0, 8, i, 127, -1); + do_test (0, 0, 8, i, 127, 1); + do_test (i, i, 8, i, 127, 0); + do_test (i, i, 8, i, 127, 1); + do_test (i, i, 8, i, 127, -1); + do_test (i, 2 * i, 8, i, 127, 0); + do_test (2 * i, i, 8, i, 127, 1); + do_test (i, 3 * i, 8, i, 127, -1); + do_test (0, 0, 8, i, 255, 0); + do_test (0, 0, 8, i, 255, -1); + do_test (0, 0, 8, i, 255, 1); + do_test (i, i, 8, i, 255, 0); + do_test (i, i, 8, i, 255, 1); + do_test (i, i, 8, i, 255, -1); + do_test (i, 2 * i, 8, i, 255, 0); + do_test (2 * i, i, 8, i, 255, 1); + do_test (i, 3 * i, 8, i, 255, -1); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 8 << i, 16 << i, 127, 0); + do_test (0, 0, 8 << i, 16 << i, 127, 1); + do_test (0, 0, 8 << i, 16 << i, 127, -1); + do_test (0, 0, 8 << i, 16 << i, 255, 0); + do_test (0, 0, 8 << i, 16 << i, 255, 1); + do_test (0, 0, 8 << i, 16 << i, 255, -1); + do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 0); + do_test (8 - i, 2 * i, 8 << i, 16 << i, 127, 1); + do_test (2 * i, i, 8 << i, 16 << i, 255, 0); + do_test (2 * i, i, 8 << i, 16 << i, 255, 1); + } + + do_test_limit (0, 0, 0, 0, 127, 0); + do_test_limit (4, 0, 21, 20, 127, 0); + do_test_limit (0, 4, 21, 20, 127, 0); + do_test_limit (8, 0, 25, 24, 127, 0); + do_test_limit (0, 8, 25, 24, 127, 0); + + for (i = 0; i < 8; ++i) + { + do_test_limit (0, 0, 17 - i, 16 - i, 127, 0); + do_test_limit (0, 0, 17 - i, 16 - i, 255, 0); + do_test_limit (0, 0, 15 - i, 16 - i, 127, 0); + do_test_limit (0, 0, 15 - i, 16 - i, 127, 1); + do_test_limit (0, 0, 15 - i, 16 - i, 127, -1); + do_test_limit (0, 0, 15 - i, 16 - i, 255, 0); + do_test_limit (0, 0, 15 - i, 16 - i, 255, 1); + do_test_limit (0, 0, 15 - i, 16 - i, 255, -1); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strncpy-ifunc.c b/benchtests/bench-strncpy-ifunc.c new file mode 100644 index 0000000000..d4eebe6234 --- /dev/null +++ b/benchtests/bench-strncpy-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strncpy function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strncpy.c" diff --git a/benchtests/bench-strncpy.c b/benchtests/bench-strncpy.c new file mode 100644 index 0000000000..4065c0aae4 --- /dev/null +++ b/benchtests/bench-strncpy.c @@ -0,0 +1,180 @@ +/* Measure strncpy functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef STRNCPY_RESULT +# define STRNCPY_RESULT(dst, len, n) dst +# define TEST_MAIN +# define TEST_NAME "strncpy" +# include "bench-string.h" + +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) +{ + char *ret = dst; + while (n--) + if ((*dst++ = *src++) == '\0') + { + while (n--) + *dst++ = '\0'; + return ret; + } + return ret; +} + +char * +stupid_strncpy (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; +} +#endif + +typedef char *(*proto_t) (char *, const char *, size_t); + +static void +do_one_test (impl_t *impl, char *dst, const char *src, size_t len, size_t n) +{ + if (CALL (impl, dst, src, n) != STRNCPY_RESULT (dst, len, n)) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + CALL (impl, dst, src, n), dst); + ret = 1; + return; + } + + if (memcmp (dst, src, len > n ? n : len) != 0) + { + error (0, 0, "Wrong result in function %s", impl->name); + ret = 1; + return; + } + + if (n > len) + { + size_t i; + + for (i = len; i < n; ++i) + if (dst [i] != '\0') + { + error (0, 0, "Wrong result in function %s", impl->name); + ret = 1; + return; + } + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute__ ((unused)); + hp_timing_t stop __attribute__ ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, dst, src, n); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align1, size_t align2, size_t len, size_t n, int max_char) +{ + size_t i; + char *s1, *s2; + + align1 &= 7; + if (align1 + len >= page_size) + return; + + align2 &= 7; + if (align2 + len >= page_size) + return; + + s1 = (char *) (buf1 + align1); + s2 = (char *) (buf2 + align2); + + for (i = 0; i < len; ++i) + s1[i] = 32 + 23 * i % (max_char - 32); + s1[len] = 0; + for (i = len + 1; i + align1 < page_size && i < len + 64; ++i) + s1[i] = 32 + 32 * i % (max_char - 32); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, n %4zd, alignment %2zd/%2zd:", len, n, align1, align2); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s2, s1, len, n); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%28s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (i, i, 16, 16, 127); + do_test (i, i, 16, 16, 255); + do_test (i, 2 * i, 16, 16, 127); + do_test (2 * i, i, 16, 16, 255); + do_test (8 - i, 2 * i, 1 << i, 2 << i, 127); + do_test (2 * i, 8 - i, 2 << i, 1 << i, 127); + do_test (8 - i, 2 * i, 1 << i, 2 << i, 255); + do_test (2 * i, 8 - i, 2 << i, 1 << i, 255); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 0, 4 << i, 8 << i, 127); + do_test (0, 0, 16 << i, 8 << i, 127); + do_test (8 - i, 2 * i, 4 << i, 8 << i, 127); + do_test (8 - i, 2 * i, 16 << i, 8 << i, 127); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strnlen-ifunc.c b/benchtests/bench-strnlen-ifunc.c new file mode 100644 index 0000000000..05563aa05a --- /dev/null +++ b/benchtests/bench-strnlen-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strnlen function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strnlen.c" diff --git a/benchtests/bench-strnlen.c b/benchtests/bench-strnlen.c new file mode 100644 index 0000000000..4233f279ba --- /dev/null +++ b/benchtests/bench-strnlen.c @@ -0,0 +1,139 @@ +/* Measure strlen functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "strnlen" +#include "bench-string.h" + +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 +simple_strnlen (const char *s, size_t maxlen) +{ + size_t i; + + for (i = 0; i < maxlen && s[i]; ++i); + return i; +} + +static void +do_one_test (impl_t *impl, const char *s, size_t maxlen, size_t exp_len) +{ + size_t len = CALL (impl, s, maxlen); + if (len != exp_len) + { + error (0, 0, "Wrong result in function %s %zd %zd", impl->name, + len, exp_len); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, maxlen); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t len, size_t maxlen, int max_char) +{ + size_t i; + + align &= 7; + if (align + len >= page_size) + return; + + for (i = 0; i < len; ++i) + buf1[align + i] = 1 + 7 * i % max_char; + buf1[align + len] = 0; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd:", len, align); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, (char *) (buf1 + align), maxlen, MIN (len, maxlen)); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (0, i, i - 1, 127); + do_test (0, i, i, 127); + do_test (0, i, i + 1, 127); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, i, i - 1, 127); + do_test (i, i, i, 127); + do_test (i, i, i + 1, 127); + } + + for (i = 2; i <= 10; ++i) + { + do_test (0, 1 << i, 5000, 127); + do_test (1, 1 << i, 5000, 127); + } + + for (i = 1; i < 8; ++i) + do_test (0, i, 5000, 255); + + for (i = 1; i < 8; ++i) + do_test (i, i, 5000, 255); + + for (i = 2; i <= 10; ++i) + { + do_test (0, 1 << i, 5000, 255); + do_test (1, 1 << i, 5000, 255); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strpbrk-ifunc.c b/benchtests/bench-strpbrk-ifunc.c new file mode 100644 index 0000000000..38f9881706 --- /dev/null +++ b/benchtests/bench-strpbrk-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strpbrk function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strpbrk.c" diff --git a/benchtests/bench-strpbrk.c b/benchtests/bench-strpbrk.c new file mode 100644 index 0000000000..0163de89bc --- /dev/null +++ b/benchtests/bench-strpbrk.c @@ -0,0 +1,182 @@ +/* Measure strpbrk functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef STRPBRK_RESULT +# define STRPBRK_RESULT(s, pos) ((s)[(pos)] ? (s) + (pos) : NULL) +# define RES_TYPE char * +# define TEST_MAIN +# define TEST_NAME "strpbrk" +# include "bench-string.h" + +typedef char *(*proto_t) (const char *, const char *); +char *simple_strpbrk (const char *, const char *); +char *stupid_strpbrk (const char *, const char *); + +IMPL (stupid_strpbrk, 0) +IMPL (simple_strpbrk, 0) +IMPL (strpbrk, 1) + +char * +simple_strpbrk (const char *s, const char *rej) +{ + const char *r; + char c; + + while ((c = *s++) != '\0') + for (r = rej; *r != '\0'; ++r) + if (*r == c) + return (char *) s - 1; + return NULL; +} + +char * +stupid_strpbrk (const char *s, const char *rej) +{ + size_t ns = strlen (s), nrej = strlen (rej); + size_t i, j; + + for (i = 0; i < ns; ++i) + for (j = 0; j < nrej; ++j) + if (s[i] == rej[j]) + return (char *) s + i; + return NULL; +} +#endif + +static void +do_one_test (impl_t *impl, const char *s, const char *rej, RES_TYPE exp_res) +{ + RES_TYPE res = CALL (impl, s, rej); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + (void *) res, (void *) exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, rej); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len) +{ + size_t i; + int c; + RES_TYPE result; + char *rej, *s; + + align &= 7; + if (align + pos + 10 >= page_size || len > 240) + return; + + rej = (char *) (buf2 + (random () & 255)); + s = (char *) (buf1 + align); + + for (i = 0; i < len; ++i) + { + rej[i] = random () & 255; + if (!rej[i]) + rej[i] = random () & 255; + if (!rej[i]) + rej[i] = 1 + (random () & 127); + } + rej[len] = '\0'; + for (c = 1; c <= 255; ++c) + if (strchr (rej, c) == NULL) + break; + + for (i = 0; i < pos; ++i) + { + s[i] = random () & 255; + if (strchr (rej, s[i])) + { + s[i] = random () & 255; + if (strchr (rej, s[i])) + s[i] = c; + } + } + s[pos] = rej[random () % (len + 1)]; + if (s[pos]) + { + for (i = pos + 1; i < pos + 10; ++i) + s[i] = random () & 255; + s[i] = '\0'; + } + result = STRPBRK_RESULT (s, pos); + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd, rej len %2zd:", pos, align, len); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s, rej, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%32s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 32; ++i) + { + do_test (0, 512, i); + do_test (i, 512, i); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 4); + do_test (i, 16 << i, 4); + } + + for (i = 1; i < 8; ++i) + do_test (i, 64, 10); + + for (i = 0; i < 64; ++i) + do_test (0, i, 6); + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strrchr-ifunc.c b/benchtests/bench-strrchr-ifunc.c new file mode 100644 index 0000000000..06283cd528 --- /dev/null +++ b/benchtests/bench-strrchr-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strrchr function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strrchr.c" diff --git a/benchtests/bench-strrchr.c b/benchtests/bench-strrchr.c new file mode 100644 index 0000000000..400ac80e2c --- /dev/null +++ b/benchtests/bench-strrchr.c @@ -0,0 +1,190 @@ +/* Measure STRCHR functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#ifdef WIDE +# define TEST_NAME "wcsrchr" +#else +# define TEST_NAME "strrchr" +#endif +#include "bench-string.h" + +#ifdef WIDE +# include <wchar.h> +# define SIMPLE_STRRCHR simple_wcsrchr +# define STRRCHR wcsrchr +# define CHAR wchar_t +# define UCHAR wchar_t +# define BIG_CHAR WCHAR_MAX +# define SMALL_CHAR 1273 +#else +# define SIMPLE_STRRCHR simple_strrchr +# define STRRCHR strrchr +# define CHAR char +# define UCHAR unsigned char +# define BIG_CHAR CHAR_MAX +# define SMALL_CHAR 127 +#endif + +typedef CHAR *(*proto_t) (const CHAR *, int); +CHAR *SIMPLE_STRRCHR (const CHAR *, int); + +IMPL (SIMPLE_STRRCHR, 0) +IMPL (STRRCHR, 1) + +CHAR * +SIMPLE_STRRCHR (const CHAR *s, int c) +{ + const CHAR *ret = NULL; + + for (; *s != '\0'; ++s) + if (*s == (CHAR) c) + ret = s; + + return (CHAR *) (c == '\0' ? s : ret); +} + +static void +do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) +{ + CHAR *res = CALL (impl, s, c); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + res, exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, c); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) +/* For wcsrchr: align here means align not in bytes, + but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) + len for wcschr here isn't in bytes but it's number of wchar_t symbols. */ +{ + size_t i; + CHAR *result; + CHAR *buf = (CHAR *) buf1; + + align &= 7; + if ( (align + len) * sizeof(CHAR) >= page_size) + return; + + for (i = 0; i < len; ++i) + { + buf[align + i] = (random () * random ()) & max_char; + if (!buf[align + i]) + buf[align + i] = (random () * random ()) & max_char; + if (!buf[align + i]) + buf[align + i] = 1; + if ((i > pos || pos >= len) && buf[align + i] == seek_char) + buf[align + i] = seek_char + 10 + (random () & 15); + } + buf[align + len] = 0; + + if (pos < len) + { + buf[align + pos] = seek_char; + result = (CHAR *) (buf + align + pos); + } + else if (seek_char == 0) + result = (CHAR *) (buf + align + len); + else + result = NULL; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment in bytes %2zd:", pos, align * sizeof(CHAR)); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, (CHAR *) (buf + align), seek_char, result); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%20s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 23, SMALL_CHAR); + do_test (i, 16 << i, 2048, 23, SMALL_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 64, 256, 23, SMALL_CHAR); + do_test (i, 64, 256, 23, BIG_CHAR); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, i, i + 1, 23, SMALL_CHAR); + do_test (0, i, i + 1, 23, BIG_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 2048, 0, SMALL_CHAR); + do_test (i, 16 << i, 2048, 0, SMALL_CHAR); + } + + for (i = 1; i < 8; ++i) + { + do_test (i, 64, 256, 0, SMALL_CHAR); + do_test (i, 64, 256, 0, BIG_CHAR); + } + + for (i = 0; i < 32; ++i) + { + do_test (0, i, i + 1, 0, SMALL_CHAR); + do_test (0, i, i + 1, 0, BIG_CHAR); + } + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strspn-ifunc.c b/benchtests/bench-strspn-ifunc.c new file mode 100644 index 0000000000..4040c2fb20 --- /dev/null +++ b/benchtests/bench-strspn-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strspn function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strspn.c" diff --git a/benchtests/bench-strspn.c b/benchtests/bench-strspn.c new file mode 100644 index 0000000000..7cf26f4709 --- /dev/null +++ b/benchtests/bench-strspn.c @@ -0,0 +1,174 @@ +/* Measure strspn functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "strspn" +#include "bench-string.h" + +typedef size_t (*proto_t) (const char *, const char *); +size_t simple_strspn (const char *, const char *); +size_t stupid_strspn (const char *, const char *); + +IMPL (stupid_strspn, 0) +IMPL (simple_strspn, 0) +IMPL (strspn, 1) + +size_t +simple_strspn (const char *s, const char *acc) +{ + const char *r, *str = s; + char c; + + while ((c = *s++) != '\0') + { + for (r = acc; *r != '\0'; ++r) + if (*r == c) + break; + if (*r == '\0') + return s - str - 1; + } + return s - str - 1; +} + +size_t +stupid_strspn (const char *s, const char *acc) +{ + size_t ns = strlen (s), nacc = strlen (acc); + size_t i, j; + + for (i = 0; i < ns; ++i) + { + for (j = 0; j < nacc; ++j) + if (s[i] == acc[j]) + break; + if (j == nacc) + return i; + } + return i; +} + +static void +do_one_test (impl_t *impl, const char *s, const char *acc, size_t exp_res) +{ + size_t res = CALL (impl, s, acc); + if (res != exp_res) + { + error (0, 0, "Wrong result in function %s %p %p", impl->name, + (void *) res, (void *) exp_res); + ret = 1; + return; + } + + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~ (hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s, acc); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + +static void +do_test (size_t align, size_t pos, size_t len) +{ + size_t i; + char *acc, *s; + + align &= 7; + if (align + pos + 10 >= page_size || len > 240 || ! len) + return; + + acc = (char *) (buf2 + (random () & 255)); + s = (char *) (buf1 + align); + + for (i = 0; i < len; ++i) + { + acc[i] = random () & 255; + if (!acc[i]) + acc[i] = random () & 255; + if (!acc[i]) + acc[i] = 1 + (random () & 127); + } + acc[len] = '\0'; + + for (i = 0; i < pos; ++i) + s[i] = acc[random () % len]; + s[pos] = random () & 255; + if (strchr (acc, s[pos])) + s[pos] = '\0'; + else + { + for (i = pos + 1; i < pos + 10; ++i) + s[i] = random () & 255; + s[i] = '\0'; + } + + if (HP_TIMING_AVAIL) + printf ("Length %4zd, alignment %2zd, acc len %2zd:", pos, align, len); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s, acc, pos); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +int +test_main (void) +{ + size_t i; + + test_init (); + + printf ("%32s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (i = 0; i < 32; ++i) + { + do_test (0, 512, i); + do_test (i, 512, i); + } + + for (i = 1; i < 8; ++i) + { + do_test (0, 16 << i, 4); + do_test (i, 16 << i, 4); + } + + for (i = 1; i < 8; ++i) + do_test (i, 64, 10); + + for (i = 0; i < 64; ++i) + do_test (0, i, 6); + + return ret; +} + +#include "../test-skeleton.c" diff --git a/benchtests/bench-strstr-ifunc.c b/benchtests/bench-strstr-ifunc.c new file mode 100644 index 0000000000..b187ca5037 --- /dev/null +++ b/benchtests/bench-strstr-ifunc.c @@ -0,0 +1,20 @@ +/* Measure IFUNC implementations of strstr function. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_IFUNC 1 +#include "bench-strstr.c" diff --git a/benchtests/bench-strstr.c b/benchtests/bench-strstr.c new file mode 100644 index 0000000000..91a8dfed6a --- /dev/null +++ b/benchtests/bench-strstr.c @@ -0,0 +1,183 @@ +/* Measure strstr functions. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_MAIN +#define TEST_NAME "strstr" +#include "bench-string.h" + + +#define STRSTR simple_strstr +#include "../string/strstr.c" + + +static char * +stupid_strstr (const char *s1, const char *s2) +{ + ssize_t s1len = strlen (s1); + ssize_t s2len = strlen (s2); + + if (s2len > s1len) + return NULL; + + for (ssize_t i = 0; i <= s1len - s2len; ++i) + { + size_t j; + for (j = 0; j < s2len; ++j) + if (s1[i + j] != s2[j]) + break; + if (j == s2len) + return (char *) s1 + i; + } + + return NULL; +} + + +typedef char *(*proto_t) (const char *, const char *); + +IMPL (stupid_strstr, 0) +IMPL (simple_strstr, 0) +IMPL (strstr, 1) + + +static void +do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result) +{ + if (HP_TIMING_AVAIL) + { + hp_timing_t start __attribute ((unused)); + hp_timing_t stop __attribute ((unused)); + hp_timing_t best_time = ~(hp_timing_t) 0; + size_t i; + + for (i = 0; i < 32; ++i) + { + HP_TIMING_NOW (start); + CALL (impl, s1, s2); + HP_TIMING_NOW (stop); + HP_TIMING_BEST (best_time, start, stop); + } + + printf ("\t%zd", (size_t) best_time); + } +} + + +static void +do_test (size_t align1, size_t align2, size_t len1, size_t len2, + int fail) +{ + char *s1 = (char *) (buf1 + align1); + char *s2 = (char *) (buf2 + align2); + + static const char d[] = "1234567890abcdef"; +#define dl (sizeof (d) - 1) + char *ss2 = s2; + for (size_t l = len2; l > 0; l = l > dl ? l - dl : 0) + { + size_t t = l > dl ? dl : l; + ss2 = mempcpy (ss2, d, t); + } + s2[len2] = '\0'; + + if (fail) + { + char *ss1 = s1; + for (size_t l = len1; l > 0; l = l > dl ? l - dl : 0) + { + size_t t = l > dl ? dl : l; + memcpy (ss1, d, t); + ++ss1[len2 > 7 ? 7 : len2 - 1]; + ss1 += t; + } + } + else + { + memset (s1, '0', len1); + memcpy (s1 + len1 - len2, s2, len2); + } + s1[len1] = '\0'; + + if (HP_TIMING_AVAIL) + printf ("Length %4zd/%zd, alignment %2zd/%2zd, %s:", + len1, len2, align1, align2, fail ? "fail" : "found"); + + FOR_EACH_IMPL (impl, 0) + do_one_test (impl, s1, s2, fail ? NULL : s1 + len1 - len2); + + if (HP_TIMING_AVAIL) + putchar ('\n'); +} + +static int +test_main (void) +{ + test_init (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) + printf ("\t%s", impl->name); + putchar ('\n'); + + for (size_t klen = 2; klen < 32; ++klen) + for (size_t hlen = 2 * klen; hlen < 16 * klen; hlen += klen) + { + do_test (0, 0, hlen, klen, 0); + do_test (0, 0, hlen, klen, 1); + do_test (0, 3, hlen, klen, 0); + do_test (0, 3, hlen, klen, 1); + do_test (0, 9, hlen, klen, 0); + do_test (0, 9, hlen, klen, 1); + do_test (0, 15, hlen, klen, 0); + do_test (0, 15, hlen, klen, 1); + + do_test (3, 0, hlen, klen, 0); + do_test (3, 0, hlen, klen, 1); + do_test (3, 3, hlen, klen, 0); + do_test (3, 3, hlen, klen, 1); + do_test (3, 9, hlen, klen, 0); + do_test (3, 9, hlen, klen, 1); + do_test (3, 15, hlen, klen, 0); + do_test (3, 15, hlen, klen, 1); + + do_test (9, 0, hlen, klen, 0); + do_test (9, 0, hlen, klen, 1); + do_test (9, 3, hlen, klen, 0); + do_test (9, 3, hlen, klen, 1); + do_test (9, 9, hlen, klen, 0); + do_test (9, 9, hlen, klen, 1); + do_test (9, 15, hlen, klen, 0); + do_test (9, 15, hlen, klen, 1); + + do_test (15, 0, hlen, klen, 0); + do_test (15, 0, hlen, klen, 1); + do_test (15, 3, hlen, klen, 0); + do_test (15, 3, hlen, klen, 1); + do_test (15, 9, hlen, klen, 0); + do_test (15, 9, hlen, klen, 1); + do_test (15, 15, hlen, klen, 0); + do_test (15, 15, hlen, klen, 1); + } + + do_test (0, 0, page_size - 1, 16, 0); + do_test (0, 0, page_size - 1, 16, 1); + + return ret; +} + +#include "../test-skeleton.c" |