Improve 64 bit memchr, memrchr, rawmemchr with SSE2
authorLiubov Dmitrieva <liubov.dmitrieva@gmail.com>
Fri, 7 Oct 2011 15:49:10 +0000 (11:49 -0400)
committerUlrich Drepper <drepper@gmail.com>
Fri, 7 Oct 2011 15:49:10 +0000 (11:49 -0400)
ChangeLog
NEWS
sysdeps/x86_64/memchr.S
sysdeps/x86_64/memrchr.S [new file with mode: 0644]
sysdeps/x86_64/multiarch/rawmemchr.S
sysdeps/x86_64/rawmemchr.S

index c369539..a5b5a53 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2011-08-31  Liubov Dmitrieva  <liubov.dmitrieva@gmail.com>
+
+       * sysdeps/x86_64/multiarch/rawmemchr.S: Update.
+       Use new sse2 version for core i3 - i7 as it's faster
+       than sse42 version.
+       (bit_Prefer_PMINUB_for_stringop): New.
+       * sysdeps/x86_64/rawmemchr.S: Update.
+       Replace with faster SSE2 version.
+       * sysdeps/x86_64/memrchr.S: New file.
+       * sysdeps/x86_64/memchr.S: Update.
+       Replace with faster SSE2 version.
+
 2011-09-12  Marek Polacek  <mpolacek@redhat.com>
 
        * elf/dl-load.c (lose): Add cast to avoid warning.
diff --git a/NEWS b/NEWS
index 1af566f..73552e6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,9 @@ Version 2.15
 * Optimized strchr and strrchr for SSE on x86-32.
   Contributed by Liubov Dmitrieva.
 
+* Optimized memchr, memrchr, rawmemchr for x86-64.
+  Contributed by Liubov Dmitrieva.
+
 * New interfaces: scandirat, scandirat64
   Implemented by Ulrich Drepper.
 
index 6082aa7..895a014 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 2009 Free Software Foundation, Inc.
-   Contributed by Ulrich Drepper <drepper@redhat.com>.
+/* Copyright (C)  2011 Free Software Foundation, Inc.
+   Contributed by Intel Corporation.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
 
 #include <sysdep.h>
 
+/* fast SSE2 version with using pmaxub and 64 byte loop */
 
        .text
-ENTRY (memchr)
-       movd    %esi, %xmm1
-       movq    %rdi, %rcx
+ENTRY(memchr)
+       movd    %rsi, %xmm1
+       mov     %rdi, %rcx
+
        punpcklbw %xmm1, %xmm1
-       andq    $~15, %rdi
-       testq   %rdx, %rdx
+       test    %rdx, %rdx
+       jz      L(return_null)
        punpcklbw %xmm1, %xmm1
-       jz      3f
-       orl     $0xffffffff, %esi
-       movdqa  (%rdi), %xmm0
+
+       and     $63, %rcx
        pshufd  $0, %xmm1, %xmm1
-       subq    %rdi, %rcx
+
+       cmp     $48, %rcx
+       ja      L(crosscache)
+
+       movdqu  (%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+
+       jnz     L(matches_1)
+       sub     $16, %rdx
+       jbe     L(return_null)
+       add     $16, %rdi
+       and     $15, %rcx
+       and     $-16, %rdi
+       add     %rcx, %rdx
+       sub     $64, %rdx
+       jbe     L(exit_loop)
+       jmp     L(loop_prolog)
+
+       .p2align 4
+L(crosscache):
+       and     $15, %rcx
+       and     $-16, %rdi
+       movdqa  (%rdi), %xmm0
+
+       pcmpeqb %xmm1, %xmm0
+/* Check if there is a match.  */
+       pmovmskb %xmm0, %eax
+/* Remove the leading bytes.  */
+       sar     %cl, %eax
+       test    %eax, %eax
+       je      L(unaligned_no_match)
+/* Check which byte is a match.  */
+       bsf     %eax, %eax
+
+       sub     %rax, %rdx
+       jbe     L(return_null)
+       add     %rdi, %rax
+       add     %rcx, %rax
+       ret
+
+       .p2align 4
+L(unaligned_no_match):
+       add     %rcx, %rdx
+       sub     $16, %rdx
+       jbe     L(return_null)
+       add     $16, %rdi
+       sub     $64, %rdx
+       jbe     L(exit_loop)
+
+       .p2align 4
+L(loop_prolog):
+       movdqa  (%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches)
+
+       movdqa  16(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  32(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       movdqa  48(%rdi), %xmm4
+       pcmpeqb %xmm1, %xmm4
+       add     $64, %rdi
+       pmovmskb %xmm4, %eax
+       test    %eax, %eax
+       jnz     L(matches0)
+
+       test    $0x3f, %rdi
+       jz      L(align64_loop)
+
+       sub     $64, %rdx
+       jbe     L(exit_loop)
+
+       movdqa  (%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches)
+
+       movdqa  16(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  32(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       movdqa  48(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb %xmm3, %eax
+
+       add     $64, %rdi
+       test    %eax, %eax
+       jnz     L(matches0)
+
+       mov     %rdi, %rcx
+       and     $-64, %rdi
+       and     $63, %rcx
+       add     %rcx, %rdx
+
+       .p2align 4
+L(align64_loop):
+       sub     $64, %rdx
+       jbe     L(exit_loop)
+       movdqa  (%rdi), %xmm0
+       movdqa  16(%rdi), %xmm2
+       movdqa  32(%rdi), %xmm3
+       movdqa  48(%rdi), %xmm4
+
+       pcmpeqb %xmm1, %xmm0
+       pcmpeqb %xmm1, %xmm2
+       pcmpeqb %xmm1, %xmm3
+       pcmpeqb %xmm1, %xmm4
+
+       pmaxub  %xmm0, %xmm3
+       pmaxub  %xmm2, %xmm4
+       pmaxub  %xmm3, %xmm4
+       pmovmskb %xmm4, %eax
+
+       add     $64, %rdi
+
+       test    %eax, %eax
+       jz      L(align64_loop)
+
+       sub     $64, %rdi
+
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches)
+
+       pmovmskb %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  32(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+
+       pcmpeqb 48(%rdi), %xmm1
+       pmovmskb %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       pmovmskb %xmm1, %eax
+       bsf     %eax, %eax
+       lea     48(%rdi, %rax), %rax
+       ret
+
+       .p2align 4
+L(exit_loop):
+       add     $32, %rdx
+       jle     L(exit_loop_32)
+
+       movdqa  (%rdi), %xmm0
        pcmpeqb %xmm1, %xmm0
-       addq    %rcx, %rdx
-       shl     %cl, %esi
-       pmovmskb %xmm0, %ecx
-       andl    %esi, %ecx
-       movl    $16, %esi
-       jnz     1f
-       cmpq    %rsi, %rdx
-       jbe     3f
-
-2:     movdqa  (%rdi,%rsi), %xmm0
-       leaq    16(%rsi), %rsi
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches)
+
+       movdqa  16(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  32(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches32_1)
+       sub     $16, %rdx
+       jle     L(return_null)
+
+       pcmpeqb 48(%rdi), %xmm1
+       pmovmskb %xmm1, %eax
+       test    %eax, %eax
+       jnz     L(matches48_1)
+       xor     %rax, %rax
+       ret
+
+       .p2align 4
+L(exit_loop_32):
+       add     $32, %rdx
+       movdqa  (%rdi), %xmm0
        pcmpeqb %xmm1, %xmm0
-       pmovmskb %xmm0, %ecx
-       testl   %ecx, %ecx
-       jnz     1f
-       cmpq    %rsi, %rdx
-       ja      2b
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches_1)
+       sub     $16, %rdx
+       jbe     L(return_null)
 
-3:     xorl    %eax, %eax
+       pcmpeqb 16(%rdi), %xmm1
+       pmovmskb %xmm1, %eax
+       test    %eax, %eax
+       jnz     L(matches16_1)
+       xor     %rax, %rax
        ret
 
-1:     leaq    -16(%rdi,%rsi), %rax
-       bsfl    %ecx, %ecx
-       addq    %rcx, %rax
-       leaq    -16(%rsi,%rcx), %rsi
-       cmpq    %rsi, %rdx
-       jbe     3b
+       .p2align 4
+L(matches0):
+       bsf     %eax, %eax
+       lea     -16(%rax, %rdi), %rax
        ret
-END (memchr)
+
+       .p2align 4
+L(matches):
+       bsf     %eax, %eax
+       add     %rdi, %rax
+       ret
+
+       .p2align 4
+L(matches16):
+       bsf     %eax, %eax
+       lea     16(%rax, %rdi), %rax
+       ret
+
+       .p2align 4
+L(matches32):
+       bsf     %eax, %eax
+       lea     32(%rax, %rdi), %rax
+       ret
+
+       .p2align 4
+L(matches_1):
+       bsf     %eax, %eax
+       sub     %rax, %rdx
+       jbe     L(return_null)
+       add     %rdi, %rax
+       ret
+
+       .p2align 4
+L(matches16_1):
+       bsf     %eax, %eax
+       sub     %rax, %rdx
+       jbe     L(return_null)
+       lea     16(%rdi, %rax), %rax
+       ret
+
+       .p2align 4
+L(matches32_1):
+       bsf     %eax, %eax
+       sub     %rax, %rdx
+       jbe     L(return_null)
+       lea     32(%rdi, %rax), %rax
+       ret
+
+       .p2align 4
+L(matches48_1):
+       bsf     %eax, %eax
+       sub     %rax, %rdx
+       jbe     L(return_null)
+       lea     48(%rdi, %rax), %rax
+       ret
+
+       .p2align 4
+L(return_null):
+       xor     %rax, %rax
+       ret
+END(memchr)
 
 strong_alias (memchr, __memchr)
-libc_hidden_builtin_def (memchr)
+
+libc_hidden_builtin_def(memchr)
diff --git a/sysdeps/x86_64/memrchr.S b/sysdeps/x86_64/memrchr.S
new file mode 100644 (file)
index 0000000..a85dc6b
--- /dev/null
@@ -0,0 +1,380 @@
+/* fast SSE2 memrchr with 64 byte loop and pmaxub instruction using
+
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by Intel Corporation.
+   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 <sysdep.h>
+
+       .text
+ENTRY (memrchr)
+       movd    %rsi, %xmm1
+
+       sub     $16, %rdx
+       jbe     L(length_less16)
+
+       punpcklbw       %xmm1, %xmm1
+       punpcklbw       %xmm1, %xmm1
+
+       add     %rdx, %rdi
+       pshufd  $0, %xmm1, %xmm1
+
+       movdqu  (%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+
+/* Check if there is a match.  */
+       pmovmskb        %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches0)
+
+       sub     $64, %rdi
+       mov     %rdi, %rcx
+       and     $15, %rcx
+       jz      L(loop_prolog)
+
+       add     $16, %rdi
+       add     $16, %rdx
+       and     $-16, %rdi
+       sub     %rcx, %rdx
+
+       .p2align 4
+L(loop_prolog):
+       sub     $64, %rdx
+       jbe     L(exit_loop)
+
+       movdqa  48(%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb        %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches48)
+
+       movdqa  32(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb        %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       movdqa  16(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb        %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  (%rdi), %xmm4
+       pcmpeqb %xmm1, %xmm4
+       pmovmskb        %xmm4, %eax
+       test    %eax, %eax
+       jnz     L(matches0)
+
+       sub     $64, %rdi
+       sub     $64, %rdx
+       jbe     L(exit_loop)
+
+       movdqa  48(%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb        %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches48)
+
+       movdqa  32(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb        %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       movdqa  16(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb        %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  (%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb        %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches0)
+
+       mov     %rdi, %rcx
+       and     $63, %rcx
+       jz      L(align64_loop)    
+
+       add     $64, %rdi
+       add     $64, %rdx
+       and     $-64, %rdi
+       sub     %rcx, %rdx
+
+       .p2align 4
+L(align64_loop):
+       sub     $64, %rdi
+       sub     $64, %rdx
+       jbe     L(exit_loop)
+
+       movdqa  (%rdi), %xmm0
+       movdqa  16(%rdi), %xmm2
+       movdqa  32(%rdi), %xmm3
+       movdqa  48(%rdi), %xmm4
+
+       pcmpeqb %xmm1, %xmm0
+       pcmpeqb %xmm1, %xmm2
+       pcmpeqb %xmm1, %xmm3
+       pcmpeqb %xmm1, %xmm4
+
+       pmaxub  %xmm3, %xmm0
+       pmaxub  %xmm4, %xmm2
+       pmaxub  %xmm0, %xmm2
+       pmovmskb        %xmm2, %eax
+
+       test    %eax, %eax
+       jz      L(align64_loop)
+
+       pmovmskb        %xmm4, %eax
+       test    %eax, %eax
+       jnz     L(matches48)
+
+       pmovmskb        %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       movdqa  16(%rdi), %xmm2
+
+       pcmpeqb %xmm1, %xmm2
+       pcmpeqb (%rdi), %xmm1
+
+       pmovmskb        %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       pmovmskb        %xmm1, %eax
+       bsr     %eax, %eax
+
+       add     %rdi, %rax
+       ret
+
+       .p2align 4
+L(exit_loop):
+       add     $64, %rdx
+       cmp     $32, %rdx
+       jbe     L(exit_loop_32)
+
+       movdqa  48(%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb        %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches48)
+
+       movdqa  32(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb        %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       movdqa  16(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb        %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches16_1)
+       cmp     $48, %rdx
+       jbe     L(return_null)
+
+       pcmpeqb (%rdi), %xmm1
+       pmovmskb        %xmm1, %eax
+       test    %eax, %eax
+       jnz     L(matches0_1)
+       xor     %eax, %eax
+       ret
+
+       .p2align 4
+L(exit_loop_32):
+       movdqa  48(%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb        %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches48_1)
+       cmp     $16, %rdx
+       jbe     L(return_null)
+
+       pcmpeqb 32(%rdi), %xmm1
+       pmovmskb        %xmm1, %eax
+       test    %eax, %eax
+       jnz     L(matches32_1)
+       xor     %eax, %eax
+       ret
+
+       .p2align 4
+L(matches0):
+       bsr     %eax, %eax
+       add     %rdi, %rax
+       ret
+
+       .p2align 4
+L(matches16):
+       bsr     %eax, %eax
+       lea     16(%rax, %rdi), %rax
+       ret
+
+       .p2align 4
+L(matches32):
+       bsr     %eax, %eax
+       lea     32(%rax, %rdi), %rax
+       ret
+
+       .p2align 4
+L(matches48):
+       bsr     %eax, %eax
+       lea     48(%rax, %rdi), %rax
+       ret
+
+       .p2align 4
+L(matches0_1):
+       bsr     %eax, %eax
+       sub     $64, %rdx
+       add     %rax, %rdx
+       jl      L(return_null)
+       add     %rdi, %rax
+       ret
+
+       .p2align 4
+L(matches16_1):
+       bsr     %eax, %eax
+       sub     $48, %rdx
+       add     %rax, %rdx
+       jl      L(return_null)
+       lea     16(%rdi, %rax), %rax
+       ret
+
+       .p2align 4
+L(matches32_1):
+       bsr     %eax, %eax
+       sub     $32, %rdx
+       add     %rax, %rdx
+       jl      L(return_null)
+       lea     32(%rdi, %rax), %rax
+       ret
+
+       .p2align 4
+L(matches48_1):
+       bsr     %eax, %eax
+       sub     $16, %rdx
+       add     %rax, %rdx
+       jl      L(return_null)
+       lea     48(%rdi, %rax), %rax
+       ret
+
+       .p2align 4
+L(return_null):
+       xor     %rax, %rax
+       ret
+
+       .p2align 4
+L(length_less16_offset0):
+       mov     %dl, %cl
+       pcmpeqb (%rdi), %xmm1
+
+       mov     $1, %edx
+       sal     %cl, %edx
+       sub     $1, %edx
+
+       pmovmskb        %xmm1, %eax
+
+       and     %edx, %eax
+       test    %eax, %eax
+       jz      L(return_null)
+
+       bsr     %eax, %eax
+       add     %rdi, %rax
+       ret
+
+       .p2align 4
+L(length_less16):
+       punpcklbw       %xmm1, %xmm1
+       punpcklbw       %xmm1, %xmm1
+
+       add     $16, %rdx
+
+       pshufd  $0, %xmm1, %xmm1
+
+       mov     %rdi, %rcx
+       and     $15, %rcx
+       jz      L(length_less16_offset0)
+
+       mov     %rdi, %rcx
+       and     $15, %rcx
+       mov     %cl, %dh
+       mov     %rcx, %r8
+       add     %dl, %dh
+       and     $-16, %rdi
+
+       sub     $16, %dh
+       ja      L(length_less16_part2)
+
+       pcmpeqb (%rdi), %xmm1
+       pmovmskb        %xmm1, %eax
+
+       sar     %cl, %eax
+       mov     %dl, %cl
+
+       mov     $1, %edx
+       sal     %cl, %edx
+       sub     $1, %edx
+
+       and     %edx, %eax
+       test    %eax, %eax
+       jz      L(return_null)
+
+       bsr     %eax, %eax
+       add     %rdi, %rax
+       add     %r8, %rax
+       ret
+
+       .p2align 4
+L(length_less16_part2):
+       movdqa  16(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb        %xmm2, %eax
+
+       mov     %dh, %cl
+       mov     $1, %edx
+       sal     %cl, %edx
+       sub     $1, %edx
+
+       and     %edx, %eax
+
+       test    %eax, %eax
+       jnz     L(length_less16_part2_return)
+
+       pcmpeqb (%rdi), %xmm1
+       pmovmskb        %xmm1, %eax
+
+       mov     %r8, %rcx
+       sar     %cl, %eax
+       test    %eax, %eax
+       jz      L(return_null)
+
+       bsr     %eax, %eax
+       add     %rdi, %rax
+       add     %r8, %rax
+       ret
+
+       .p2align 4
+L(length_less16_part2_return):
+       bsr     %eax, %eax
+       lea     16(%rax, %rdi), %rax
+       ret
+
+END (memrchr)
+strong_alias (memrchr, __memrchr)
index 2a8a690..a8933fb 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2009, 2011 Free Software Foundation, Inc.
    Contributed by Ulrich Drepper <drepper@redhat.com>.
    This file is part of the GNU C Library.
 
@@ -29,11 +29,15 @@ ENTRY(rawmemchr)
        cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
        jne     1f
        call    __init_cpu_features
-1:     leaq    __rawmemchr_sse2(%rip), %rax
+1:     testl   $bit_Prefer_PMINUB_for_stringop, __cpu_features+FEATURE_OFFSET+index_Prefer_PMINUB_for_stringop(%rip)
+       jnz     2f
        testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
        jz      2f
        leaq    __rawmemchr_sse42(%rip), %rax
-2:     ret
+       ret
+2:     leaq    __rawmemchr_sse2(%rip), %rax
+       ret
+
 END(rawmemchr)
 strong_alias (rawmemchr, __rawmemchr)
 
index cfb4ceb..a68b52c 100644 (file)
@@ -1,5 +1,7 @@
-/* Copyright (C) 2009 Free Software Foundation, Inc.
-   Contributed by Ulrich Drepper <drepper@redhat.com>.
+/* fast SSE2 memchr with 64 byte loop and pmaxub instruction using
+
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by Intel Corporation.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
 
 #include <sysdep.h>
 
-
        .text
 ENTRY (rawmemchr)
-       movd    %esi, %xmm1
-       movq    %rdi, %rcx
+       movd    %rsi, %xmm1
+       mov     %rdi, %rcx
+
        punpcklbw %xmm1, %xmm1
-       andq    $~15, %rdi
        punpcklbw %xmm1, %xmm1
-       orl     $0xffffffff, %esi
-       movdqa  (%rdi), %xmm0
+
+       and     $63, %rcx
        pshufd  $0, %xmm1, %xmm1
-       subq    %rdi, %rcx
+
+       cmp     $48, %rcx
+       ja      L(crosscache)
+
+       movdqu  (%rdi), %xmm0
        pcmpeqb %xmm1, %xmm0
-       shl     %cl, %esi
-       pmovmskb %xmm0, %ecx
-       andl    %esi, %ecx
-       jnz     1f
+/* Check if there is a match.  */
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+
+       jnz     L(matches)
+       add     $16, %rdi
+       and     $-16, %rdi
+       jmp     L(loop_prolog)
+
+       .p2align 4
+L(crosscache):
+       and     $15, %rcx
+       and     $-16, %rdi
+       movdqa  (%rdi), %xmm0
 
-2:     movdqa  16(%rdi), %xmm0
-       leaq    16(%rdi), %rdi
        pcmpeqb %xmm1, %xmm0
-       pmovmskb %xmm0, %ecx
-       testl   %ecx, %ecx
-       jz      2b
+/* Check if there is a match.  */
+       pmovmskb %xmm0, %eax
+/* Remove the leading bytes.  */
+       sar     %cl, %eax
+       test    %eax, %eax
+       je      L(unaligned_no_match)
+/* Check which byte is a match.  */
+       bsf     %eax, %eax
 
-1:     bsfl    %ecx, %eax
-       addq    %rdi, %rax
+       add     %rdi, %rax
+       add     %rcx, %rax
        ret
+
+       .p2align 4
+L(unaligned_no_match):
+       add     $16, %rdi
+
+       .p2align 4
+L(loop_prolog):
+       movdqa  (%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches)
+
+       movdqa  16(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  32(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       movdqa  48(%rdi), %xmm4
+       pcmpeqb %xmm1, %xmm4
+       add     $64, %rdi
+       pmovmskb %xmm4, %eax
+       test    %eax, %eax
+       jnz     L(matches0)
+
+       test    $0x3f, %rdi
+       jz      L(align64_loop)
+
+       movdqa  (%rdi), %xmm0
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches)
+
+       movdqa  16(%rdi), %xmm2
+       pcmpeqb %xmm1, %xmm2
+       pmovmskb %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  32(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       movdqa  48(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+       pmovmskb %xmm3, %eax
+
+       add     $64, %rdi
+       test    %eax, %eax
+       jnz     L(matches0)
+
+       and     $-64, %rdi
+
+       .p2align 4
+L(align64_loop):
+       movdqa  (%rdi), %xmm0
+       movdqa  16(%rdi), %xmm2
+       movdqa  32(%rdi), %xmm3
+       movdqa  48(%rdi), %xmm4
+
+       pcmpeqb %xmm1, %xmm0
+       pcmpeqb %xmm1, %xmm2
+       pcmpeqb %xmm1, %xmm3
+       pcmpeqb %xmm1, %xmm4
+
+       pmaxub  %xmm0, %xmm3
+       pmaxub  %xmm2, %xmm4
+       pmaxub  %xmm3, %xmm4
+       pmovmskb %xmm4, %eax
+
+       add     $64, %rdi
+
+       test    %eax, %eax
+       jz      L(align64_loop)
+
+       sub     $64, %rdi
+
+       pmovmskb %xmm0, %eax
+       test    %eax, %eax
+       jnz     L(matches)
+
+       pmovmskb %xmm2, %eax
+       test    %eax, %eax
+       jnz     L(matches16)
+
+       movdqa  32(%rdi), %xmm3
+       pcmpeqb %xmm1, %xmm3
+
+       pcmpeqb 48(%rdi), %xmm1
+       pmovmskb %xmm3, %eax
+       test    %eax, %eax
+       jnz     L(matches32)
+
+       pmovmskb %xmm1, %eax
+       bsf     %eax, %eax
+       lea     48(%rdi, %rax), %rax
+       ret
+
+       .p2align 4
+L(matches0):
+       bsf     %eax, %eax
+       lea     -16(%rax, %rdi), %rax
+       ret
+
+       .p2align 4
+L(matches):
+       bsf     %eax, %eax
+       add     %rdi, %rax
+       ret
+
+       .p2align 4
+L(matches16):
+       bsf     %eax, %eax
+       lea     16(%rax, %rdi), %rax
+       ret
+
+       .p2align 4
+L(matches32):
+       bsf     %eax, %eax
+       lea     32(%rax, %rdi), %rax
+       ret
+
+       .p2align 4
+L(return_null):
+       xor     %rax, %rax
+       ret
+
 END (rawmemchr)
 
 strong_alias (rawmemchr, __rawmemchr)