about summary refs log tree commit diff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-08-20 13:57:22 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-08-20 16:25:22 -0700
commit6458faf199de42a3bba3dc7cad9fb38d66bf0b4d (patch)
treeab91cebf0633a9f9dad6263cb75ff16c3cf01a9c
parent507abbad59c5777be75a6bac5f887d919af44e6d (diff)
downloadglibc-6458faf199de42a3bba3dc7cad9fb38d66bf0b4d.tar.gz
glibc-6458faf199de42a3bba3dc7cad9fb38d66bf0b4d.tar.xz
glibc-6458faf199de42a3bba3dc7cad9fb38d66bf0b4d.zip
Add i386 strcmp family multiarch functions
-rw-r--r--sysdeps/i386/i686/rtld-strcmp.S1
-rw-r--r--sysdeps/i386/multiarch/Makefile8
-rw-r--r--sysdeps/i386/multiarch/ifunc-impl-list.c22
-rw-r--r--sysdeps/i386/multiarch/rtld-strcmp.c1
-rw-r--r--sysdeps/i386/multiarch/strcasecmp-i386.c (renamed from sysdeps/i386/i686/multiarch/strcasecmp-c.c)2
-rw-r--r--sysdeps/i386/multiarch/strcasecmp.c53
-rw-r--r--sysdeps/i386/multiarch/strcasecmp_l-i386.c (renamed from sysdeps/i386/i686/multiarch/strcasecmp_l-c.c)2
-rw-r--r--sysdeps/i386/multiarch/strcasecmp_l-sse4.S (renamed from sysdeps/i386/i686/multiarch/strcasecmp_l-sse4.S)0
-rw-r--r--sysdeps/i386/multiarch/strcasecmp_l-ssse3.S (renamed from sysdeps/i386/i686/multiarch/strcasecmp_l-ssse3.S)0
-rw-r--r--sysdeps/i386/multiarch/strcasecmp_l.c53
-rw-r--r--sysdeps/i386/multiarch/strcmp-i386.c10
-rw-r--r--sysdeps/i386/multiarch/strcmp-i686.S16
-rw-r--r--sysdeps/i386/multiarch/strcmp-sse4.S (renamed from sysdeps/i386/i686/multiarch/strcmp-sse4.S)0
-rw-r--r--sysdeps/i386/multiarch/strcmp-ssse3.S (renamed from sysdeps/i386/i686/multiarch/strcmp-ssse3.S)0
-rw-r--r--sysdeps/i386/multiarch/strcmp.c58
-rw-r--r--sysdeps/i386/multiarch/strncase-i386.c (renamed from sysdeps/i386/i686/multiarch/strncase-c.c)2
-rw-r--r--sysdeps/i386/multiarch/strncase.c53
-rw-r--r--sysdeps/i386/multiarch/strncase_l-i386.c (renamed from sysdeps/i386/i686/multiarch/strncase_l-c.c)2
-rw-r--r--sysdeps/i386/multiarch/strncase_l-sse4.S (renamed from sysdeps/i386/i686/multiarch/strncase_l-sse4.S)0
-rw-r--r--sysdeps/i386/multiarch/strncase_l-ssse3.S (renamed from sysdeps/i386/i686/multiarch/strncase_l-ssse3.S)0
-rw-r--r--sysdeps/i386/multiarch/strncase_l.c53
-rw-r--r--sysdeps/i386/multiarch/strncmp-i386.c (renamed from sysdeps/i386/i686/multiarch/strncmp-c.c)4
-rw-r--r--sysdeps/i386/multiarch/strncmp-sse4.S (renamed from sysdeps/i386/i686/multiarch/strncmp-sse4.S)0
-rw-r--r--sysdeps/i386/multiarch/strncmp-ssse3.S (renamed from sysdeps/i386/i686/multiarch/strncmp-ssse3.S)0
-rw-r--r--sysdeps/i386/multiarch/strncmp.c54
25 files changed, 379 insertions, 15 deletions
diff --git a/sysdeps/i386/i686/rtld-strcmp.S b/sysdeps/i386/i686/rtld-strcmp.S
new file mode 100644
index 0000000000..01f31f4ef8
--- /dev/null
+++ b/sysdeps/i386/i686/rtld-strcmp.S
@@ -0,0 +1 @@
+#include <sysdeps/i386/i686/strcmp.S>
diff --git a/sysdeps/i386/multiarch/Makefile b/sysdeps/i386/multiarch/Makefile
index 147258cbe9..ba6a489303 100644
--- a/sysdeps/i386/multiarch/Makefile
+++ b/sysdeps/i386/multiarch/Makefile
@@ -25,7 +25,13 @@ sysdep_routines += bcopy-i386 bcopy-i686 bcopy-sse2-unaligned \
 		   stpcpy-i386 stpcpy-i586 stpcpy-sse2 stpcpy-ssse3 \
 		   stpncpy-i386 stpncpy-sse2 stpncpy-ssse3 \
 		   strcpy-i386 strcpy-i586 strcpy-sse2 strcpy-ssse3 \
-		   strncpy-i386 strncpy-sse2 strncpy-ssse3
+		   strncpy-i386 strncpy-sse2 strncpy-ssse3 \
+		   strcmp-i386 strcmp-i686 strcmp-sse4 strcmp-ssse3 \
+		   strcasecmp-i386 strcasecmp_l-i386 strcasecmp_l-sse4 \
+		   strcasecmp_l-ssse3 \
+		   strncase-i386 strncase_l-i386 strncase_l-sse4 \
+		   strncase_l-ssse3 \
+		   strncmp-i386 strncmp-ssse3 strncmp-sse4 
 endif
 
 ifeq (mathyes,$(subdir)$(config-cflags-avx))
diff --git a/sysdeps/i386/multiarch/ifunc-impl-list.c b/sysdeps/i386/multiarch/ifunc-impl-list.c
index 73cd46d15c..015ad3c6dd 100644
--- a/sysdeps/i386/multiarch/ifunc-impl-list.c
+++ b/sysdeps/i386/multiarch/ifunc-impl-list.c
@@ -191,7 +191,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 #endif
 	     )
 
-#if 0
   /* Support sysdeps/i386/i686/multiarch/strcasecmp.S.  */
   IFUNC_IMPL (i, name, strcasecmp,
 	      IFUNC_IMPL_ADD (array, i, strcasecmp,
@@ -200,7 +199,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 	      IFUNC_IMPL_ADD (array, i, strcasecmp,
 			      HAS_CPU_FEATURE (SSSE3),
 			      __strcasecmp_ssse3)
-	      IFUNC_IMPL_ADD (array, i, strcasecmp, 1, __strcasecmp_ia32))
+	      IFUNC_IMPL_ADD (array, i, strcasecmp, 1, __strcasecmp_i386))
 
   /* Support sysdeps/i386/i686/multiarch/strcasecmp_l.S.  */
   IFUNC_IMPL (i, name, strcasecmp_l,
@@ -211,8 +210,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      HAS_CPU_FEATURE (SSSE3),
 			      __strcasecmp_l_ssse3)
 	      IFUNC_IMPL_ADD (array, i, strcasecmp_l, 1,
-			      __strcasecmp_l_ia32))
+			      __strcasecmp_l_i386))
 
+#if 0
   /* Support sysdeps/i386/i686/multiarch/strcat.S.  */
   IFUNC_IMPL (i, name, strcat,
 	      IFUNC_IMPL_ADD (array, i, strcat, HAS_CPU_FEATURE (SSSE3),
@@ -228,6 +228,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 	      IFUNC_IMPL_ADD (array, i, strchr, HAS_CPU_FEATURE (SSE2),
 			      __strchr_sse2)
 	      IFUNC_IMPL_ADD (array, i, strchr, 1, __strchr_ia32))
+#endif
 
   /* Support sysdeps/i386/i686/multiarch/strcmp.S.  */
   IFUNC_IMPL (i, name, strcmp,
@@ -235,8 +236,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __strcmp_sse4_2)
 	      IFUNC_IMPL_ADD (array, i, strcmp, HAS_CPU_FEATURE (SSSE3),
 			      __strcmp_ssse3)
-	      IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_ia32))
+	      IFUNC_IMPL_ADD (array, i, strcmp, HAS_I686, __strcmp_i686)
+#if !SUPPORT_I686
+	      IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_i386)
 #endif
+	      )
 
   /* Support sysdeps/i386/i686/multiarch/strcpy.S.  */
   IFUNC_IMPL (i, name, strcpy,
@@ -256,6 +260,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 	      IFUNC_IMPL_ADD (array, i, strcspn, HAS_CPU_FEATURE (SSE4_2),
 			      __strcspn_sse42)
 	      IFUNC_IMPL_ADD (array, i, strcspn, 1, __strcspn_ia32))
+#endif
 
   /* Support sysdeps/i386/i686/multiarch/strncase.S.  */
   IFUNC_IMPL (i, name, strncasecmp,
@@ -266,7 +271,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      HAS_CPU_FEATURE (SSSE3),
 			      __strncasecmp_ssse3)
 	      IFUNC_IMPL_ADD (array, i, strncasecmp, 1,
-			      __strncasecmp_ia32))
+			      __strncasecmp_i386))
 
   /* Support sysdeps/i386/i686/multiarch/strncase_l.S.  */
   IFUNC_IMPL (i, name, strncasecmp_l,
@@ -277,8 +282,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      HAS_CPU_FEATURE (SSSE3),
 			      __strncasecmp_l_ssse3)
 	      IFUNC_IMPL_ADD (array, i, strncasecmp_l, 1,
-			      __strncasecmp_l_ia32))
+			      __strncasecmp_l_i386))
 
+#if 0
   /* Support sysdeps/i386/i686/multiarch/strncat.S.  */
   IFUNC_IMPL (i, name, strncat,
 	      IFUNC_IMPL_ADD (array, i, strncat, HAS_CPU_FEATURE (SSSE3),
@@ -451,6 +457,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 	      IFUNC_IMPL_ADD (array, i, strlen, HAS_CPU_FEATURE (SSE2),
 			      __strlen_sse2)
 	      IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_ia32))
+#endif
 
   /* Support sysdeps/i386/i686/multiarch/strncmp.S.  */
   IFUNC_IMPL (i, name, strncmp,
@@ -458,8 +465,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 			      __strncmp_sse4_2)
 	      IFUNC_IMPL_ADD (array, i, strncmp, HAS_CPU_FEATURE (SSSE3),
 			      __strncmp_ssse3)
-	      IFUNC_IMPL_ADD (array, i, strncmp, 1, __strncmp_ia32))
-#endif
+	      IFUNC_IMPL_ADD (array, i, strncmp, 1, __strncmp_i386))
 #endif
 
   return i;
diff --git a/sysdeps/i386/multiarch/rtld-strcmp.c b/sysdeps/i386/multiarch/rtld-strcmp.c
new file mode 100644
index 0000000000..78448ae52b
--- /dev/null
+++ b/sysdeps/i386/multiarch/rtld-strcmp.c
@@ -0,0 +1 @@
+#include "string/strcmp.c"
diff --git a/sysdeps/i386/i686/multiarch/strcasecmp-c.c b/sysdeps/i386/multiarch/strcasecmp-i386.c
index 753c6ec84a..eb5d602dc1 100644
--- a/sysdeps/i386/i686/multiarch/strcasecmp-c.c
+++ b/sysdeps/i386/multiarch/strcasecmp-i386.c
@@ -5,7 +5,7 @@ extern __typeof (strcasecmp) __strcasecmp_nonascii;
 #define __strcasecmp __strcasecmp_nonascii
 #include <string/strcasecmp.c>
 
-strong_alias (__strcasecmp_nonascii, __strcasecmp_ia32)
+strong_alias (__strcasecmp_nonascii, __strcasecmp_i386)
 
 /* The needs of strcasecmp in libc are minimal, no need to go through
    the IFUNC.  */
diff --git a/sysdeps/i386/multiarch/strcasecmp.c b/sysdeps/i386/multiarch/strcasecmp.c
new file mode 100644
index 0000000000..261bd7a893
--- /dev/null
+++ b/sysdeps/i386/multiarch/strcasecmp.c
@@ -0,0 +1,53 @@
+/* Multiple versions of strcasecmp.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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 multiple versions only for the definition in lib.  */
+#if IS_IN (libc)
+/* Redefine strcasecmp so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strcasecmp
+# define strcasecmp __redirect_strcasecmp
+# include <string.h>
+# undef strcasecmp
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_strcasecmp) __strcasecmp_i386 attribute_hidden;
+extern __typeof (__redirect_strcasecmp) __strcasecmp_ssse3 attribute_hidden;
+extern __typeof (__redirect_strcasecmp) __strcasecmp_sse4_2 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_strcasecmp) __strcasecmp;
+extern void *strcasecmp_ifunc (void) __asm__ ("__strcasecmp");
+
+void *
+strcasecmp_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSE4_2))
+    return __strcasecmp_sse4_2;
+  else if (HAS_CPU_FEATURE (SSSE3))
+    return __strcasecmp_ssse3;
+
+  return __strcasecmp_i386;
+}
+__asm__ (".type __strcasecmp, %gnu_indirect_function");
+
+weak_alias (__strcasecmp, strcasecmp)
+#endif
diff --git a/sysdeps/i386/i686/multiarch/strcasecmp_l-c.c b/sysdeps/i386/multiarch/strcasecmp_l-i386.c
index d4fcd2b4a1..b5b38d3f7a 100644
--- a/sysdeps/i386/i686/multiarch/strcasecmp_l-c.c
+++ b/sysdeps/i386/multiarch/strcasecmp_l-i386.c
@@ -6,7 +6,7 @@ extern __typeof (strcasecmp_l) __strcasecmp_l_nonascii;
 #define USE_IN_EXTENDED_LOCALE_MODEL    1
 #include <string/strcasecmp.c>
 
-strong_alias (__strcasecmp_l_nonascii, __strcasecmp_l_ia32)
+strong_alias (__strcasecmp_l_nonascii, __strcasecmp_l_i386)
 
 /* The needs of strcasecmp in libc are minimal, no need to go through
    the IFUNC.  */
diff --git a/sysdeps/i386/i686/multiarch/strcasecmp_l-sse4.S b/sysdeps/i386/multiarch/strcasecmp_l-sse4.S
index 411d4153f2..411d4153f2 100644
--- a/sysdeps/i386/i686/multiarch/strcasecmp_l-sse4.S
+++ b/sysdeps/i386/multiarch/strcasecmp_l-sse4.S
diff --git a/sysdeps/i386/i686/multiarch/strcasecmp_l-ssse3.S b/sysdeps/i386/multiarch/strcasecmp_l-ssse3.S
index a22b93c518..a22b93c518 100644
--- a/sysdeps/i386/i686/multiarch/strcasecmp_l-ssse3.S
+++ b/sysdeps/i386/multiarch/strcasecmp_l-ssse3.S
diff --git a/sysdeps/i386/multiarch/strcasecmp_l.c b/sysdeps/i386/multiarch/strcasecmp_l.c
new file mode 100644
index 0000000000..7bdc760a3f
--- /dev/null
+++ b/sysdeps/i386/multiarch/strcasecmp_l.c
@@ -0,0 +1,53 @@
+/* Multiple versions of strcasecmp_l.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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 multiple versions only for the definition in lib.  */
+#if IS_IN (libc)
+/* Redefine strcasecmp_l so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strcasecmp_l
+# define strcasecmp_l __redirect_strcasecmp_l
+# include <string.h>
+# undef strcasecmp_l
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_strcasecmp_l) __strcasecmp_l_i386 attribute_hidden;
+extern __typeof (__redirect_strcasecmp_l) __strcasecmp_l_ssse3 attribute_hidden;
+extern __typeof (__redirect_strcasecmp_l) __strcasecmp_l_sse4_2 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_strcasecmp_l) __strcasecmp_l;
+extern void *strcasecmp_l_ifunc (void) __asm__ ("__strcasecmp_l");
+
+void *
+strcasecmp_l_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSE4_2))
+    return __strcasecmp_l_sse4_2;
+  else if (HAS_CPU_FEATURE (SSSE3))
+    return __strcasecmp_l_ssse3;
+
+  return __strcasecmp_l_i386;
+}
+__asm__ (".type __strcasecmp_l, %gnu_indirect_function");
+
+weak_alias (__strcasecmp_l, strcasecmp_l)
+#endif
diff --git a/sysdeps/i386/multiarch/strcmp-i386.c b/sysdeps/i386/multiarch/strcmp-i386.c
new file mode 100644
index 0000000000..f5931bf5aa
--- /dev/null
+++ b/sysdeps/i386/multiarch/strcmp-i386.c
@@ -0,0 +1,10 @@
+#include <init-arch.h>
+#if !SUPPORT_I686
+# ifdef SHARED
+#  define STRCMP __strcmp_i386
+#  undef libc_hidden_builtin_def
+#   define libc_hidden_builtin_def(name)  \
+    __hidden_ver1 (__strcmp_i386, __GI_strcmp, __strcmp_i386);
+# endif
+# include "string/strcmp.c"
+#endif
diff --git a/sysdeps/i386/multiarch/strcmp-i686.S b/sysdeps/i386/multiarch/strcmp-i686.S
new file mode 100644
index 0000000000..ce07410733
--- /dev/null
+++ b/sysdeps/i386/multiarch/strcmp-i686.S
@@ -0,0 +1,16 @@
+#include <init-arch.h>
+#ifdef SHARED
+# define strcmp __strcmp_i686
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(name)
+#endif
+
+#if SUPPORT_I686 || defined SHARED
+#include <sysdeps/i386/i686/strcmp.S>
+#endif
+
+#if defined SHARED && SUPPORT_I686
+	.globl __GI_strcmp
+	.hidden __GI_strcmp
+	__GI_strcmp = __strcmp_i686
+#endif
diff --git a/sysdeps/i386/i686/multiarch/strcmp-sse4.S b/sysdeps/i386/multiarch/strcmp-sse4.S
index 38c2317c26..38c2317c26 100644
--- a/sysdeps/i386/i686/multiarch/strcmp-sse4.S
+++ b/sysdeps/i386/multiarch/strcmp-sse4.S
diff --git a/sysdeps/i386/i686/multiarch/strcmp-ssse3.S b/sysdeps/i386/multiarch/strcmp-ssse3.S
index fb21288c7d..fb21288c7d 100644
--- a/sysdeps/i386/i686/multiarch/strcmp-ssse3.S
+++ b/sysdeps/i386/multiarch/strcmp-ssse3.S
diff --git a/sysdeps/i386/multiarch/strcmp.c b/sysdeps/i386/multiarch/strcmp.c
new file mode 100644
index 0000000000..58049e8051
--- /dev/null
+++ b/sysdeps/i386/multiarch/strcmp.c
@@ -0,0 +1,58 @@
+/* Multiple versions of strcmp.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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 multiple versions only for the definition in libc.  Don't
+   define multiple versions for strcmp in static library since we
+   need strcmp before the initialization happened.  */
+#if defined  SHARED && IS_IN (libc)
+# define _HAVE_STRING_ARCH_strcmp
+/* Redefine strcmp so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strcmp
+# define strcmp __redirect_strcmp
+# include <string.h>
+# undef strcmp
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_strcmp) __strcmp_i386 attribute_hidden;
+extern __typeof (__redirect_strcmp) __strcmp_i686 attribute_hidden;
+extern __typeof (__redirect_strcmp) __strcmp_ssse3 attribute_hidden;
+extern __typeof (__redirect_strcmp) __strcmp_sse4_2 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_strcmp) strcmp;
+extern void *strcmp_ifunc (void) __asm__ ("strcmp");
+
+void *
+strcmp_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSE4_2))
+    return __strcmp_sse4_2;
+  else if (HAS_CPU_FEATURE (SSSE3))
+    return __strcmp_ssse3;
+
+  if (HAS_I686)
+    return __strcmp_i686;
+  else
+    return __strcmp_i386;
+}
+__asm__ (".type strcmp, %gnu_indirect_function");
+#endif
diff --git a/sysdeps/i386/i686/multiarch/strncase-c.c b/sysdeps/i386/multiarch/strncase-i386.c
index 76581eb62b..7053e553cf 100644
--- a/sysdeps/i386/i686/multiarch/strncase-c.c
+++ b/sysdeps/i386/multiarch/strncase-i386.c
@@ -5,4 +5,4 @@ extern __typeof (strncasecmp) __strncasecmp_nonascii;
 #define __strncasecmp __strncasecmp_nonascii
 #include <string/strncase.c>
 
-strong_alias (__strncasecmp_nonascii, __strncasecmp_ia32)
+strong_alias (__strncasecmp_nonascii, __strncasecmp_i386)
diff --git a/sysdeps/i386/multiarch/strncase.c b/sysdeps/i386/multiarch/strncase.c
new file mode 100644
index 0000000000..9e5dcabfca
--- /dev/null
+++ b/sysdeps/i386/multiarch/strncase.c
@@ -0,0 +1,53 @@
+/* Multiple versions of strncasecmp.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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 multiple versions only for the definition in lib.  */
+#if IS_IN (libc)
+/* Redefine strncasecmp so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strncasecmp
+# define strncasecmp __redirect_strncasecmp
+# include <string.h>
+# undef strncasecmp
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_strncasecmp) __strncasecmp_i386 attribute_hidden;
+extern __typeof (__redirect_strncasecmp) __strncasecmp_ssse3 attribute_hidden;
+extern __typeof (__redirect_strncasecmp) __strncasecmp_sse4_2 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_strncasecmp) __strncasecmp;
+extern void *strncasecmp_ifunc (void) __asm__ ("__strncasecmp");
+
+void *
+strncasecmp_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSE4_2))
+    return __strncasecmp_sse4_2;
+  else if (HAS_CPU_FEATURE (SSSE3))
+    return __strncasecmp_ssse3;
+
+  return __strncasecmp_i386;
+}
+__asm__ (".type __strncasecmp, %gnu_indirect_function");
+
+weak_alias (__strncasecmp, strncasecmp)
+#endif
diff --git a/sysdeps/i386/i686/multiarch/strncase_l-c.c b/sysdeps/i386/multiarch/strncase_l-i386.c
index 7e601af271..efee0bf991 100644
--- a/sysdeps/i386/i686/multiarch/strncase_l-c.c
+++ b/sysdeps/i386/multiarch/strncase_l-i386.c
@@ -6,7 +6,7 @@ extern __typeof (strncasecmp_l) __strncasecmp_l_nonascii;
 #define USE_IN_EXTENDED_LOCALE_MODEL    1
 #include <string/strncase.c>
 
-strong_alias (__strncasecmp_l_nonascii, __strncasecmp_l_ia32)
+strong_alias (__strncasecmp_l_nonascii, __strncasecmp_l_i386)
 
 /* The needs of strcasecmp in libc are minimal, no need to go through
    the IFUNC.  */
diff --git a/sysdeps/i386/i686/multiarch/strncase_l-sse4.S b/sysdeps/i386/multiarch/strncase_l-sse4.S
index 557210832e..557210832e 100644
--- a/sysdeps/i386/i686/multiarch/strncase_l-sse4.S
+++ b/sysdeps/i386/multiarch/strncase_l-sse4.S
diff --git a/sysdeps/i386/i686/multiarch/strncase_l-ssse3.S b/sysdeps/i386/multiarch/strncase_l-ssse3.S
index d438a1ae35..d438a1ae35 100644
--- a/sysdeps/i386/i686/multiarch/strncase_l-ssse3.S
+++ b/sysdeps/i386/multiarch/strncase_l-ssse3.S
diff --git a/sysdeps/i386/multiarch/strncase_l.c b/sysdeps/i386/multiarch/strncase_l.c
new file mode 100644
index 0000000000..279b3ce007
--- /dev/null
+++ b/sysdeps/i386/multiarch/strncase_l.c
@@ -0,0 +1,53 @@
+/* Multiple versions of strncasecmp_l.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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 multiple versions only for the definition in lib.  */
+#if IS_IN (libc)
+/* Redefine strncasecmp_l so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strncasecmp_l
+# define strncasecmp_l __redirect_strncasecmp_l
+# include <string.h>
+# undef strncasecmp_l
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_strncasecmp_l) __strncasecmp_l_i386 attribute_hidden;
+extern __typeof (__redirect_strncasecmp_l) __strncasecmp_l_ssse3 attribute_hidden;
+extern __typeof (__redirect_strncasecmp_l) __strncasecmp_l_sse4_2 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_strncasecmp_l) __strncasecmp_l;
+extern void *strncasecmp_l_ifunc (void) __asm__ ("__strncasecmp_l");
+
+void *
+strncasecmp_l_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSE4_2))
+    return __strncasecmp_l_sse4_2;
+  else if (HAS_CPU_FEATURE (SSSE3))
+    return __strncasecmp_l_ssse3;
+
+  return __strncasecmp_l_i386;
+}
+__asm__ (".type __strncasecmp_l, %gnu_indirect_function");
+
+weak_alias (__strncasecmp_l, strncasecmp_l)
+#endif
diff --git a/sysdeps/i386/i686/multiarch/strncmp-c.c b/sysdeps/i386/multiarch/strncmp-i386.c
index cc059da494..8e4138894f 100644
--- a/sysdeps/i386/i686/multiarch/strncmp-c.c
+++ b/sysdeps/i386/multiarch/strncmp-i386.c
@@ -1,8 +1,8 @@
 #ifdef SHARED
-# define STRNCMP __strncmp_ia32
+# define STRNCMP __strncmp_i386
 # undef libc_hidden_builtin_def
 # define libc_hidden_builtin_def(name)  \
-    __hidden_ver1 (__strncmp_ia32, __GI_strncmp, __strncmp_ia32);
+    __hidden_ver1 (__strncmp_i386, __GI_strncmp, __strncmp_i386);
 #endif
 
 #include "string/strncmp.c"
diff --git a/sysdeps/i386/i686/multiarch/strncmp-sse4.S b/sysdeps/i386/multiarch/strncmp-sse4.S
index cf14dfaf6c..cf14dfaf6c 100644
--- a/sysdeps/i386/i686/multiarch/strncmp-sse4.S
+++ b/sysdeps/i386/multiarch/strncmp-sse4.S
diff --git a/sysdeps/i386/i686/multiarch/strncmp-ssse3.S b/sysdeps/i386/multiarch/strncmp-ssse3.S
index 536c8685f2..536c8685f2 100644
--- a/sysdeps/i386/i686/multiarch/strncmp-ssse3.S
+++ b/sysdeps/i386/multiarch/strncmp-ssse3.S
diff --git a/sysdeps/i386/multiarch/strncmp.c b/sysdeps/i386/multiarch/strncmp.c
new file mode 100644
index 0000000000..180f87062e
--- /dev/null
+++ b/sysdeps/i386/multiarch/strncmp.c
@@ -0,0 +1,54 @@
+/* Multiple versions of strncmp.
+   All versions must be listed in ifunc-impl-list.c.
+   Copyright (C) 2015 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 multiple versions only for the definition in libc.  Don't
+   define multiple versions for strncmp in static library since we
+   need strncmp before the initialization happened.  */
+#if defined  SHARED && IS_IN (libc)
+# define _HAVE_STRING_ARCH_strncmp
+/* Redefine strncmp so that the compiler won't complain about the type
+   mismatch with the IFUNC selector in strong_alias, below.  */
+# undef strncmp
+# define strncmp __redirect_strncmp
+# include <string.h>
+# undef strncmp
+
+# include <init-arch.h>
+
+extern __typeof (__redirect_strncmp) __strncmp_i386 attribute_hidden;
+extern __typeof (__redirect_strncmp) __strncmp_ssse3 attribute_hidden;
+extern __typeof (__redirect_strncmp) __strncmp_sse4_2 attribute_hidden;
+
+/* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle
+   ifunc symbol properly.  */
+extern __typeof (__redirect_strncmp) strncmp;
+extern void *strncmp_ifunc (void) __asm__ ("strncmp");
+
+void *
+strncmp_ifunc (void)
+{
+  if (HAS_CPU_FEATURE (SSE4_2))
+    return __strncmp_sse4_2;
+  else if (HAS_CPU_FEATURE (SSSE3))
+    return __strncmp_ssse3;
+
+  return __strncmp_i386;
+}
+__asm__ (".type strncmp, %gnu_indirect_function");
+#endif