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 | |
parent | c1f75dc386d533806d29b7e94118363a7b50eed8 (diff) | |
download | glibc-9702047480d9002522936c5e1e1ebe16f696880d.zip glibc-9702047480d9002522936c5e1e1ebe16f696880d.tar.gz glibc-9702047480d9002522936c5e1e1ebe16f696880d.tar.bz2 |
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.
62 files changed, 5053 insertions, 1 deletions
@@ -1,5 +1,67 @@ 2013-06-11 Siddhesh Poyarekar <siddhesh@redhat.com> + * benchtests/Makefile (string-bench): Add string benchmarks. + * benchtests/bench-bcopy-ifunc.c: New file. + * benchtests/bench-bcopy.c: New file. + * benchtests/bench-bzero-ifunc.c: New file. + * benchtests/bench-bzero.c: New file. + * benchtests/bench-memccpy-ifunc.c: New file. + * benchtests/bench-memccpy.c: New file. + * benchtests/bench-memchr-ifunc.c: New file. + * benchtests/bench-memchr.c: New file. + * benchtests/bench-memcmp-ifunc.c: New file. + * benchtests/bench-memcmp.c: New file. + * benchtests/bench-memmem-ifunc.c: New file. + * benchtests/bench-memmem.c: New file. + * benchtests/bench-memmove-ifunc.c: New file. + * benchtests/bench-memmove.c: New file. + * benchtests/bench-mempcpy-ifunc.c: New file. + * benchtests/bench-mempcpy.c: New file. + * benchtests/bench-memset-ifunc.c: New file. + * benchtests/bench-memset.c: New file. + * benchtests/bench-rawmemchr-ifunc.c: New file. + * benchtests/bench-rawmemchr.c: New file. + * benchtests/bench-stpcpy-ifunc.c: New file. + * benchtests/bench-stpcpy.c: New file. + * benchtests/bench-stpncpy-ifunc.c: New file. + * benchtests/bench-stpncpy.c: New file. + * benchtests/bench-strcasecmp-ifunc.c: New file. + * benchtests/bench-strcasecmp.c: New file. + * benchtests/bench-strcasestr-ifunc.c: New file. + * benchtests/bench-strcasestr.c: New file. + * benchtests/bench-strcat-ifunc.c: New file. + * benchtests/bench-strcat.c: New file. + * benchtests/bench-strchr-ifunc.c: New file. + * benchtests/bench-strchr.c: New file. + * benchtests/bench-strchrnul-ifunc.c: New file. + * benchtests/bench-strchrnul.c: New file. + * benchtests/bench-strcmp-ifunc.c: New file. + * benchtests/bench-strcmp.c: New file. + * benchtests/bench-strcpy-ifunc.c: New file. + * benchtests/bench-strcpy.c: New file. + * benchtests/bench-strcspn-ifunc.c: New file. + * benchtests/bench-strcspn.c: New file. + * benchtests/bench-strlen-ifunc.c: New file. + * benchtests/bench-strlen.c: New file. + * benchtests/bench-strncasecmp-ifunc.c: New file. + * benchtests/bench-strncasecmp.c: New file. + * benchtests/bench-strncat-ifunc.c: New file. + * benchtests/bench-strncat.c: New file. + * benchtests/bench-strncmp-ifunc.c: New file. + * benchtests/bench-strncmp.c: New file. + * benchtests/bench-strncpy-ifunc.c: New file. + * benchtests/bench-strncpy.c: New file. + * benchtests/bench-strnlen-ifunc.c: New file. + * benchtests/bench-strnlen.c: New file. + * benchtests/bench-strpbrk-ifunc.c: New file. + * benchtests/bench-strpbrk.c: New file. + * benchtests/bench-strrchr-ifunc.c: New file. + * benchtests/bench-strrchr.c: New file. + * benchtests/bench-strspn-ifunc.c: New file. + * benchtests/bench-strspn.c: New file. + * benchtests/bench-strstr-ifunc.c: New file. + * benchtests/bench-strstr.c: New file. + * benchtests/Makefile: Disable parallel execution of targets. (string-bench): Add memcpy. (benchset): New variable to store a list of benchmark sets. diff --git a/benchtests/Makefile b/benchtests/Makefile index 27d83f4..5023c7c 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 0000000..66020e9 --- /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 0000000..4d0d055 --- /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 0000000..84f1354 --- /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 0000000..18e7d17 --- /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 0000000..b61050f --- /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 0000000..612513c --- /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 0000000..dd2c39f --- /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 0000000..5470ce6 --- /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 0000000..4467164 --- /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 0000000..053bb50 --- /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 0000000..6b951d8 --- /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 0000000..ca758a8 --- /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 0000000..345e594 --- /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 0000000..dccde5d --- /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 0000000..4fa93e0 --- /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 0000000..0e0e3b9 --- /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 0000000..1d43eef --- /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 0000000..92e34f0 --- /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 0000000..b1e86f1 --- /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 0000000..a6b29d7 --- /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 0000000..d36bcb2 --- /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 0000000..0645298 --- /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 0000000..736cac0 --- /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 0000000..65ed800 --- /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 0000000..bdeb8c5 --- /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 0000000..27250bb --- /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 0000000..645f504 --- /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 0000000..289b490 --- /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 0000000..003dc38 --- /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 0000000..b70a272 --- /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 0000000..0ef1398 --- /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 0000000..710b592 --- /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 0000000..35c7cb1 --- /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 0000000..db5680c --- /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 0000000..01a8095 --- /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 0000000..63a3cd4 --- /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 0000000..d27a4f9 --- /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 0000000..4e024d4 --- /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 0000000..e257c9b --- /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 0000000..22b3b84 --- /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 0000000..fcd4592 --- /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 0000000..63b1e93 --- /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 0000000..df796e2 --- /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 0000000..5fa9220 --- /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 0000000..adcfd22 --- /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 0000000..904daa7 --- /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 0000000..1cae32b --- /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 0000000..b3af0f9 --- /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 0000000..d4eebe6 --- /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 0000000..4065c0a --- /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 0000000..05563aa --- /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 0000000..4233f27 --- /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 0000000..38f9881 --- /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 0000000..0163de8 --- /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 0000000..06283cd --- /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 0000000..400ac80 --- /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 0000000..4040c2f --- /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 0000000..7cf26f4 --- /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 0000000..b187ca5 --- /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 0000000..91a8dfe --- /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" |