x86: Rename generic functions with unique postfix for clarity
authorNoah Goldstein <goldstein.w.n@gmail.com>
Thu, 16 Jun 2022 22:07:12 +0000 (15:07 -0700)
committerNoah Goldstein <goldstein.w.n@gmail.com>
Fri, 17 Jun 2022 03:17:45 +0000 (20:17 -0700)
No functions are changed. It just renames generic implementations from
'{func}_sse2' to '{func}_generic'. This is just because the postfix
"_sse2" was overloaded and was used for files that had hand-optimized
sse2 assembly implementations and files that just redirected back
to the generic implementation.

Full xcheck passed on x86_64.

36 files changed:
sysdeps/x86_64/multiarch/Makefile
sysdeps/x86_64/multiarch/ifunc-avx2.h
sysdeps/x86_64/multiarch/ifunc-impl-list.c
sysdeps/x86_64/multiarch/ifunc-sse4_2.h
sysdeps/x86_64/multiarch/ifunc-strcpy.h
sysdeps/x86_64/multiarch/ifunc-wcslen.h
sysdeps/x86_64/multiarch/stpncpy-c.c [deleted file]
sysdeps/x86_64/multiarch/stpncpy-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/stpncpy.c
sysdeps/x86_64/multiarch/strcspn-c.c [deleted file]
sysdeps/x86_64/multiarch/strcspn-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/strcspn-sse2.c [deleted file]
sysdeps/x86_64/multiarch/strcspn-sse4.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/strncat-c.c [deleted file]
sysdeps/x86_64/multiarch/strncat-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/strncat.c
sysdeps/x86_64/multiarch/strncpy-c.c [deleted file]
sysdeps/x86_64/multiarch/strncpy-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/strncpy.c
sysdeps/x86_64/multiarch/strpbrk-c.c [deleted file]
sysdeps/x86_64/multiarch/strpbrk-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/strpbrk-sse2.c [deleted file]
sysdeps/x86_64/multiarch/strpbrk-sse4.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/strspn-c.c [deleted file]
sysdeps/x86_64/multiarch/strspn-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/strspn-sse2.c [deleted file]
sysdeps/x86_64/multiarch/strspn-sse4.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/wcscpy-c.c [deleted file]
sysdeps/x86_64/multiarch/wcscpy-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/wcscpy.c
sysdeps/x86_64/multiarch/wcsncmp-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/wcsncmp-sse2.c [deleted file]
sysdeps/x86_64/multiarch/wcsncmp.c
sysdeps/x86_64/multiarch/wcsnlen-c.c [deleted file]
sysdeps/x86_64/multiarch/wcsnlen-generic.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/wcsnlen.c

index 3d153cac354b954d5696f1cf4c97053eb39f95d7..666ee4d5d6326d4cd5246c99ff165b3f2448c5ac 100644 (file)
@@ -43,7 +43,7 @@ sysdep_routines += \
   stpcpy-sse2-unaligned \
   stpncpy-avx2 \
   stpncpy-avx2-rtm \
-  stpncpy-c \
+  stpncpy-generic \
   stpncpy-evex \
   stpncpy-sse2-unaligned \
   strcasecmp_l-avx2 \
@@ -76,8 +76,8 @@ sysdep_routines += \
   strcpy-evex \
   strcpy-sse2 \
   strcpy-sse2-unaligned \
-  strcspn-c \
-  strcspn-sse2 \
+  strcspn-generic \
+  strcspn-sse4 \
   strlen-avx2 \
   strlen-avx2-rtm \
   strlen-evex \
@@ -90,7 +90,7 @@ sysdep_routines += \
   strncase_l-sse4_2 \
   strncat-avx2 \
   strncat-avx2-rtm \
-  strncat-c \
+  strncat-generic \
   strncat-evex \
   strncat-sse2-unaligned \
   strncmp-avx2 \
@@ -100,7 +100,7 @@ sysdep_routines += \
   strncmp-sse4_2 \
   strncpy-avx2 \
   strncpy-avx2-rtm \
-  strncpy-c \
+  strncpy-generic \
   strncpy-evex \
   strncpy-sse2-unaligned \
   strnlen-avx2 \
@@ -108,22 +108,23 @@ sysdep_routines += \
   strnlen-evex \
   strnlen-evex512 \
   strnlen-sse2 \
-  strpbrk-c \
-  strpbrk-sse2 \
+  strpbrk-generic \
+  strpbrk-sse4 \
   strrchr-avx2 \
   strrchr-avx2-rtm \
   strrchr-evex \
   strrchr-sse2 \
-  strspn-c \
-  strspn-sse2 \
+  strspn-generic \
+  strspn-sse4 \
   strstr-avx512 \
   strstr-sse2-unaligned \
   varshift \
 # sysdep_routines
-CFLAGS-varshift.c += -msse4
-CFLAGS-strcspn-c.c += -msse4
-CFLAGS-strpbrk-c.c += -msse4
-CFLAGS-strspn-c.c += -msse4
+
+CFLAGS-strcspn-sse4.c += -msse4
+CFLAGS-strpbrk-sse4.c += -msse4
+CFLAGS-strspn-sse4.c += -msse4
+
 CFLAGS-strstr-avx512.c += -mavx512f -mavx512vl -mavx512dq -mavx512bw -mbmi -mbmi2 -O3
 endif
 
@@ -137,7 +138,7 @@ sysdep_routines += \
   wcscmp-avx2-rtm \
   wcscmp-evex \
   wcscmp-sse2 \
-  wcscpy-c \
+  wcscpy-generic \
   wcscpy-ssse3 \
   wcslen-avx2 \
   wcslen-avx2-rtm \
@@ -147,11 +148,11 @@ sysdep_routines += \
   wcslen-sse4_1 \
   wcsncmp-avx2 \
   wcsncmp-avx2-rtm \
+  wcsncmp-generic \
   wcsncmp-evex \
-  wcsncmp-sse2 \
   wcsnlen-avx2 \
   wcsnlen-avx2-rtm \
-  wcsnlen-c \
+  wcsnlen-generic \
   wcsnlen-evex \
   wcsnlen-evex512 \
   wcsnlen-sse4_1 \
index 4289df29ecbbb7211f6b48d8d113f24bb1394b80..1d9cdfcfec7fcee8dfaa105071d9eec1eee10a94 100644 (file)
 
 #include <init-arch.h>
 
-extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
+#ifndef GENERIC
+# define GENERIC sse2
+#endif
+
+extern __typeof (REDIRECT_NAME) OPTIMIZE (GENERIC) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2_rtm) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (evex) attribute_hidden;
@@ -44,5 +48,5 @@ IFUNC_SELECTOR (void)
        return OPTIMIZE (avx2);
     }
 
-  return OPTIMIZE (sse2);
+  return OPTIMIZE (GENERIC);
 }
index dc595752e0dc7665012b314b76e3f4b4c92afe5f..883362f63d8f1cfe55a576cd6ece01a17b5b3071 100644 (file)
@@ -367,7 +367,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                              __stpncpy_evex)
              IFUNC_IMPL_ADD (array, i, stpncpy, 1,
                              __stpncpy_sse2_unaligned)
-             IFUNC_IMPL_ADD (array, i, stpncpy, 1, __stpncpy_sse2))
+             IFUNC_IMPL_ADD (array, i, stpncpy, 1, __stpncpy_generic))
 
   /* Support sysdeps/x86_64/multiarch/stpcpy.c.  */
   IFUNC_IMPL (i, name, stpcpy,
@@ -526,7 +526,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
   IFUNC_IMPL (i, name, strcspn,
              IFUNC_IMPL_ADD (array, i, strcspn, CPU_FEATURE_USABLE (SSE4_2),
                              __strcspn_sse42)
-             IFUNC_IMPL_ADD (array, i, strcspn, 1, __strcspn_sse2))
+             IFUNC_IMPL_ADD (array, i, strcspn, 1, __strcspn_generic))
 
   /* Support sysdeps/x86_64/multiarch/strncase_l.c.  */
   IFUNC_IMPL (i, name, strncasecmp,
@@ -580,7 +580,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                              __strncat_evex)
              IFUNC_IMPL_ADD (array, i, strncat, 1,
                              __strncat_sse2_unaligned)
-             IFUNC_IMPL_ADD (array, i, strncat, 1, __strncat_sse2))
+             IFUNC_IMPL_ADD (array, i, strncat, 1, __strncat_generic))
 
   /* Support sysdeps/x86_64/multiarch/strncpy.c.  */
   IFUNC_IMPL (i, name, strncpy,
@@ -596,20 +596,20 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                              __strncpy_evex)
              IFUNC_IMPL_ADD (array, i, strncpy, 1,
                              __strncpy_sse2_unaligned)
-             IFUNC_IMPL_ADD (array, i, strncpy, 1, __strncpy_sse2))
+             IFUNC_IMPL_ADD (array, i, strncpy, 1, __strncpy_generic))
 
   /* Support sysdeps/x86_64/multiarch/strpbrk.c.  */
   IFUNC_IMPL (i, name, strpbrk,
              IFUNC_IMPL_ADD (array, i, strpbrk, CPU_FEATURE_USABLE (SSE4_2),
                              __strpbrk_sse42)
-             IFUNC_IMPL_ADD (array, i, strpbrk, 1, __strpbrk_sse2))
+             IFUNC_IMPL_ADD (array, i, strpbrk, 1, __strpbrk_generic))
 
 
   /* Support sysdeps/x86_64/multiarch/strspn.c.  */
   IFUNC_IMPL (i, name, strspn,
              IFUNC_IMPL_ADD (array, i, strspn, CPU_FEATURE_USABLE (SSE4_2),
                              __strspn_sse42)
-             IFUNC_IMPL_ADD (array, i, strspn, 1, __strspn_sse2))
+             IFUNC_IMPL_ADD (array, i, strspn, 1, __strspn_generic))
 
   /* Support sysdeps/x86_64/multiarch/strstr.c.  */
   IFUNC_IMPL (i, name, strstr,
@@ -686,13 +686,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                               && CPU_FEATURE_USABLE (AVX512BW)
                               && CPU_FEATURE_USABLE (BMI2)),
                              __wcsncmp_evex)
-             IFUNC_IMPL_ADD (array, i, wcsncmp, 1, __wcsncmp_sse2))
+             IFUNC_IMPL_ADD (array, i, wcsncmp, 1, __wcsncmp_generic))
 
   /* Support sysdeps/x86_64/multiarch/wcscpy.c.  */
   IFUNC_IMPL (i, name, wcscpy,
              IFUNC_IMPL_ADD (array, i, wcscpy, CPU_FEATURE_USABLE (SSSE3),
                              __wcscpy_ssse3)
-             IFUNC_IMPL_ADD (array, i, wcscpy, 1, __wcscpy_sse2))
+             IFUNC_IMPL_ADD (array, i, wcscpy, 1, __wcscpy_generic))
 
   /* Support sysdeps/x86_64/multiarch/wcslen.c.  */
   IFUNC_IMPL (i, name, wcslen,
@@ -744,7 +744,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
              IFUNC_IMPL_ADD (array, i, wcsnlen,
                              CPU_FEATURE_USABLE (SSE4_1),
                              __wcsnlen_sse4_1)
-             IFUNC_IMPL_ADD (array, i, wcsnlen, 1, __wcsnlen_sse2))
+             IFUNC_IMPL_ADD (array, i, wcsnlen, 1, __wcsnlen_generic))
 
   /* Support sysdeps/x86_64/multiarch/wmemchr.c.  */
   IFUNC_IMPL (i, name, wmemchr,
index b555ff2fac2b04fda83c1c03d6519e05bf968131..ee36525bcf7f5b19c03b27472934fd33fca8f213 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <init-arch.h>
 
-extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (generic) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse42) attribute_hidden;
 
 static inline void *
@@ -30,5 +30,5 @@ IFUNC_SELECTOR (void)
   if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_2))
     return OPTIMIZE (sse42);
 
-  return OPTIMIZE (sse2);
+  return OPTIMIZE (generic);
 }
index a15afa44e98ad93f9a873276c7e54429ca1ddcb9..80529458d161f7dde3414f9b75e9417ba67c43a2 100644 (file)
 
 #include <init-arch.h>
 
-extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
+#ifndef GENERIC
+# define GENERIC sse2
+#endif
+
+extern __typeof (REDIRECT_NAME) OPTIMIZE (GENERIC) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2_unaligned)
   attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2) attribute_hidden;
@@ -49,5 +53,5 @@ IFUNC_SELECTOR (void)
   if (CPU_FEATURES_ARCH_P (cpu_features, Fast_Unaligned_Load))
     return OPTIMIZE (sse2_unaligned);
 
-  return OPTIMIZE (sse2);
+  return OPTIMIZE (GENERIC);
 }
index 2b29e7608a030b7a654741d7e0e918d419c1099f..88c1c502afd98ddc5e8e5841f564d30cb2668c67 100644 (file)
 
 #include <init-arch.h>
 
-extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
+#ifndef GENERIC
+# define GENERIC sse2
+#endif
+
+extern __typeof (REDIRECT_NAME) OPTIMIZE (GENERIC) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (sse4_1) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2_rtm) attribute_hidden;
@@ -48,5 +52,5 @@ IFUNC_SELECTOR (void)
   if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_1))
     return OPTIMIZE (sse4_1);
 
-  return OPTIMIZE (sse2);
+  return OPTIMIZE (GENERIC);
 }
diff --git a/sysdeps/x86_64/multiarch/stpncpy-c.c b/sysdeps/x86_64/multiarch/stpncpy-c.c
deleted file mode 100644 (file)
index b016e48..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#define STPNCPY __stpncpy_sse2
-#undef weak_alias
-#define weak_alias(ignored1, ignored2)
-#undef libc_hidden_def
-#define libc_hidden_def(stpncpy)
-
-#include <string/stpncpy.c>
diff --git a/sysdeps/x86_64/multiarch/stpncpy-generic.c b/sysdeps/x86_64/multiarch/stpncpy-generic.c
new file mode 100644 (file)
index 0000000..8782684
--- /dev/null
@@ -0,0 +1,26 @@
+/* stpncpy.
+   Copyright (C) 2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+
+#define STPNCPY __stpncpy_generic
+#undef weak_alias
+#define weak_alias(ignored1, ignored2)
+#undef libc_hidden_def
+#define libc_hidden_def(stpncpy)
+
+#include <string/stpncpy.c>
index 82fa53957d4250bf992351fdc4c3d655528d93f9..879bc83f0bceca13106fd6abc486d7c03686a820 100644 (file)
@@ -25,6 +25,7 @@
 # undef stpncpy
 # undef __stpncpy
 
+# define GENERIC generic
 # define SYMBOL_NAME stpncpy
 # include "ifunc-strcpy.h"
 
diff --git a/sysdeps/x86_64/multiarch/strcspn-c.c b/sysdeps/x86_64/multiarch/strcspn-c.c
deleted file mode 100644 (file)
index c312fab..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/* strcspn with SSE4.2 intrinsics
-   Copyright (C) 2009-2022 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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <nmmintrin.h>
-#include <string.h>
-#include "varshift.h"
-
-/* We use 0x2:
-       _SIDD_SBYTE_OPS
-       | _SIDD_CMP_EQUAL_ANY
-       | _SIDD_POSITIVE_POLARITY
-       | _SIDD_LEAST_SIGNIFICANT
-   on pcmpistri to compare xmm/mem128
-
-   0 1 2 3 4 5 6 7 8 9 A B C D E F
-   X X X X X X X X X X X X X X X X
-
-   against xmm
-
-   0 1 2 3 4 5 6 7 8 9 A B C D E F
-   A A A A A A A A A A A A A A A A
-
-   to find out if the first 16byte data element has any byte A and
-   the offset of the first byte.  There are 3 cases:
-
-   1. The first 16byte data element has the byte A at the offset X.
-   2. The first 16byte data element has EOS and doesn't have the byte A.
-   3. The first 16byte data element is valid and doesn't have the byte A.
-
-   Here is the table of ECX, CFlag, ZFlag and SFlag for 2 cases:
-
-    1           X        1      0/1      0
-    2          16        0       1       0
-    3          16        0       0       0
-
-   We exit from the loop for cases 1 and 2 with jbe which branches
-   when either CFlag or ZFlag is 1.  If CFlag == 1, ECX has the offset
-   X for case 1.  */
-
-#ifndef STRCSPN_SSE2
-# define STRCSPN_SSE2 __strcspn_sse2
-# define STRCSPN_SSE42 __strcspn_sse42
-#endif
-
-#ifdef USE_AS_STRPBRK
-# define RETURN(val1, val2) return val1
-#else
-# define RETURN(val1, val2) return val2
-#endif
-
-extern
-#ifdef USE_AS_STRPBRK
-char *
-#else
-size_t
-#endif
-STRCSPN_SSE2 (const char *, const char *) attribute_hidden;
-
-
-#ifdef USE_AS_STRPBRK
-char *
-#else
-size_t
-#endif
-__attribute__ ((section (".text.sse4.2")))
-STRCSPN_SSE42 (const char *s, const char *a)
-{
-  if (*a == 0)
-    RETURN (NULL, strlen (s));
-
-  const char *aligned;
-  __m128i mask, maskz, zero;
-  unsigned int maskz_bits;
-  unsigned int offset = (unsigned int) ((size_t) a & 15);
-  zero = _mm_set1_epi8 (0);
-  if (offset != 0)
-    {
-      /* Load masks.  */
-      aligned = (const char *) ((size_t) a & -16L);
-      __m128i mask0 = _mm_load_si128 ((__m128i *) aligned);
-      maskz = _mm_cmpeq_epi8 (mask0, zero);
-
-      /* Find where the NULL terminator is.  */
-      maskz_bits = _mm_movemask_epi8 (maskz) >> offset;
-      if (maskz_bits != 0)
-        {
-          mask = __m128i_shift_right (mask0, offset);
-          offset = (unsigned int) ((size_t) s & 15);
-          if (offset)
-            goto start_unaligned;
-
-          aligned = s;
-          goto start_loop;
-        }
-    }
-
-  /* A is aligned.  */
-  mask = _mm_loadu_si128 ((__m128i *) a);
-  /* Find where the NULL terminator is.  */
-  maskz = _mm_cmpeq_epi8 (mask, zero);
-  maskz_bits = _mm_movemask_epi8 (maskz);
-  if (maskz_bits == 0)
-    {
-      /* There is no NULL terminator.  Don't use SSE4.2 if the length
-         of A > 16.  */
-      if (a[16] != 0)
-        return STRCSPN_SSE2 (s, a);
-    }
-
-  aligned = s;
-  offset = (unsigned int) ((size_t) s & 15);
-  if (offset != 0)
-    {
-    start_unaligned:
-      /* Check partial string.  */
-      aligned = (const char *) ((size_t) s & -16L);
-      __m128i value = _mm_load_si128 ((__m128i *) aligned);
-
-      value = __m128i_shift_right (value, offset);
-
-      unsigned int length = _mm_cmpistri (mask, value, 0x2);
-      /* No need to check ZFlag since ZFlag is always 1.  */
-      unsigned int cflag = _mm_cmpistrc (mask, value, 0x2);
-      if (cflag)
-       RETURN ((char *) (s + length), length);
-      /* Find where the NULL terminator is.  */
-      unsigned int index = _mm_cmpistri (value, value, 0x3a);
-      if (index < 16 - offset)
-       RETURN (NULL, index);
-      aligned += 16;
-    }
-
-start_loop:
-  while (1)
-    {
-      __m128i value = _mm_load_si128 ((__m128i *) aligned);
-      unsigned int index = _mm_cmpistri (mask, value, 0x2);
-      unsigned int cflag = _mm_cmpistrc (mask, value, 0x2);
-      unsigned int zflag = _mm_cmpistrz (mask, value, 0x2);
-      if (cflag)
-       RETURN ((char *) (aligned + index), (size_t) (aligned + index - s));
-      if (zflag)
-       RETURN (NULL,
-               /* Find where the NULL terminator is.  */
-               (size_t) (aligned + _mm_cmpistri (value, value, 0x3a) - s));
-      aligned += 16;
-    }
-}
diff --git a/sysdeps/x86_64/multiarch/strcspn-generic.c b/sysdeps/x86_64/multiarch/strcspn-generic.c
new file mode 100644 (file)
index 0000000..423de2e
--- /dev/null
@@ -0,0 +1,28 @@
+/* strcspn.
+   Copyright (C) 2017-2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+#if IS_IN (libc)
+
+# include <sysdep.h>
+# define STRCSPN __strcspn_generic
+
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(STRCSPN)
+#endif
+
+#include <string/strcspn.c>
diff --git a/sysdeps/x86_64/multiarch/strcspn-sse2.c b/sysdeps/x86_64/multiarch/strcspn-sse2.c
deleted file mode 100644 (file)
index 3a04bb3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* strcspn.
-   Copyright (C) 2017-2022 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
-   <https://www.gnu.org/licenses/>.  */
-
-#if IS_IN (libc)
-
-# include <sysdep.h>
-# define STRCSPN __strcspn_sse2
-
-# undef libc_hidden_builtin_def
-# define libc_hidden_builtin_def(STRCSPN)
-#endif
-
-#include <string/strcspn.c>
diff --git a/sysdeps/x86_64/multiarch/strcspn-sse4.c b/sysdeps/x86_64/multiarch/strcspn-sse4.c
new file mode 100644 (file)
index 0000000..59f64f9
--- /dev/null
@@ -0,0 +1,163 @@
+/* strcspn with SSE4.2 intrinsics
+   Copyright (C) 2009-2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <nmmintrin.h>
+#include <string.h>
+#include "varshift.h"
+
+/* We use 0x2:
+       _SIDD_SBYTE_OPS
+       | _SIDD_CMP_EQUAL_ANY
+       | _SIDD_POSITIVE_POLARITY
+       | _SIDD_LEAST_SIGNIFICANT
+   on pcmpistri to compare xmm/mem128
+
+   0 1 2 3 4 5 6 7 8 9 A B C D E F
+   X X X X X X X X X X X X X X X X
+
+   against xmm
+
+   0 1 2 3 4 5 6 7 8 9 A B C D E F
+   A A A A A A A A A A A A A A A A
+
+   to find out if the first 16byte data element has any byte A and
+   the offset of the first byte.  There are 3 cases:
+
+   1. The first 16byte data element has the byte A at the offset X.
+   2. The first 16byte data element has EOS and doesn't have the byte A.
+   3. The first 16byte data element is valid and doesn't have the byte A.
+
+   Here is the table of ECX, CFlag, ZFlag and SFlag for 2 cases:
+
+    1           X        1      0/1      0
+    2          16        0       1       0
+    3          16        0       0       0
+
+   We exit from the loop for cases 1 and 2 with jbe which branches
+   when either CFlag or ZFlag is 1.  If CFlag == 1, ECX has the offset
+   X for case 1.  */
+
+#ifndef STRCSPN_GENERIC
+# define STRCSPN_GENERIC __strcspn_generic
+# define STRCSPN_SSE42 __strcspn_sse42
+#endif
+
+#ifdef USE_AS_STRPBRK
+# define RETURN(val1, val2) return val1
+#else
+# define RETURN(val1, val2) return val2
+#endif
+
+extern
+#ifdef USE_AS_STRPBRK
+char *
+#else
+size_t
+#endif
+STRCSPN_GENERIC (const char *, const char *) attribute_hidden;
+
+
+#ifdef USE_AS_STRPBRK
+char *
+#else
+size_t
+#endif
+__attribute__ ((section (".text.sse4.2")))
+STRCSPN_SSE42 (const char *s, const char *a)
+{
+  if (*a == 0)
+    RETURN (NULL, strlen (s));
+
+  const char *aligned;
+  __m128i mask, maskz, zero;
+  unsigned int maskz_bits;
+  unsigned int offset = (unsigned int) ((size_t) a & 15);
+  zero = _mm_set1_epi8 (0);
+  if (offset != 0)
+    {
+      /* Load masks.  */
+      aligned = (const char *) ((size_t) a & -16L);
+      __m128i mask0 = _mm_load_si128 ((__m128i *) aligned);
+      maskz = _mm_cmpeq_epi8 (mask0, zero);
+
+      /* Find where the NULL terminator is.  */
+      maskz_bits = _mm_movemask_epi8 (maskz) >> offset;
+      if (maskz_bits != 0)
+        {
+          mask = __m128i_shift_right (mask0, offset);
+          offset = (unsigned int) ((size_t) s & 15);
+          if (offset)
+            goto start_unaligned;
+
+          aligned = s;
+          goto start_loop;
+        }
+    }
+
+  /* A is aligned.  */
+  mask = _mm_loadu_si128 ((__m128i *) a);
+  /* Find where the NULL terminator is.  */
+  maskz = _mm_cmpeq_epi8 (mask, zero);
+  maskz_bits = _mm_movemask_epi8 (maskz);
+  if (maskz_bits == 0)
+    {
+      /* There is no NULL terminator.  Don't use SSE4.2 if the length
+         of A > 16.  */
+      if (a[16] != 0)
+        return STRCSPN_GENERIC (s, a);
+    }
+
+  aligned = s;
+  offset = (unsigned int) ((size_t) s & 15);
+  if (offset != 0)
+    {
+    start_unaligned:
+      /* Check partial string.  */
+      aligned = (const char *) ((size_t) s & -16L);
+      __m128i value = _mm_load_si128 ((__m128i *) aligned);
+
+      value = __m128i_shift_right (value, offset);
+
+      unsigned int length = _mm_cmpistri (mask, value, 0x2);
+      /* No need to check ZFlag since ZFlag is always 1.  */
+      unsigned int cflag = _mm_cmpistrc (mask, value, 0x2);
+      if (cflag)
+       RETURN ((char *) (s + length), length);
+      /* Find where the NULL terminator is.  */
+      unsigned int index = _mm_cmpistri (value, value, 0x3a);
+      if (index < 16 - offset)
+       RETURN (NULL, index);
+      aligned += 16;
+    }
+
+start_loop:
+  while (1)
+    {
+      __m128i value = _mm_load_si128 ((__m128i *) aligned);
+      unsigned int index = _mm_cmpistri (mask, value, 0x2);
+      unsigned int cflag = _mm_cmpistrc (mask, value, 0x2);
+      unsigned int zflag = _mm_cmpistrz (mask, value, 0x2);
+      if (cflag)
+       RETURN ((char *) (aligned + index), (size_t) (aligned + index - s));
+      if (zflag)
+       RETURN (NULL,
+               /* Find where the NULL terminator is.  */
+               (size_t) (aligned + _mm_cmpistri (value, value, 0x3a) - s));
+      aligned += 16;
+    }
+}
diff --git a/sysdeps/x86_64/multiarch/strncat-c.c b/sysdeps/x86_64/multiarch/strncat-c.c
deleted file mode 100644 (file)
index 93a7fab..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#define STRNCAT __strncat_sse2
-#include <string/strncat.c>
diff --git a/sysdeps/x86_64/multiarch/strncat-generic.c b/sysdeps/x86_64/multiarch/strncat-generic.c
new file mode 100644 (file)
index 0000000..0090669
--- /dev/null
@@ -0,0 +1,21 @@
+/* strncat.
+   Copyright (C) 2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+
+#define STRNCAT __strncat_generic
+#include <string/strncat.c>
index b649343a972a75ecb2cb9184d75985d9c26a633c..50fba8a41f92f13c30e05392176898d13fe918e2 100644 (file)
@@ -24,6 +24,7 @@
 # undef strncat
 
 # define SYMBOL_NAME strncat
+# define GENERIC generic
 # include "ifunc-strcpy.h"
 
 libc_ifunc_redirected (__redirect_strncat, strncat, IFUNC_SELECTOR ());
diff --git a/sysdeps/x86_64/multiarch/strncpy-c.c b/sysdeps/x86_64/multiarch/strncpy-c.c
deleted file mode 100644 (file)
index 57c45ac..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#define STRNCPY __strncpy_sse2
-#undef libc_hidden_builtin_def
-#define libc_hidden_builtin_def(strncpy)
-
-#include <string/strncpy.c>
diff --git a/sysdeps/x86_64/multiarch/strncpy-generic.c b/sysdeps/x86_64/multiarch/strncpy-generic.c
new file mode 100644 (file)
index 0000000..9916153
--- /dev/null
@@ -0,0 +1,24 @@
+/* strncpy.
+   Copyright (C) 2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+
+#define STRNCPY __strncpy_generic
+#undef libc_hidden_builtin_def
+#define libc_hidden_builtin_def(strncpy)
+
+#include <string/strncpy.c>
index 2a780a7e16044341cc1d7f3270da2299c579dcbf..7fc7d72ec55f27b3893ed31331625b384addc650 100644 (file)
@@ -24,6 +24,7 @@
 # undef strncpy
 
 # define SYMBOL_NAME strncpy
+# define GENERIC generic
 # include "ifunc-strcpy.h"
 
 libc_ifunc_redirected (__redirect_strncpy, strncpy, IFUNC_SELECTOR ());
diff --git a/sysdeps/x86_64/multiarch/strpbrk-c.c b/sysdeps/x86_64/multiarch/strpbrk-c.c
deleted file mode 100644 (file)
index abf4ff7..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* strpbrk with SSE4.2 intrinsics
-   Copyright (C) 2022 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
-   <https://www.gnu.org/licenses/>.  */
-
-#define USE_AS_STRPBRK
-#define STRCSPN_SSE2 __strpbrk_sse2
-#define STRCSPN_SSE42 __strpbrk_sse42
-#include "strcspn-c.c"
diff --git a/sysdeps/x86_64/multiarch/strpbrk-generic.c b/sysdeps/x86_64/multiarch/strpbrk-generic.c
new file mode 100644 (file)
index 0000000..d31acfe
--- /dev/null
@@ -0,0 +1,28 @@
+/* strpbrk.
+   Copyright (C) 2017-2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+#if IS_IN (libc)
+
+# include <sysdep.h>
+# define STRPBRK __strpbrk_generic
+
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(STRPBRK)
+#endif
+
+#include <string/strpbrk.c>
diff --git a/sysdeps/x86_64/multiarch/strpbrk-sse2.c b/sysdeps/x86_64/multiarch/strpbrk-sse2.c
deleted file mode 100644 (file)
index d03214c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* strpbrk.
-   Copyright (C) 2017-2022 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
-   <https://www.gnu.org/licenses/>.  */
-
-#if IS_IN (libc)
-
-# include <sysdep.h>
-# define STRPBRK __strpbrk_sse2
-
-# undef libc_hidden_builtin_def
-# define libc_hidden_builtin_def(STRPBRK)
-#endif
-
-#include <string/strpbrk.c>
diff --git a/sysdeps/x86_64/multiarch/strpbrk-sse4.c b/sysdeps/x86_64/multiarch/strpbrk-sse4.c
new file mode 100644 (file)
index 0000000..bf74d66
--- /dev/null
@@ -0,0 +1,22 @@
+/* strpbrk with SSE4.2 intrinsics
+   Copyright (C) 2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+#define USE_AS_STRPBRK
+#define STRCSPN_GENERIC __strpbrk_generic
+#define STRCSPN_SSE42 __strpbrk_sse42
+#include "strcspn-sse4.c"
diff --git a/sysdeps/x86_64/multiarch/strspn-c.c b/sysdeps/x86_64/multiarch/strspn-c.c
deleted file mode 100644 (file)
index 6124033..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/* strspn with SSE4.2 intrinsics
-   Copyright (C) 2009-2022 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
-   <https://www.gnu.org/licenses/>.  */
-
-#include <nmmintrin.h>
-#include <string.h>
-#include "varshift.h"
-
-/* We use 0x12:
-       _SIDD_SBYTE_OPS
-       | _SIDD_CMP_EQUAL_ANY
-       | _SIDD_NEGATIVE_POLARITY
-       | _SIDD_LEAST_SIGNIFICANT
-   on pcmpistri to compare xmm/mem128
-
-   0 1 2 3 4 5 6 7 8 9 A B C D E F
-   X X X X X X X X X X X X X X X X
-
-   against xmm
-
-   0 1 2 3 4 5 6 7 8 9 A B C D E F
-   A A A A A A A A A A A A A A A A
-
-   to find out if the first 16byte data element has any non-A byte and
-   the offset of the first byte.  There are 2 cases:
-
-   1. The first 16byte data element has the non-A byte, including
-      EOS, at the offset X.
-   2. The first 16byte data element is valid and doesn't have the non-A
-      byte.
-
-   Here is the table of ECX, CFlag, ZFlag and SFlag for 2 cases:
-
-   case                ECX     CFlag   ZFlag   SFlag
-    1           X        1      0/1      0
-    2          16        0       0       0
-
-   We exit from the loop for case 1.  */
-
-extern size_t __strspn_sse2 (const char *, const char *) attribute_hidden;
-
-
-size_t
-__attribute__ ((section (".text.sse4.2")))
-__strspn_sse42 (const char *s, const char *a)
-{
-  if (*a == 0)
-    return 0;
-
-  const char *aligned;
-  __m128i mask, maskz, zero;
-  unsigned int maskz_bits;
-  unsigned int offset = (int) ((size_t) a & 15);
-  zero = _mm_set1_epi8 (0);
-  if (offset != 0)
-    {
-      /* Load masks.  */
-      aligned = (const char *) ((size_t) a & -16L);
-      __m128i mask0 = _mm_load_si128 ((__m128i *) aligned);
-      maskz = _mm_cmpeq_epi8 (mask0, zero);
-
-      /* Find where the NULL terminator is.  */
-      maskz_bits = _mm_movemask_epi8 (maskz) >> offset;
-      if (maskz_bits != 0)
-        {
-          mask = __m128i_shift_right (mask0, offset);
-          offset = (unsigned int) ((size_t) s & 15);
-          if (offset)
-            goto start_unaligned;
-
-          aligned = s;
-          goto start_loop;
-        }
-    }
-
-  /* A is aligned.  */
-  mask = _mm_loadu_si128 ((__m128i *) a);
-
-  /* Find where the NULL terminator is.  */
-  maskz = _mm_cmpeq_epi8 (mask, zero);
-  maskz_bits = _mm_movemask_epi8 (maskz);
-  if (maskz_bits == 0)
-    {
-      /* There is no NULL terminator.  Don't use SSE4.2 if the length
-         of A > 16.  */
-      if (a[16] != 0)
-        return __strspn_sse2 (s, a);
-    }
-  aligned = s;
-  offset = (unsigned int) ((size_t) s & 15);
-
-  if (offset != 0)
-    {
-    start_unaligned:
-      /* Check partial string.  */
-      aligned = (const char *) ((size_t) s & -16L);
-      __m128i value = _mm_load_si128 ((__m128i *) aligned);
-      __m128i adj_value = __m128i_shift_right (value, offset);
-
-      unsigned int length = _mm_cmpistri (mask, adj_value, 0x12);
-      /* No need to check CFlag since it is always 1.  */
-      if (length < 16 - offset)
-       return length;
-      /* Find where the NULL terminator is.  */
-      maskz = _mm_cmpeq_epi8 (value, zero);
-      maskz_bits = _mm_movemask_epi8 (maskz) >> offset;
-      if (maskz_bits != 0)
-       return length;
-      aligned += 16;
-    }
-
-start_loop:
-  while (1)
-    {
-      __m128i value = _mm_load_si128 ((__m128i *) aligned);
-      unsigned int index = _mm_cmpistri (mask, value, 0x12);
-      unsigned int cflag = _mm_cmpistrc (mask, value, 0x12);
-      if (cflag)
-       return (size_t) (aligned + index - s);
-      aligned += 16;
-    }
-}
diff --git a/sysdeps/x86_64/multiarch/strspn-generic.c b/sysdeps/x86_64/multiarch/strspn-generic.c
new file mode 100644 (file)
index 0000000..6b50c36
--- /dev/null
@@ -0,0 +1,28 @@
+/* strspn.
+   Copyright (C) 2017-2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+#if IS_IN (libc)
+
+# include <sysdep.h>
+# define STRSPN __strspn_generic
+
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(STRSPN)
+#endif
+
+#include <string/strspn.c>
diff --git a/sysdeps/x86_64/multiarch/strspn-sse2.c b/sysdeps/x86_64/multiarch/strspn-sse2.c
deleted file mode 100644 (file)
index 61cc6cb..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* strspn.
-   Copyright (C) 2017-2022 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
-   <https://www.gnu.org/licenses/>.  */
-
-#if IS_IN (libc)
-
-# include <sysdep.h>
-# define STRSPN __strspn_sse2
-
-# undef libc_hidden_builtin_def
-# define libc_hidden_builtin_def(STRSPN)
-#endif
-
-#include <string/strspn.c>
diff --git a/sysdeps/x86_64/multiarch/strspn-sse4.c b/sysdeps/x86_64/multiarch/strspn-sse4.c
new file mode 100644 (file)
index 0000000..d044916
--- /dev/null
@@ -0,0 +1,136 @@
+/* strspn with SSE4.2 intrinsics
+   Copyright (C) 2009-2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <nmmintrin.h>
+#include <string.h>
+#include "varshift.h"
+
+/* We use 0x12:
+       _SIDD_SBYTE_OPS
+       | _SIDD_CMP_EQUAL_ANY
+       | _SIDD_NEGATIVE_POLARITY
+       | _SIDD_LEAST_SIGNIFICANT
+   on pcmpistri to compare xmm/mem128
+
+   0 1 2 3 4 5 6 7 8 9 A B C D E F
+   X X X X X X X X X X X X X X X X
+
+   against xmm
+
+   0 1 2 3 4 5 6 7 8 9 A B C D E F
+   A A A A A A A A A A A A A A A A
+
+   to find out if the first 16byte data element has any non-A byte and
+   the offset of the first byte.  There are 2 cases:
+
+   1. The first 16byte data element has the non-A byte, including
+      EOS, at the offset X.
+   2. The first 16byte data element is valid and doesn't have the non-A
+      byte.
+
+   Here is the table of ECX, CFlag, ZFlag and SFlag for 2 cases:
+
+   case                ECX     CFlag   ZFlag   SFlag
+    1           X        1      0/1      0
+    2          16        0       0       0
+
+   We exit from the loop for case 1.  */
+
+extern size_t __strspn_generic (const char *, const char *) attribute_hidden;
+
+
+size_t
+__attribute__ ((section (".text.sse4.2")))
+__strspn_sse42 (const char *s, const char *a)
+{
+  if (*a == 0)
+    return 0;
+
+  const char *aligned;
+  __m128i mask, maskz, zero;
+  unsigned int maskz_bits;
+  unsigned int offset = (int) ((size_t) a & 15);
+  zero = _mm_set1_epi8 (0);
+  if (offset != 0)
+    {
+      /* Load masks.  */
+      aligned = (const char *) ((size_t) a & -16L);
+      __m128i mask0 = _mm_load_si128 ((__m128i *) aligned);
+      maskz = _mm_cmpeq_epi8 (mask0, zero);
+
+      /* Find where the NULL terminator is.  */
+      maskz_bits = _mm_movemask_epi8 (maskz) >> offset;
+      if (maskz_bits != 0)
+        {
+          mask = __m128i_shift_right (mask0, offset);
+          offset = (unsigned int) ((size_t) s & 15);
+          if (offset)
+            goto start_unaligned;
+
+          aligned = s;
+          goto start_loop;
+        }
+    }
+
+  /* A is aligned.  */
+  mask = _mm_loadu_si128 ((__m128i *) a);
+
+  /* Find where the NULL terminator is.  */
+  maskz = _mm_cmpeq_epi8 (mask, zero);
+  maskz_bits = _mm_movemask_epi8 (maskz);
+  if (maskz_bits == 0)
+    {
+      /* There is no NULL terminator.  Don't use SSE4.2 if the length
+         of A > 16.  */
+      if (a[16] != 0)
+        return __strspn_generic (s, a);
+    }
+  aligned = s;
+  offset = (unsigned int) ((size_t) s & 15);
+
+  if (offset != 0)
+    {
+    start_unaligned:
+      /* Check partial string.  */
+      aligned = (const char *) ((size_t) s & -16L);
+      __m128i value = _mm_load_si128 ((__m128i *) aligned);
+      __m128i adj_value = __m128i_shift_right (value, offset);
+
+      unsigned int length = _mm_cmpistri (mask, adj_value, 0x12);
+      /* No need to check CFlag since it is always 1.  */
+      if (length < 16 - offset)
+       return length;
+      /* Find where the NULL terminator is.  */
+      maskz = _mm_cmpeq_epi8 (value, zero);
+      maskz_bits = _mm_movemask_epi8 (maskz) >> offset;
+      if (maskz_bits != 0)
+       return length;
+      aligned += 16;
+    }
+
+start_loop:
+  while (1)
+    {
+      __m128i value = _mm_load_si128 ((__m128i *) aligned);
+      unsigned int index = _mm_cmpistri (mask, value, 0x12);
+      unsigned int cflag = _mm_cmpistrc (mask, value, 0x12);
+      if (cflag)
+       return (size_t) (aligned + index - s);
+      aligned += 16;
+    }
+}
diff --git a/sysdeps/x86_64/multiarch/wcscpy-c.c b/sysdeps/x86_64/multiarch/wcscpy-c.c
deleted file mode 100644 (file)
index 26d6984..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#if IS_IN (libc)
-# define WCSCPY  __wcscpy_sse2
-#endif
-
-#include <wcsmbs/wcscpy.c>
diff --git a/sysdeps/x86_64/multiarch/wcscpy-generic.c b/sysdeps/x86_64/multiarch/wcscpy-generic.c
new file mode 100644 (file)
index 0000000..5ea905f
--- /dev/null
@@ -0,0 +1,24 @@
+/* wcscpy.
+   Copyright (C) 2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+
+#if IS_IN (libc)
+# define WCSCPY  __wcscpy_generic
+#endif
+
+#include <wcsmbs/wcscpy.c>
index 6a2d1421d9e31c6d9543bbdcc37540d3ba4f8e0e..53c3228dc2cc9471bacd24fd0790373f6b7c53e7 100644 (file)
@@ -26,7 +26,7 @@
 # define SYMBOL_NAME wcscpy
 # include <init-arch.h>
 
-extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (generic) attribute_hidden;
 extern __typeof (REDIRECT_NAME) OPTIMIZE (ssse3) attribute_hidden;
 
 static inline void *
@@ -37,7 +37,7 @@ IFUNC_SELECTOR (void)
   if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3))
     return OPTIMIZE (ssse3);
 
-  return OPTIMIZE (sse2);
+  return OPTIMIZE (generic);
 }
 
 libc_ifunc_redirected (__redirect_wcscpy, __wcscpy, IFUNC_SELECTOR ());
diff --git a/sysdeps/x86_64/multiarch/wcsncmp-generic.c b/sysdeps/x86_64/multiarch/wcsncmp-generic.c
new file mode 100644 (file)
index 0000000..658d541
--- /dev/null
@@ -0,0 +1,20 @@
+/* wcsncmp.
+   Copyright (C) 2018-2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+#define WCSNCMP __wcsncmp_generic
+#include <wcsmbs/wcsncmp.c>
diff --git a/sysdeps/x86_64/multiarch/wcsncmp-sse2.c b/sysdeps/x86_64/multiarch/wcsncmp-sse2.c
deleted file mode 100644 (file)
index 8d9cbbb..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* wcsncmp optimized with SSE2.
-   Copyright (C) 2018-2022 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
-   <https://www.gnu.org/licenses/>.  */
-
-#define WCSNCMP __wcsncmp_sse2
-#include <wcsmbs/wcsncmp.c>
index 5e00af2ca56f4f5c431fe6e0575e8f38179798e4..1836f794dd77bca20c979c8aff4ee35a96e5f755 100644 (file)
@@ -24,6 +24,8 @@
 # undef wcsncmp
 # undef __wcsncmp
 
+# define GENERIC generic
+
 # define SYMBOL_NAME wcsncmp
 # include "ifunc-avx2.h"
 
diff --git a/sysdeps/x86_64/multiarch/wcsnlen-c.c b/sysdeps/x86_64/multiarch/wcsnlen-c.c
deleted file mode 100644 (file)
index e1ec7cf..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#if IS_IN (libc)
-# include <wchar.h>
-
-# define WCSNLEN __wcsnlen_sse2
-
-extern __typeof (wcsnlen) __wcsnlen_sse2;
-#endif
-
-#include "wcsmbs/wcsnlen.c"
diff --git a/sysdeps/x86_64/multiarch/wcsnlen-generic.c b/sysdeps/x86_64/multiarch/wcsnlen-generic.c
new file mode 100644 (file)
index 0000000..2d75da7
--- /dev/null
@@ -0,0 +1,28 @@
+/* wcsnlen.
+   Copyright (C) 2022 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
+   <https://www.gnu.org/licenses/>.  */
+
+
+#if IS_IN (libc)
+# include <wchar.h>
+
+# define WCSNLEN __wcsnlen_generic
+
+extern __typeof (wcsnlen) __wcsnlen_generic;
+#endif
+
+#include "wcsmbs/wcsnlen.c"
index baa26666a84172fe25bdf11318ef75e662dd69a1..05b7a211deadd8b2b0017aef77c497db15bf54a5 100644 (file)
@@ -24,6 +24,7 @@
 # undef __wcsnlen
 
 # define SYMBOL_NAME wcsnlen
+# define GENERIC generic
 # include "ifunc-wcslen.h"
 
 libc_ifunc_redirected (__redirect_wcsnlen, __wcsnlen, IFUNC_SELECTOR ());