Unroll the loop x86-64 SSE4.2 strlen.
[glibc.git] / sysdeps / x86_64 / multiarch / strlen.S
blobf9641131fa3e63ac4890e1b31899d10f53a2f47b
1 /* strlen(str) -- determine the length of the string STR.
2    Copyright (C) 2009 Free Software Foundation, Inc.
3    Contributed by Ulrich Drepper <drepper@redhat.com>.
4    This file is part of the GNU C Library.
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
21 #include <sysdep.h>
22 #include <init-arch.h>
25 /* Define multiple versions only for the definition in libc and for
26    the DSO.  In static binaries we need strlen before the initialization
27    happened.  */
28 #if defined SHARED && !defined NOT_IN_libc
29         .text
30 ENTRY(strlen)
31         .type   strlen, @gnu_indirect_function
32         cmpl    $0, __cpu_features+KIND_OFFSET(%rip)
33         jne     1f
34         call    __init_cpu_features
35 1:      leaq    __strlen_sse2(%rip), %rax
36         testl   $bit_SSE4_2, __cpu_features+CPUID_OFFSET+index_SSE4_2(%rip)
37         jz      2f
38         leaq    __strlen_sse42(%rip), %rax
39 2:      ret
40 END(strlen)
43         .section .text.sse4.2,"ax",@progbits
44         .align  16
45         .type   __strlen_sse42, @function
46 __strlen_sse42:
47         cfi_startproc
48         CALL_MCOUNT
49         pxor    %xmm1, %xmm1
50         movl    %edi, %ecx
51         movq    %rdi, %r8
52         andq    $~15, %rdi
53         xor     %edi, %ecx
54         pcmpeqb (%rdi), %xmm1
55         pmovmskb %xmm1, %edx
56         shrl    %cl, %edx
57         shll    %cl, %edx
58         andl    %edx, %edx
59         jnz     L(less16bytes)
60         pxor    %xmm1, %xmm1
62         .p2align 4
63 L(more64bytes_loop):
64         pcmpistri $0x08, 16(%rdi), %xmm1
65         jz      L(more32bytes)
67         pcmpistri $0x08, 32(%rdi), %xmm1
68         jz      L(more48bytes)
70         pcmpistri $0x08, 48(%rdi), %xmm1
71         jz      L(more64bytes)
73         add     $64, %rdi
74         pcmpistri $0x08, (%rdi), %xmm1
75         jnz     L(more64bytes_loop)
76         leaq    (%rdi,%rcx), %rax
77         subq    %r8, %rax
78         ret
80         .p2align 4
81 L(more32bytes):
82         leaq    16(%rdi,%rcx, 1), %rax
83         subq    %r8, %rax
84         ret
86         .p2align 4
87 L(more48bytes):
88         leaq    32(%rdi,%rcx, 1), %rax
89         subq    %r8, %rax
90         ret
92         .p2align 4
93 L(more64bytes):
94         leaq    48(%rdi,%rcx, 1), %rax
95         subq    %r8, %rax
96         ret
98         .p2align 4
99 L(less16bytes):
100         subq    %r8, %rdi
101         bsfl    %edx, %eax
102         addq    %rdi, %rax
103         ret
104         cfi_endproc
105         .size   __strlen_sse42, .-__strlen_sse42
108 # undef ENTRY
109 # define ENTRY(name) \
110         .type __strlen_sse2, @function; \
111         .align 16; \
112         __strlen_sse2: cfi_startproc; \
113         CALL_MCOUNT
114 # undef END
115 # define END(name) \
116         cfi_endproc; .size __strlen_sse2, .-__strlen_sse2
117 # undef libc_hidden_builtin_def
118 /* It doesn't make sense to send libc-internal strlen calls through a PLT.
119    The speedup we get from using SSE4.2 instruction is likely eaten away
120    by the indirect call in the PLT.  */
121 # define libc_hidden_builtin_def(name) \
122         .globl __GI_strlen; __GI_strlen = __strlen_sse2
123 #endif
125 #include "../strlen.S"