From patchwork Fri Jun 26 11:51:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Stefan Liebler X-Patchwork-Id: 7374 Received: (qmail 26663 invoked by alias); 26 Jun 2015 11:52:58 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 22655 invoked by uid 89); 26 Jun 2015 11:52:23 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: e06smtp12.uk.ibm.com X-MailFrom: stli@linux.vnet.ibm.com X-RcptTo: libc-alpha@sourceware.org From: Stefan Liebler To: libc-alpha@sourceware.org Cc: Stefan Liebler Subject: [PATCH 24/27] S390: Optimize memccpy. Date: Fri, 26 Jun 2015 13:51:49 +0200 Message-Id: <1435319512-22245-25-git-send-email-stli@linux.vnet.ibm.com> In-Reply-To: <1435319512-22245-1-git-send-email-stli@linux.vnet.ibm.com> References: <1435319512-22245-1-git-send-email-stli@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15062611-0009-0000-0000-000004A408F1 This patch provides optimized versions of memccpy with the z13 vector instructions. ChangeLog: * sysdeps/s390/multiarch/memccpy-c.c: New File. * sysdeps/s390/multiarch/memccpy-vx.S: Likewise. * sysdeps/s390/multiarch/memccpy.c: Likewise. * sysdeps/s390/multiarch/Makefile (sysdep_routines): Add memccpy functions. * sysdeps/s390/multiarch/ifunc-impl-list-common.c (__libc_ifunc_impl_list_common): Add ifunc test for memccpy. * string/memccpy.c: Use MEMCCPY if defined. --- string/memccpy.c | 4 + sysdeps/s390/multiarch/Makefile | 3 +- sysdeps/s390/multiarch/ifunc-impl-list.c | 2 + sysdeps/s390/multiarch/memccpy-c.c | 25 +++++ sysdeps/s390/multiarch/memccpy-vx.S | 156 +++++++++++++++++++++++++++++++ sysdeps/s390/multiarch/memccpy.c | 28 ++++++ 6 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 sysdeps/s390/multiarch/memccpy-c.c create mode 100644 sysdeps/s390/multiarch/memccpy-vx.S create mode 100644 sysdeps/s390/multiarch/memccpy.c diff --git a/string/memccpy.c b/string/memccpy.c index d9ed697..3f018f0 100644 --- a/string/memccpy.c +++ b/string/memccpy.c @@ -20,6 +20,10 @@ #undef __memccpy #undef memccpy +#ifdef MEMCCPY +# define __memccpy MEMCCPY +#endif + /* Copy no more than N bytes of SRC to DEST, stopping when C is found. Return the position in DEST one byte past where C was copied, or NULL if C was not found in the first N bytes of SRC. */ diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile index 4a04c34..87dff0f 100644 --- a/sysdeps/s390/multiarch/Makefile +++ b/sysdeps/s390/multiarch/Makefile @@ -16,7 +16,8 @@ sysdep_routines += strlen strlen-vx strlen-c \ strpbrk strpbrk-vx strpbrk-c \ strcspn strcspn-vx strcspn-c \ memchr memchr-vx \ - rawmemchr rawmemchr-vx rawmemchr-c + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c endif ifeq ($(subdir),wcsmbs) diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c index d4c7c0d..c90fb6b 100644 --- a/sysdeps/s390/multiarch/ifunc-impl-list.c +++ b/sysdeps/s390/multiarch/ifunc-impl-list.c @@ -131,6 +131,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, IFUNC_VX_IMPL (wmemchr); IFUNC_VX_IMPL (rawmemchr); + IFUNC_VX_IMPL (memccpy); + #endif /* HAVE_S390_VX_ASM_SUPPORT */ return i; diff --git a/sysdeps/s390/multiarch/memccpy-c.c b/sysdeps/s390/multiarch/memccpy-c.c new file mode 100644 index 0000000..d034d23 --- /dev/null +++ b/sysdeps/s390/multiarch/memccpy-c.c @@ -0,0 +1,25 @@ +/* Default memccpy implementation for S/390. + 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 + . */ + +#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# define MEMCCPY __memccpy_c + +# include +extern __typeof (__memccpy) __memccpy_c; +# include +#endif diff --git a/sysdeps/s390/multiarch/memccpy-vx.S b/sysdeps/s390/multiarch/memccpy-vx.S new file mode 100644 index 0000000..6e9eddc --- /dev/null +++ b/sysdeps/s390/multiarch/memccpy-vx.S @@ -0,0 +1,156 @@ +/* Vector optimized 32/64 bit S/390 version of memccpy. + 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 + . */ + +#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) + +# include "sysdep.h" +# include "asm-syntax.h" + + .text + +/* void *memccpy (void * dest, const void *src, int c, size_t n) + Copies no more than n bytes from src to dest, + stopping when the character c is found + and returns pointer next to c in dest or null if c not found. + + Register usage: + -r0=tmp + -r1=tmp + -r2=dest + -r3=src + -r4=c + -r5=n + -r6=current_len + -v16=part of s + -v17=index of found c + -v18=c replicated + -v19=part #2 of s + -v31=save area for r6 +*/ +ENTRY(__memccpy_vx) + .machine "z13" + .machinemode "zarch_nohighgprs" + +# if !defined __s390x__ + llgfr %r5,%r5 +# endif /* !defined __s390x__ */ + + vlvgp %v31,%r6,%r7 /* Save registers. */ + clgije %r5,0,.Lnf_end /* If len == 0 then exit. */ + vlvgb %v18,%r4,0 /* Generate vector which elements are all c. + if c > 255, c will be truncated. */ + vrepb %v18,%v18,0 + lghi %r6,0 /* current_len = 0. */ + + + /* Align s to 16byte. */ + risbg %r1,%r3,60,128+63,0 /* Test if s is aligned and + %r1 = bits 60-63 'and' 15. */ + je .Lpreloop1 /* If s is aligned, loop aligned. */ + lghi %r0,15 + slr %r0,%r1 /* Compute highest index to load (15-x). */ + vll %v16,%r0,0(%r3) /* Load up to 16 byte boundary (vll needs + highest index, remaining bytes are 0). */ + ahi %r0,1 /* Work with loaded byte count. */ + clgrj %r5,%r0,12,.Lremaining_v16 /* If maxlen <= loaded-bytes + -> Process remaining. */ + vfeebs %v17,%v16,%v18 /* Find c. */ + vlgvb %r1,%v17,7 /* Load byte index of c. */ + clgrjl %r1,%r0,.Lfound_v16 /* Found c is within loaded bytes. */ + lgr %r6,%r0 /* c not found + -> First %r0 bytes are already processed. */ + ahi %r0,-1 /* vstl needs highest index. */ + vstl %v16,%r0,0(%r2) /* Store prcessed bytes */ + +.Lpreloop1: + /* Now we are 16byte aligned, so we can load + a full vreg without page fault. */ + vl %v16,0(%r6,%r3) /* Load s. */ + clgijl %r5,17,.Lremaining_v16 /* If n <= 16, + process remaining bytes. */ + lgr %r7,%r5 + slgfi %r7,16 /* border_len = n - 16. */ + j .Lloop1 + +.Lloop2: + vl %v16,16(%r6,%r3) + vst %v19,0(%r6,%r2) + aghi %r6,16 + +.Lloop1: + clgrjhe %r6,%r7,.Lremaining_v16 /* If current_len >= border + then process remaining bytes. */ + vfeebs %v17,%v16,%v18 /* Find c. */ + jl .Lfound_v16 /* Jump away if c was found. */ + vl %v19,16(%r6,%r3) /* Load next s part. */ + vst %v16,0(%r6,%r2) /* Store previous part without c. */ + aghi %r6,16 + + clgrjhe %r6,%r7,.Lremaining_v19 + vfeebs %v17,%v19,%v18 + jl .Lfound_v19 + vl %v16,16(%r6,%r3) + vst %v19,0(%r6,%r2) + aghi %r6,16 + + clgrjhe %r6,%r7,.Lremaining_v16 + vfeebs %v17,%v16,%v18 + jl .Lfound_v16 + vl %v19,16(%r6,%r3) + vst %v16,0(%r6,%r2) + aghi %r6,16 + + clgrjhe %r6,%r7,.Lremaining_v19 + vfeebs %v17,%v19,%v18 + jo .Lloop2 + +.Lfound_v19: + vlr %v16,%v19 +.Lfound_v16: + /* v16 contains c. Store remaining bytes to c. currlen hasn´t + reached border, thus checking for maxlen is not needed! */ + vlgvb %r1,%v17,7 /* Load byte index of c. */ + la %r2,0(%r6,%r2) /* vstl has no support for index-register. */ +.Lfound_v16_store: + vstl %v16,%r1,0(%r2) /* Copy bytes including c. */ + la %r2,1(%r1,%r2) /* Return pointer next to c in dest. */ + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + br %r14 + +.Lremaining_v19: + vlr %v16,%v19 +.Lremaining_v16: + /* v16 contains the remaining bytes [1...16]. + Check and store remaining bytes. */ + vfeebs %v17,%v16,%v18 + slgrk %r7,%r5,%r6 /* Remaining bytes = maxlen - current_len. */ + aghi %r7,-1 /* vstl needs highest index. */ + la %r2,0(%r6,%r2) /* vstl has no index register. */ + vlgvb %r1,%v17,7 /* Load index of c or 16 if not found. */ + /* c in remaining bytes? -> Jump away (c-index <= max-index) */ + clrjle %r1,%r7,.Lfound_v16_store + vstl %v16,%r7,0(%r2) /* Store remaining bytes. */ + +.Lnf_end: + vlgvg %r6,%v31,0 + vlgvg %r7,%v31,1 + lghi %r2,0 /* Return null. */ + br %r14 +END(__memccpy_vx) +#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ diff --git a/sysdeps/s390/multiarch/memccpy.c b/sysdeps/s390/multiarch/memccpy.c new file mode 100644 index 0000000..c5a9628 --- /dev/null +++ b/sysdeps/s390/multiarch/memccpy.c @@ -0,0 +1,28 @@ +/* Multiple versions of memccpy. + 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 + . */ + +#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +# include +# include + +s390_vx_libc_ifunc (__memccpy) +weak_alias (__memccpy, memccpy) + +#else +# include +#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */