RFC: Test optimizations for multiple architectures
H.J. Lu
hongjiu.lu@intel.com
Thu Nov 11 15:14:00 GMT 2010
With IFUNC functions, glibc testsuite can only test one implementation.
This patch adds --enable-test-multi-arch, which is disabled by default.
--enable-test-multi-arch will enable testing for all implementations
supported on build machine. This prove of concept implements testing
for 64bit memcpy. On Intel Core i7, I got
simple_memcpy builtin_memcpy memcpy __memcpy_ssse3_back __memcpy_ssse3 __memcpy_sse2
Length 1, alignment 0/ 0: 0 0 0 0 0 0
Length 1, alignment 0/ 0: 0 0 0 0 0 0
Length 1, alignment 0/ 0: 0 0 0 0 0 0
Length 1, alignment 0/ 0: 0 0 0 0 0 0
Length 2, alignment 0/ 0: 0 0 0 0 0 0
Length 2, alignment 1/ 0: 0 0 0 0 0 0
Length 2, alignment 0/ 1: 0 0 0 0 0 0
Length 2, alignment 1/ 1: 0 0 0 0 0 0
Length 4, alignment 0/ 0: 0 0 0 0 0 0
Any comments?
Thanks.
H.J.
---
2010-11-11 H.J. Lu <hongjiu.lu@intel.com>
* config.h.in (TEST_MULTIARCH): New.
* config.make.in (test-multi-arch): Likewise.
* configure.in: Add --enable-test-multi-arch.
* configure: Regenerated.
* debug/test-stpcpy_chk.c (TEST_NAME): New.
* debug/test-strcpy_chk.c (TEST_NAME): Likewise.
* string/test-memccpy.c (TEST_NAME): Likewise.
* string/test-memchr.c (TEST_NAME): Likewise.
* string/test-memcmp.c (TEST_NAME): Likewise.
* string/test-memcpy.c (TEST_NAME): Likewise.
* string/test-memmem.c (TEST_NAME): Likewise.
* string/test-memmove.c (TEST_NAME): Likewise.
* string/test-mempcpy.c (TEST_NAME): Likewise.
* string/test-memset.c (TEST_NAME): Likewise.
* string/test-stpcpy.c (TEST_NAME): Likewise.
* string/test-stpncpy.c (TEST_NAME): Likewise.
* string/test-strcasecmp.c (TEST_NAME): Likewise.
* string/test-strcasestr.c (TEST_NAME): Likewise.
* string/test-strcat.c (TEST_NAME): Likewise.
* string/test-strchr.c (TEST_NAME): Likewise.
* string/test-strcmp.c(TEST_NAME): Likewise.
* string/test-strcpy.c (TEST_NAME): Likewise.
* string/test-strcspn.c (TEST_NAME): Likewise.
* string/test-strlen.c (TEST_NAME): Likewise.
* string/test-strncasecmp.c (TEST_NAME): Likewise.
* string/test-strncmp.c (TEST_NAME): Likewise.
* string/test-strncpy.c (TEST_NAME): Likewise.
* string/test-strnlen.c (TEST_NAME): Likewise.
* string/test-strpbrk.c (TEST_NAME): Likewise.
* string/test-strrchr.c (TEST_NAME): Likewise.
* string/test-strspn.c (TEST_NAME): Likewise.
* string/test-strstr.c (TEST_NAME): Likewise.
* include/libc-test.h: New.
* sysdeps/generic/libc-test.c: Likewise.
* sysdeps/x86_64/multiarch/libc-test.c: Likewise.
* string/Makefile: Include ../Makeconfig.
(routines): Add libc-test if $(test-multi-arch) is yes.
* string/test-string.h: Include <libc-test.h>.
(FOR_EACH_IMPL): Support func_list.
(func_list): New.
(impl_count): Likewise.
(impl_array); Likewise.
(test_init): __libc_func to initialize func_list if
TEST_MULTIARCH is defined.
* string/Versions: Add __libc_func if TEST_MULTIARCH is defined.
* sysdeps/x86_64/multiarch/memcpy.S (__memcpy_sse2): Make it
global and hidden.
diff --git a/config.h.in b/config.h.in
index 18bf01a..7501aee 100644
--- a/config.h.in
+++ b/config.h.in
@@ -201,6 +201,9 @@
/* Define if multi-arch DSOs should be generated. */
#undef USE_MULTIARCH
+/* Define if optimizations for multiple architectures should be tested. */
+#undef TEST_MULTIARCH
+
/*
*/
diff --git a/config.make.in b/config.make.in
index efffee4..87aafb8 100644
--- a/config.make.in
+++ b/config.make.in
@@ -76,6 +76,7 @@ oldest-abi = @oldest_abi@
no-whole-archive = @no_whole_archive@
exceptions = @exceptions@
multi-arch = @multi_arch@
+test-multi-arch = @test_multi_arch@
mach-interface-list = @mach_interface_list@
diff --git a/configure b/configure
index eae35ba..ab31c22 100755
--- a/configure
+++ b/configure
@@ -684,6 +684,7 @@ add_on_subdirs
add_ons
libc_cv_nss_crypt
experimental_malloc
+test_multi_arch
all_warnings
force_install
bindnow
@@ -782,6 +783,7 @@ enable_force_install
enable_kernel
enable_all_warnings
enable_multi_arch
+enable_test_multi_arch
enable_experimental_malloc
enable_nss_crypt
with_cpu
@@ -1441,6 +1443,9 @@ Optional Features:
--enable-all-warnings enable all useful warnings gcc can issue
--enable-multi-arch enable single DSO with optimizations for multiple
architectures
+ --enable-test-multi-arch
+ enable test of optimizations for multiple
+ architectures
--enable-experimental-malloc
enable experimental malloc features
--enable-nss-crypt enable libcrypt to use nss
@@ -3750,6 +3755,19 @@ else
fi
+# Check whether --enable-test-multi-arch was given.
+if test "${enable_test_multi_arch+set}" = set; then :
+ enableval=$enable_test_multi_arch; test_multi_arch=$enableval
+else
+ test_multi_arch=no
+fi
+
+if test x"$test_multi_arch" != xno; then
+ $as_echo "#define TEST_MULTIARCH 1" >>confdefs.h
+
+fi
+
+
# Check whether --enable-experimental-malloc was given.
if test "${enable_experimental_malloc+set}" = set; then :
enableval=$enable_experimental_malloc; experimental_malloc=$enableval
diff --git a/configure.in b/configure.in
index d8cd5f1..f8f7602 100644
--- a/configure.in
+++ b/configure.in
@@ -274,6 +274,16 @@ AC_ARG_ENABLE([multi-arch],
[multi_arch=$enableval],
[multi_arch=default])
+AC_ARG_ENABLE([test-multi-arch],
+ AC_HELP_STRING([--enable-test-multi-arch],
+ [enable test of optimizations for multiple architectures]),
+ [test_multi_arch=$enableval],
+ [test_multi_arch=no])
+if test x"$test_multi_arch" != xno; then
+ AC_DEFINE(TEST_MULTIARCH)
+fi
+AC_SUBST(test_multi_arch)
+
AC_ARG_ENABLE([experimental-malloc],
AC_HELP_STRING([--enable-experimental-malloc],
[enable experimental malloc features]),
diff --git a/debug/test-stpcpy_chk.c b/debug/test-stpcpy_chk.c
index d717ca7..1f8f588 100644
--- a/debug/test-stpcpy_chk.c
+++ b/debug/test-stpcpy_chk.c
@@ -20,6 +20,7 @@
#define STRCPY_RESULT(dst, len) ((dst) + (len))
#define TEST_MAIN
+#define TEST_NAME "stpcpy_chk"
#include "../string/test-string.h"
extern void __attribute__ ((noreturn)) __chk_fail (void);
diff --git a/debug/test-strcpy_chk.c b/debug/test-strcpy_chk.c
index e08141d..05bd0cb 100644
--- a/debug/test-strcpy_chk.c
+++ b/debug/test-strcpy_chk.c
@@ -21,6 +21,7 @@
#ifndef STRCPY_RESULT
# define STRCPY_RESULT(dst, len) dst
# define TEST_MAIN
+# define TEST_NAME "strcpy_chk"
# include "../string/test-string.h"
extern void __attribute__ ((noreturn)) __chk_fail (void);
diff --git a/include/libc-test.h b/include/libc-test.h
new file mode 100644
index 0000000..edd814f
--- /dev/null
+++ b/include/libc-test.h
@@ -0,0 +1,33 @@
+/* Copyright (C) 2010 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#ifndef _LIBC_TEST_H
+#define _LIBC_TEST_H 1
+
+struct libc_func_test
+{
+ /* The name of function to be tested. */
+ const char *name;
+ /* The address of function to be tested. */
+ void (*fn) (void);
+};
+
+/* Return the NULL terminated array of functions. */
+extern const struct libc_func_test *__libc_func (const char *);
+
+#endif /* libc-symbols.h */
diff --git a/string/Makefile b/string/Makefile
index f836f59..7439f45 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -42,6 +42,12 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \
strcoll_l strxfrm_l string-inlines memrchr \
xpg-strerror strerror_l
+include ../Makeconfig
+
+ifeq (yes,$(test-multi-arch))
+routines += libc-test
+endif
+
# Gcc internally generates calls to unbounded memcpy and memset
# for -fbounded-pointer compiles. Glibc uses memchr for explicit checks.
o-objects.ob := memcpy.o memset.o memchr.o
diff --git a/string/Versions b/string/Versions
index f145fd3..9cecf29 100644
--- a/string/Versions
+++ b/string/Versions
@@ -80,4 +80,9 @@ libc {
GLIBC_2.6 {
strerror_l;
}
+%ifdef TEST_MULTIARCH
+ GLIBC_PRIVATE {
+ __libc_func;
+ }
+%endif
}
diff --git a/string/test-memccpy.c b/string/test-memccpy.c
index 2653263..c5676cf 100644
--- a/string/test-memccpy.c
+++ b/string/test-memccpy.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "memccpy"
#include "test-string.h"
void *simple_memccpy (void *, const void *, int, size_t);
diff --git a/string/test-memchr.c b/string/test-memchr.c
index cd9a01e..ab510ef 100644
--- a/string/test-memchr.c
+++ b/string/test-memchr.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "memchr"
#include "test-string.h"
typedef char *(*proto_t) (const char *, int, size_t);
diff --git a/string/test-memcmp.c b/string/test-memcmp.c
index 3040e21..4fbfa54 100644
--- a/string/test-memcmp.c
+++ b/string/test-memcmp.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "memcmp"
#include "test-string.h"
typedef int (*proto_t) (const char *, const char *, size_t);
diff --git a/string/test-memcpy.c b/string/test-memcpy.c
index 7b0723a..5b5c657 100644
--- a/string/test-memcpy.c
+++ b/string/test-memcpy.c
@@ -22,6 +22,7 @@
# define MEMCPY_RESULT(dst, len) dst
# define MIN_PAGE_SIZE 131072
# define TEST_MAIN
+# define TEST_NAME "memcpy"
# include "test-string.h"
char *simple_memcpy (char *, const char *, size_t);
diff --git a/string/test-memmem.c b/string/test-memmem.c
index 91b661b..4402623 100644
--- a/string/test-memmem.c
+++ b/string/test-memmem.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "memmem"
#define BUF1PAGES 20
#define ITERATIONS 500
#include "test-string.h"
diff --git a/string/test-memmove.c b/string/test-memmove.c
index 2f3a8f7..cf3fa1e 100644
--- a/string/test-memmove.c
+++ b/string/test-memmove.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "memmove"
#include "test-string.h"
typedef char *(*proto_t) (char *, const char *, size_t);
diff --git a/string/test-mempcpy.c b/string/test-mempcpy.c
index f8b0267..9bf2e86 100644
--- a/string/test-mempcpy.c
+++ b/string/test-mempcpy.c
@@ -20,6 +20,7 @@
#define MEMCPY_RESULT(dst, len) (dst) + (len)
#define TEST_MAIN
+#define TEST_NAME "mempcpy"
#include "test-string.h"
char *simple_mempcpy (char *, const char *, size_t);
diff --git a/string/test-memset.c b/string/test-memset.c
index 601ace4..cdc51d0 100644
--- a/string/test-memset.c
+++ b/string/test-memset.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "memset"
#define MIN_PAGE_SIZE 131072
#include "test-string.h"
diff --git a/string/test-stpcpy.c b/string/test-stpcpy.c
index c8d4cc4..0582aaa 100644
--- a/string/test-stpcpy.c
+++ b/string/test-stpcpy.c
@@ -20,6 +20,7 @@
#define STRCPY_RESULT(dst, len) ((dst) + (len))
#define TEST_MAIN
+#define TEST_NAME "stpcpy"
#include "test-string.h"
char *simple_stpcpy (char *, const char *);
diff --git a/string/test-stpncpy.c b/string/test-stpncpy.c
index 8784588..115cf79 100644
--- a/string/test-stpncpy.c
+++ b/string/test-stpncpy.c
@@ -20,6 +20,7 @@
#define STRNCPY_RESULT(dst, len, n) ((dst) + ((len) > (n) ? (n) : (len)))
#define TEST_MAIN
+#define TEST_NAME "stpncpy"
#include "test-string.h"
char *simple_stpncpy (char *, const char *, size_t);
diff --git a/string/test-strcasecmp.c b/string/test-strcasecmp.c
index 7d1d110..261af13 100644
--- a/string/test-strcasecmp.c
+++ b/string/test-strcasecmp.c
@@ -20,6 +20,7 @@
#include <ctype.h>
#define TEST_MAIN
+#define TEST_NAME "strcasecmp"
#include "test-string.h"
typedef int (*proto_t) (const char *, const char *);
diff --git a/string/test-strcasestr.c b/string/test-strcasestr.c
index edc41f3..9981c23 100644
--- a/string/test-strcasestr.c
+++ b/string/test-strcasestr.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strcasestr"
#include "test-string.h"
diff --git a/string/test-strcat.c b/string/test-strcat.c
index 4437520..83b133a 100644
--- a/string/test-strcat.c
+++ b/string/test-strcat.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strcat"
#include "test-string.h"
typedef char *(*proto_t) (char *, const char *);
diff --git a/string/test-strchr.c b/string/test-strchr.c
index cf25b44..200327c 100644
--- a/string/test-strchr.c
+++ b/string/test-strchr.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strchr"
#include "test-string.h"
typedef char *(*proto_t) (const char *, int);
diff --git a/string/test-strcmp.c b/string/test-strcmp.c
index 769e982..71242e3 100644
--- a/string/test-strcmp.c
+++ b/string/test-strcmp.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strcmp"
#include "test-string.h"
typedef int (*proto_t) (const char *, const char *);
diff --git a/string/test-strcpy.c b/string/test-strcpy.c
index 6a2ea25..7a4e3be 100644
--- a/string/test-strcpy.c
+++ b/string/test-strcpy.c
@@ -21,6 +21,7 @@
#ifndef STRCPY_RESULT
# define STRCPY_RESULT(dst, len) dst
# define TEST_MAIN
+# define TEST_NAME "strcpy"
# include "test-string.h"
char *simple_strcpy (char *, const char *);
diff --git a/string/test-strcspn.c b/string/test-strcspn.c
index b563179..403a2fd 100644
--- a/string/test-strcspn.c
+++ b/string/test-strcspn.c
@@ -21,6 +21,7 @@
#define STRPBRK_RESULT(s, pos) (pos)
#define RES_TYPE size_t
#define TEST_MAIN
+#define TEST_NAME "strcspn"
#include "test-string.h"
typedef size_t (*proto_t) (const char *, const char *);
diff --git a/string/test-string.h b/string/test-string.h
index 1aea4c9..93773e3 100644
--- a/string/test-string.h
+++ b/string/test-string.h
@@ -48,6 +48,7 @@ extern impl_t __start_impls[], __stop_impls[];
#include <error.h>
#include <errno.h>
#include <time.h>
+#include <libc-test.h>
#define GL(x) _##x
#define GLRO(x) _##x
#include <hp-timing.h>
@@ -105,7 +106,38 @@ size_t iterations = 100000;
(* (proto_t) (impl)->fn) (__VA_ARGS__)
#define FOR_EACH_IMPL(impl, notall) \
- for (impl_t *impl = __start_impls; impl < __stop_impls; ++impl) \
+ impl_t *impl; \
+ int count; \
+ if (impl_count == -1) \
+ { \
+ impl_count = 0; \
+ for (impl = __start_impls; impl < __stop_impls; ++impl) \
+ impl_count++; \
+ if (func_list) \
+ { \
+ const struct libc_func_test *p; \
+ for (p = func_list; p && p->name; ++p) \
+ impl_count++; \
+ if (impl_count) \
+ { \
+ impl_t *a; \
+ a = impl_array = malloc (impl_count * sizeof (impl_t)); \
+ for (impl = __start_impls; impl < __stop_impls; ++impl) \
+ *a++ = *impl; \
+ for (p = func_list; p && p->name; ++p) \
+ { \
+ a->name = p->name; \
+ a->fn = p->fn; \
+ a->test = 1; \
+ a++; \
+ } \
+ } \
+ } \
+ else \
+ impl_array = __start_impls; \
+ } \
+ impl = impl_array; \
+ for (count = 0; count < impl_count; ++count, ++impl) \
if (!notall || impl->test)
#define HP_TIMING_BEST(best_time, start, end) \
@@ -122,9 +154,17 @@ size_t iterations = 100000;
# define BUF1PAGES 1
#endif
+static const struct libc_func_test *func_list;
+static int impl_count = -1;
+static impl_t *impl_array;
+
static void
test_init (void)
{
+#ifdef TEST_MULTIARCH
+ func_list = __libc_func (TEST_NAME);
+#endif
+
page_size = 2 * getpagesize ();
#ifdef MIN_PAGE_SIZE
if (page_size < MIN_PAGE_SIZE)
diff --git a/string/test-strlen.c b/string/test-strlen.c
index e01befb..feb1c5d 100644
--- a/string/test-strlen.c
+++ b/string/test-strlen.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strlen"
#include "test-string.h"
typedef size_t (*proto_t) (const char *);
diff --git a/string/test-strncasecmp.c b/string/test-strncasecmp.c
index daff6ed..9ec8955 100644
--- a/string/test-strncasecmp.c
+++ b/string/test-strncasecmp.c
@@ -20,6 +20,7 @@
#include <ctype.h>
#define TEST_MAIN
+#define TEST_NAME "strncasecmp"
#include "test-string.h"
typedef int (*proto_t) (const char *, const char *, size_t);
diff --git a/string/test-strncmp.c b/string/test-strncmp.c
index 3687879..891acb0 100644
--- a/string/test-strncmp.c
+++ b/string/test-strncmp.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strncmp"
#include "test-string.h"
typedef int (*proto_t) (const char *, const char *, size_t);
diff --git a/string/test-strncpy.c b/string/test-strncpy.c
index d7a714c..f89b27d 100644
--- a/string/test-strncpy.c
+++ b/string/test-strncpy.c
@@ -21,6 +21,7 @@
#ifndef STRNCPY_RESULT
# define STRNCPY_RESULT(dst, len, n) dst
# define TEST_MAIN
+# define TEST_NAME "strncpy"
# include "test-string.h"
char *simple_strncpy (char *, const char *, size_t);
diff --git a/string/test-strnlen.c b/string/test-strnlen.c
index cb8c80f..d078729 100644
--- a/string/test-strnlen.c
+++ b/string/test-strnlen.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strnlen"
#include "test-string.h"
typedef size_t (*proto_t) (const char *, size_t);
diff --git a/string/test-strpbrk.c b/string/test-strpbrk.c
index f3ed208..76ac8c7 100644
--- a/string/test-strpbrk.c
+++ b/string/test-strpbrk.c
@@ -22,6 +22,7 @@
# define STRPBRK_RESULT(s, pos) ((s)[(pos)] ? (s) + (pos) : NULL)
# define RES_TYPE char *
# define TEST_MAIN
+# define TEST_NAME "strpbrk"
# include "test-string.h"
typedef char *(*proto_t) (const char *, const char *);
diff --git a/string/test-strrchr.c b/string/test-strrchr.c
index 92e8ab1..64af621 100644
--- a/string/test-strrchr.c
+++ b/string/test-strrchr.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strrchr"
#include "test-string.h"
typedef char *(*proto_t) (const char *, int);
diff --git a/string/test-strspn.c b/string/test-strspn.c
index 15cf492..ad7b845 100644
--- a/string/test-strspn.c
+++ b/string/test-strspn.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strspn"
#include "test-string.h"
typedef size_t (*proto_t) (const char *, const char *);
diff --git a/string/test-strstr.c b/string/test-strstr.c
index c1da686..6116d70 100644
--- a/string/test-strstr.c
+++ b/string/test-strstr.c
@@ -19,6 +19,7 @@
02111-1307 USA. */
#define TEST_MAIN
+#define TEST_NAME "strstr"
#include "test-string.h"
diff --git a/sysdeps/generic/libc-test.c b/sysdeps/generic/libc-test.c
new file mode 100644
index 0000000..672e1e4
--- /dev/null
+++ b/sysdeps/generic/libc-test.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 2010 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdlib.h>
+#include <libc-test.h>
+
+/* Return the NULL terminated array of functions. */
+
+const struct libc_func_test *
+__libc_func (const char *name __attribute__ ((unused)))
+{
+ return NULL;
+}
diff --git a/sysdeps/x86_64/multiarch/libc-test.c b/sysdeps/x86_64/multiarch/libc-test.c
new file mode 100644
index 0000000..5975e0b
--- /dev/null
+++ b/sysdeps/x86_64/multiarch/libc-test.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2010 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <libc-test.h>
+#include "init-arch.h"
+
+#if defined SHARED && !defined NOT_IN_libc
+extern void *__memcpy_sse2 (void *, const void *, size_t);
+extern void *__memcpy_ssse3 (void *, const void *, size_t);
+extern void *__memcpy_ssse3_back (void *, const void *, size_t);
+
+static const struct libc_func_test memcpy_list [] =
+{
+ { "__memcpy_ssse3_back", (void (*) (void)) __memcpy_ssse3_back },
+ { "__memcpy_ssse3", (void (*) (void)) __memcpy_ssse3 },
+ { "__memcpy_sse2", (void (*) (void)) __memcpy_sse2 },
+ { NULL, NULL },
+};
+
+static const struct libc_func_test *
+find_memcpy (void)
+{
+ return memcpy_list + (HAS_SSSE3 ? 0 : 2);
+}
+#else
+static const struct libc_func_test *
+find_memcpy (void)
+{
+ return NULL;
+}
+#endif
+
+const struct libc_func_test *
+__libc_func (const char *name)
+{
+ if (strcmp (name, "memcpy") == 0)
+ return find_memcpy ();
+
+ return NULL;
+}
diff --git a/sysdeps/x86_64/multiarch/memcpy.S b/sysdeps/x86_64/multiarch/memcpy.S
index 8e9fb19..a45ca9f 100644
--- a/sysdeps/x86_64/multiarch/memcpy.S
+++ b/sysdeps/x86_64/multiarch/memcpy.S
@@ -44,6 +44,8 @@ END(memcpy)
# undef ENTRY
# define ENTRY(name) \
.type __memcpy_sse2, @function; \
+ .globl __memcpy_sse2; \
+ .hidden __memcpy_sse2; \
.p2align 4; \
__memcpy_sse2: cfi_startproc; \
CALL_MCOUNT
More information about the Libc-alpha
mailing list