]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Improve generic strpbrk. neleai/string-x64
authorOndřej Bílka <neleai@seznam.cz>
Mon, 29 Jun 2015 15:47:01 +0000 (17:47 +0200)
committerOndřej Bílka <neleai@seznam.cz>
Thu, 20 Aug 2015 07:53:36 +0000 (09:53 +0200)
string/strcspn.c
string/strpbrk.c
string/test-strcspn.c
string/test-strpbrk.c
sysdeps/x86_64/multiarch/Makefile
sysdeps/x86_64/multiarch/strcspn.S
sysdeps/x86_64/multiarch/strpbrk_sse2.c [new file with mode: 0644]
sysdeps/x86_64/multiarch/strpbrk_sse2_late.c [new file with mode: 0644]

index 2694d2ab0e807d0712d6b103dbdfd75ef164ebf1..2a82dd256e805bd7f5cbd9b606b096ba3dd9e932 100644 (file)
@@ -1,41 +1,2 @@
-/* Copyright (C) 1991-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/>.  */
-
-#include <string.h>
-
-#undef strcspn
-
-#ifndef STRCSPN
-# define STRCSPN strcspn
-#endif
-
-/* Return the length of the maximum initial segment of S
-   which contains no characters from REJECT.  */
-size_t
-STRCSPN (const char *s, const char *reject)
-{
-  size_t count = 0;
-
-  while (*s != '\0')
-    if (strchr (reject, *s++) == NULL)
-      ++count;
-    else
-      return count;
-
-  return count;
-}
-libc_hidden_builtin_def (strcspn)
+#define AS_STRCSPN
+#include "strpbrk.c"
index 4f1d9b72bb80f5690e6b10bacc496ddf26fdb056..01cd55afdf0d3f065338d061404a99198f307ee0 100644 (file)
    <http://www.gnu.org/licenses/>.  */
 
 #include <string.h>
-
+#include <stdint.h>
 #undef strpbrk
+#undef strcspn
+
+
+#ifdef AS_STRCSPN
+# ifndef STRPBRK
+#  define STRPBRK strcspn
+# endif
+# define RETURN_TYPE size_t
+# define RETURN(c) return c
+#else
+# define RETURN_TYPE char *
+# define RETURN(c) return (char *) (s[c] != '\0' ? s + c : NULL)
+#endif
 
 #ifndef STRPBRK
 #define STRPBRK strpbrk
 #endif
 
+
 /* Find the first occurrence in S of any character in ACCEPT.  */
-char *
-STRPBRK (const char *s, const char *accept)
+RETURN_TYPE
+STRPBRK (const char *_s, const char *_accept)
 {
-  while (*s != '\0')
+  unsigned char *s = (unsigned char *) _s;
+  unsigned char *a = (unsigned char *) _accept;
+
+#ifndef LATE_CHECK
+  /* We need to align s to 4 bytes. We do check now to avoid expensive table
+     construction.  */
+  do
+    {
+      if (s[0] == *a)
+        RETURN(0);
+    }
+  while (*a++);
+  a = (unsigned char *) _accept;
+
+  /* We couldn't do these checks in one loop as gcc
+     messes up register allocation.  */
+  do
+    {
+      if (s[1] == *a)
+        RETURN(1);
+    }
+  while (*a++);
+  a = (unsigned char *) _accept;
+
+  do
+    {
+      if (s[2] == *a)
+        RETURN(2);
+    }
+  while (*a++);
+  a = (unsigned char *) _accept;
+
+  do
+    {
+      if (s[3] == *a)
+        RETURN(3);
+    }
+  while (*a++);
+  a = (unsigned char *) _accept;
+
+#endif
+
+  unsigned char table[256];
+  memset (table, 0, 256);
+  do
     {
-      const char *a = accept;
-      while (*a != '\0')
-       if (*a++ == *s)
-         return (char *) s;
-      ++s;
+      table[*a] = 1;
     }
+  while (*a++);
+  unsigned char s0, s1, s2, s3;
+  size_t count = 0;
+#ifdef LATE_CHECK
+  s0 = s[count + 0];
+  s1 = s[count + 1];
+  s2 = s[count + 2];
+  s3 = s[count + 3];
+  if (table[s0])
+    goto ret0;
+  if (table[s1])
+    goto ret1;
+  if (table[s2])
+    goto ret2;
+  if (table[s3])
+    goto ret3;
 
-  return NULL;
+#endif
+
+  count = 4 - ((uintptr_t) s) % 4;
+
+  while (1)
+    {
+      s0 = s[count + 0];
+      s1 = s[count + 1];
+      s2 = s[count + 2];
+      s3 = s[count + 3];
+      if (table[s0])
+        goto ret0;
+      if (table[s1])
+        goto ret1;
+      if (table[s2])
+        goto ret2;
+      if (table[s3])
+        goto ret3;
+      count += 4;
+    }
+  ret3:
+  count++;
+  ret2:
+  count++;
+  ret1:
+  count++;
+  ret0:
+  RETURN(count);
 }
-libc_hidden_builtin_def (strpbrk)
+
+libc_hidden_builtin_def (STRPBRK)
index b60a048c5c888d4e1b6d36b9f38d711c6374e204..50a06e44c4801b63c6814ec892aea99833d30b05 100644 (file)
@@ -31,18 +31,9 @@ IMPL (stupid_strcspn, 0)
 IMPL (simple_strcspn, 0)
 IMPL (strcspn, 1)
 
-size_t
-simple_strcspn (const char *s, const char *rej)
-{
-  const char *r, *str = s;
-  char c;
-
-  while ((c = *s++) != '\0')
-    for (r = rej; *r != '\0'; ++r)
-      if (*r == c)
-       return s - str - 1;
-  return s - str - 1;
-}
+#define AS_STRCSPN
+#define STRPBRK simple_strcspn
+#include "string/strpbrk.c"
 
 size_t
 stupid_strcspn (const char *s, const char *rej)
index b4ac389a710ef4321c327785534e1fa48395d1de..f389e9dabfc030252075f0b90276f23991f885dd 100644 (file)
@@ -32,18 +32,8 @@ IMPL (stupid_strpbrk, 0)
 IMPL (simple_strpbrk, 0)
 IMPL (strpbrk, 1)
 
-char *
-simple_strpbrk (const char *s, const char *rej)
-{
-  const char *r;
-  char c;
-
-  while ((c = *s++) != '\0')
-    for (r = rej; *r != '\0'; ++r)
-      if (*r == c)
-       return (char *) s - 1;
-  return NULL;
-}
+#define STRPBRK simple_strpbrk
+#include "string/strpbrk.c"
 
 char *
 stupid_strpbrk (const char *s, const char *rej)
index 05d5c9ba307cb02122928dbe6ea6476c58521c0f..6996d128b2f09598b8e7dfdd7572f3e4f611e8fd 100644 (file)
@@ -19,7 +19,8 @@ sysdep_routines += strncat-c stpncpy-c strncpy-c strcmp-ssse3 \
                   strcpy-sse2-unaligned strncpy-sse2-unaligned \
                   stpcpy-sse2-unaligned stpncpy-sse2-unaligned \
                   strcat-sse2-unaligned strncat-sse2-unaligned \
-                  strchr-sse2-no-bsf memcmp-ssse3 strstr-sse2-unaligned
+                  strchr-sse2-no-bsf memcmp-ssse3 strstr-sse2-unaligned \
+                  strcspn_sse2 strpbrk_sse2 strcspn_sse2_late strpbrk_sse2_late
 
 ifeq (yes,$(config-cflags-sse4))
 sysdep_routines += strcspn_sse42 strpbrk_sse42 strspn_sse42
index 95e882c443b19451c6f6185a8c2c9360bc8d028c..4fe49748121d55969bde271f4f3648b2a2a105e6 100644 (file)
@@ -54,22 +54,9 @@ ENTRY(STRCSPN)
        leaq    STRCSPN_SSE42(%rip), %rax
 2:     ret
 END(STRCSPN)
-
-# undef ENTRY
-# define ENTRY(name) \
-       .type STRCSPN_SSE2, @function; \
-       .globl STRCSPN_SSE2; \
-       .align 16; \
-       STRCSPN_SSE2: cfi_startproc; \
-       CALL_MCOUNT
-# undef END
-# define END(name) \
-       cfi_endproc; .size STRCSPN_SSE2, .-STRCSPN_SSE2
 #endif
-#endif /* HAVE_SSE4_SUPPORT */
 
-#ifdef USE_AS_STRPBRK
-#include "../strpbrk.S"
-#else
-#include "../strcspn.S"
-#endif
+#else /* HAVE_SSE4_SUPPORT */
+weak_alias (STRCSPN_SSE2, STRCSPN)
+#endif /* HAVE_SSE4_SUPPORT */
+libc_hidden_builtin_def (STRCSPN)
diff --git a/sysdeps/x86_64/multiarch/strpbrk_sse2.c b/sysdeps/x86_64/multiarch/strpbrk_sse2.c
new file mode 100644 (file)
index 0000000..317f4fa
--- /dev/null
@@ -0,0 +1,4 @@
+#define STRPBRK __strpbrk_sse2
+#undef libc_hidden_builtin_def
+#define libc_hidden_builtin_def(x)
+#include "string/strpbrk.c"
diff --git a/sysdeps/x86_64/multiarch/strpbrk_sse2_late.c b/sysdeps/x86_64/multiarch/strpbrk_sse2_late.c
new file mode 100644 (file)
index 0000000..f2e1c4d
--- /dev/null
@@ -0,0 +1,4 @@
+#define STRPBRK __strpbrk_sse2_late
+#undef libc_hidden_builtin_def
+#define libc_hidden_builtin_def(x)
+#include "string/strpbrk.c"