]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
S390: Implement mempcpy with help of memcpy. [BZ #19765]
authorStefan Liebler <stli@linux.vnet.ibm.com>
Tue, 24 May 2016 08:39:13 +0000 (10:39 +0200)
committerStefan Liebler <stli@linux.vnet.ibm.com>
Tue, 24 May 2016 08:39:13 +0000 (10:39 +0200)
There exist optimized memcpy functions on s390, but no optimized mempcpy.
This patch adds mempcpy entry points in memcpy.S files, which
use the memcpy implementation. Now mempcpy itself is also an IFUNC function
as memcpy is and the variants are listed in ifunc-impl-list.c.

The s390 string.h does not define _HAVE_STRING_ARCH_mempcpy.
Instead mempcpy string/string.h inlines memcpy() + n.
If n is constant and small enough, GCC emits instructions like mvi or mvc
and avoids the function call to memcpy.
If n is not constant, then memcpy is called and n is added afterwards.
If _HAVE_STRING_ARCH_mempcpy would be defined, mempcpy would be called in
every case.

According to PR70140 "Inefficient expansion of __builtin_mempcpy"
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70140) GCC should handle a
call to mempcpy in the same way as memcpy. Then either the mempcpy macro
in string/string.h has to be removed or _HAVE_STRING_ARCH_mempcpy has to
be defined for S390.

ChangeLog:

[BZ #19765]
* sysdeps/s390/mempcpy.S: New File.
* sysdeps/s390/multiarch/mempcpy.c: Likewise.
* sysdeps/s390/multiarch/Makefile (sysdep_routines): Add mempcpy.
* sysdeps/s390/multiarch/ifunc-impl-list.c (__libc_ifunc_impl_list):
Add mempcpy variants.
* sysdeps/s390/s390-32/memcpy.S: Add mempcpy entry point.
(memcpy): Adjust to be usable from mempcpy entry point.
(__memcpy_mvcle): Likewise.
* sysdeps/s390/s390-64/memcpy.S: Likewise.
* sysdeps/s390/s390-32/multiarch/memcpy-s390.S: Add entry points
____mempcpy_z196, ____mempcpy_z10 and add __GI_ symbols for mempcpy.
(__memcpy_z196): Adjust to be usable from mempcpy entry point.
(__memcpy_z10): Likewise.
* sysdeps/s390/s390-64/multiarch/memcpy-s390x.S: Likewise.

ChangeLog
sysdeps/s390/mempcpy.S [new file with mode: 0644]
sysdeps/s390/multiarch/Makefile
sysdeps/s390/multiarch/ifunc-impl-list.c
sysdeps/s390/multiarch/mempcpy.c [new file with mode: 0644]
sysdeps/s390/s390-32/memcpy.S
sysdeps/s390/s390-32/multiarch/memcpy-s390.S
sysdeps/s390/s390-64/memcpy.S
sysdeps/s390/s390-64/multiarch/memcpy-s390x.S

index 1054ca771fbc8136be60a28e98ac3f3c005e49b5..3345a1d3796f01eecba70e06a3af789042c903a8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2016-05-24  Stefan Liebler  <stli@linux.vnet.ibm.com>
+
+       [BZ #19765]
+       * sysdeps/s390/mempcpy.S: New File.
+       * sysdeps/s390/multiarch/mempcpy.c: Likewise.
+       * sysdeps/s390/multiarch/Makefile (sysdep_routines): Add mempcpy.
+       * sysdeps/s390/multiarch/ifunc-impl-list.c (__libc_ifunc_impl_list):
+       Add mempcpy variants.
+       * sysdeps/s390/s390-32/memcpy.S: Add mempcpy entry point.
+       (memcpy): Adjust to be usable from mempcpy entry point.
+       (__memcpy_mvcle): Likewise.
+       * sysdeps/s390/s390-64/memcpy.S: Likewise.
+       * sysdeps/s390/s390-32/multiarch/memcpy-s390.S: Add entry points
+       ____mempcpy_z196, ____mempcpy_z10 and add __GI_ symbols for mempcpy.
+       (__memcpy_z196): Adjust to be usable from mempcpy entry point.
+       (__memcpy_z10): Likewise.
+       * sysdeps/s390/s390-64/multiarch/memcpy-s390x.S: Likewise.
+
 2016-05-24  Stefan Liebler  <stli@linux.vnet.ibm.com>
 
        * sysdeps/s390/multiarch/ifunc-resolve.h (s390_libc_ifunc):
diff --git a/sysdeps/s390/mempcpy.S b/sysdeps/s390/mempcpy.S
new file mode 100644 (file)
index 0000000..c62074b
--- /dev/null
@@ -0,0 +1,19 @@
+/* CPU specific mempcpy without multiarch - 32/64 bit S/390 version.
+   Copyright (C) 2016 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/>.  */
+
+/* mempcpy is implemented in memcpy.S.  */
index 0805b079841d2528fb7ace55476ffe682ca782a6..89324cadc40dc11a288047c75b68ad7a26f008b8 100644 (file)
@@ -18,7 +18,8 @@ sysdep_routines += strlen strlen-vx strlen-c \
                   memchr memchr-vx \
                   rawmemchr rawmemchr-vx rawmemchr-c \
                   memccpy memccpy-vx memccpy-c \
-                  memrchr memrchr-vx memrchr-c
+                  memrchr memrchr-vx memrchr-c \
+                  mempcpy
 endif
 
 ifeq ($(subdir),wcsmbs)
index 62a435983ce9c99dd5d6dfcfafc6695a72735488..89898ecdd97c53cf5a0bbcbb6c246ac5c6f25a16 100644 (file)
@@ -69,6 +69,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
                              S390_IS_Z10 (stfle_bits), __memcpy_z10)
              IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_default))
 
+  IFUNC_IMPL (i, name, mempcpy,
+             IFUNC_IMPL_ADD (array, i, mempcpy,
+                             S390_IS_Z196 (stfle_bits), ____mempcpy_z196)
+             IFUNC_IMPL_ADD (array, i, mempcpy,
+                             S390_IS_Z10 (stfle_bits), ____mempcpy_z10)
+             IFUNC_IMPL_ADD (array, i, mempcpy, 1, ____mempcpy_default))
+
 #endif /* SHARED */
 
 #ifdef HAVE_S390_VX_ASM_SUPPORT
diff --git a/sysdeps/s390/multiarch/mempcpy.c b/sysdeps/s390/multiarch/mempcpy.c
new file mode 100644 (file)
index 0000000..34d8329
--- /dev/null
@@ -0,0 +1,26 @@
+/* Multiple versions of mempcpy.
+   Copyright (C) 2016 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/>.  */
+
+
+#if defined SHARED && IS_IN (libc)
+# include <ifunc-resolve.h>
+s390_libc_ifunc (__mempcpy)
+
+__asm__ (".weak mempcpy\n\t"
+        ".set mempcpy,__mempcpy\n\t");
+#endif
index 2ac51ab62ed064c581a46137c7f1a3e4ca90677c..6be5104b68841825e016ea4caacdde3596f3f346 100644 (file)
      %r3 = address of source memory area
      %r4 = number of bytes to copy.  */
 
-#ifdef USE_MULTIARCH
-ENTRY(__memcpy_default)
-#else
-ENTRY(memcpy)
+       .text
+ENTRY(__mempcpy)
+       .machine "g5"
+       lr      %r1,%r2             # Use as dest
+       la      %r2,0(%r4,%r2)      # Return dest + n
+       j       .L_G5_start
+END(__mempcpy)
+#ifndef USE_MULTIARCH
+libc_hidden_def (__mempcpy)
+weak_alias (__mempcpy, mempcpy)
+libc_hidden_builtin_def (mempcpy)
 #endif
+
+ENTRY(memcpy)
        .machine "g5"
+       lr      %r1,%r2             # r1: Use as dest ; r2: Return dest
+.L_G5_start:
        st      %r13,52(%r15)
        .cfi_offset 13, -44
        basr    %r13,0
@@ -41,14 +52,13 @@ ENTRY(memcpy)
        lr      %r5,%r4
        srl     %r5,8
        ltr     %r5,%r5
-       lr      %r1,%r2
        jne     .L_G5_13
        ex      %r4,.L_G5_17-.L_G5_16(%r13)
 .L_G5_4:
        l       %r13,52(%r15)
        br      %r14
 .L_G5_13:
-       chi     %r5,4096             # Switch to mvcle for copies >1MB
+       chi     %r5,4096            # Switch to mvcle for copies >1MB
        jh      __memcpy_mvcle
 .L_G5_12:
        mvc     0(256,%r1),0(%r3)
@@ -59,24 +69,24 @@ ENTRY(memcpy)
        j       .L_G5_4
 .L_G5_17:
        mvc     0(1,%r1),0(%r3)
-#ifdef USE_MULTIARCH
-END(__memcpy_default)
-#else
 END(memcpy)
+#ifndef USE_MULTIARCH
 libc_hidden_builtin_def (memcpy)
 #endif
 
 ENTRY(__memcpy_mvcle)
-       # Using as standalone function will result in unexpected
-       # results since the length field is incremented by 1 in order to
-       # compensate the changes already done in the functions above.
-       ahi     %r4,1               # length + 1
-       lr      %r5,%r4             # source length
-       lr      %r4,%r3             # source address
-       lr      %r3,%r5             # destination length = source length
+       # Using as standalone function will result in unexpected
+       # results since the length field is incremented by 1 in order to
+       # compensate the changes already done in the functions above.
+       lr      %r0,%r2             # backup return dest [ + n ]
+       ahi     %r4,1               # length + 1
+       lr      %r5,%r4             # source length
+       lr      %r4,%r3             # source address
+       lr      %r2,%r1             # destination address
+       lr      %r3,%r5             # destination length = source length
 .L_MVCLE_1:
-       mvcle   %r2,%r4,0           # thats it, MVCLE is your friend
-       jo      .L_MVCLE_1
-       lr      %r2,%r1             # return destination address
-       br      %r14
+       mvcle   %r2,%r4,0           # thats it, MVCLE is your friend
+       jo      .L_MVCLE_1
+       lr      %r2,%r0             # return destination address
+       br      %r14
 END(__memcpy_mvcle)
index 92ffaea5edcc8c9438b8a93b3496a9bb6dc069b3..297a8943b1f8dde09dc5ce4e02b324cdc6f49a09 100644 (file)
 
 #if defined SHARED && IS_IN (libc)
 
+ENTRY(____mempcpy_z196)
+       .machine "z196"
+       .machinemode "zarch_nohighgprs"
+       lr      %r1,%r2         # Use as dest
+       la      %r2,0(%r4,%r2)  # Return dest + n
+       j       .L_Z196_start
+END(____mempcpy_z196)
+
 ENTRY(__memcpy_z196)
        .machine "z196"
        .machinemode "zarch_nohighgprs"
+       lr      %r1,%r2         # r1: Use as dest ; r2: Return dest
+.L_Z196_start:
        llgfr   %r4,%r4
        ltgr    %r4,%r4
        je      .L_Z196_4
        aghi    %r4,-1
-       lr      %r1,%r2
        srlg    %r5,%r4,8
        ltgr    %r5,%r5
        jne     .L_Z196_5
@@ -60,13 +69,22 @@ ENTRY(__memcpy_z196)
        mvc     0(1,%r1),0(%r3)
 END(__memcpy_z196)
 
+ENTRY(____mempcpy_z10)
+       .machine "z10"
+       .machinemode "zarch_nohighgprs"
+       lr      %r1,%r2         # Use as dest
+       la      %r2,0(%r4,%r2)  # Return dest + n
+       j       .L_Z10_start
+END(____mempcpy_z10)
+
 ENTRY(__memcpy_z10)
        .machine "z10"
        .machinemode "zarch_nohighgprs"
+       lr      %r1,%r2         # r1: Use as dest ; r2: Return dest
+.L_Z10_start:
        llgfr   %r4,%r4
        cgije   %r4,0,.L_Z10_4
        aghi    %r4,-1
-       lr      %r1,%r2
        srlg    %r5,%r4,8
        cgijlh  %r5,0,.L_Z10_13
 .L_Z10_3:
@@ -88,14 +106,23 @@ ENTRY(__memcpy_z10)
        mvc     0(1,%r1),0(%r3)
 END(__memcpy_z10)
 
+# define __mempcpy ____mempcpy_default
 #endif /* SHARED && IS_IN (libc) */
 
+#define memcpy __memcpy_default
 #include "../memcpy.S"
+#undef memcpy
 
 #if defined SHARED && IS_IN (libc)
 .globl   __GI_memcpy
 .set     __GI_memcpy,__memcpy_default
+.globl   __GI_mempcpy
+.set     __GI_mempcpy,____mempcpy_default
+.globl   __GI___mempcpy
+.set     __GI___mempcpy,____mempcpy_default
 #else
 .globl   memcpy
 .set     memcpy,__memcpy_default
+.weak    mempcpy
+.set     mempcpy,__mempcpy
 #endif
index 9d60a14cccdbee76f85acfb6a5479807fa00488e..e3ace0c87b634cb4561a4d059db36eb2dcd1e5db 100644 (file)
 
 
        .text
+ENTRY(__mempcpy)
+       .machine "z900"
+       lgr     %r1,%r2             # Use as dest
+       la      %r2,0(%r4,%r2)      # Return dest + n
+       j       .L_Z900_start
+END(__mempcpy)
+#ifndef USE_MULTIARCH
+libc_hidden_def (__mempcpy)
+weak_alias (__mempcpy, mempcpy)
+libc_hidden_builtin_def (mempcpy)
+#endif
 
-#ifdef USE_MULTIARCH
-ENTRY(__memcpy_default)
-#else
 ENTRY(memcpy)
-#endif
        .machine "z900"
+       lgr     %r1,%r2             # r1: Use as dest ; r2: Return dest
+.L_Z900_start:
        ltgr    %r4,%r4
        je      .L_Z900_4
        aghi    %r4,-1
        srlg    %r5,%r4,8
        ltgr    %r5,%r5
-       lgr     %r1,%r2
        jne     .L_Z900_13
 .L_Z900_3:
        larl    %r5,.L_Z900_15
@@ -57,25 +65,24 @@ ENTRY(memcpy)
        j       .L_Z900_3
 .L_Z900_15:
        mvc     0(1,%r1),0(%r3)
-
-#ifdef USE_MULTIARCH
-END(__memcpy_default)
-#else
 END(memcpy)
+#ifndef USE_MULTIARCH
 libc_hidden_builtin_def (memcpy)
 #endif
 
 ENTRY(__memcpy_mvcle)
-       # Using as standalone function will result in unexpected
-       # results since the length field is incremented by 1 in order to
-       # compensate the changes already done in the functions above.
-       aghi    %r4,1               # length + 1
-       lgr     %r5,%r4             # source length
-       lgr     %r4,%r3             # source address
-       lgr     %r3,%r5             # destination length = source length
+       # Using as standalone function will result in unexpected
+       # results since the length field is incremented by 1 in order to
+       # compensate the changes already done in the functions above.
+       lgr     %r0,%r2             # backup return dest [ + n ]
+       aghi    %r4,1               # length + 1
+       lgr     %r5,%r4             # source length
+       lgr     %r4,%r3             # source address
+       lgr     %r2,%r1             # destination address
+       lgr     %r3,%r5             # destination length = source length
 .L_MVCLE_1:
-       mvcle   %r2,%r4,0           # thats it, MVCLE is your friend
-       jo      .L_MVCLE_1
-       lgr     %r2,%r1             # return destination address
-       br      %r14
+       mvcle   %r2,%r4,0           # thats it, MVCLE is your friend
+       jo      .L_MVCLE_1
+       lgr     %r2,%r0             # return destination address
+       br      %r14
 END(__memcpy_mvcle)
index 8f54526b76f458d1cde8822c7c0f16df8f06d65e..0f5a36edd1e2e19adefdb125f855d4b118ef0610 100644 (file)
 
 #if defined SHARED && IS_IN (libc)
 
+ENTRY(____mempcpy_z196)
+       .machine "z196"
+       lgr     %r1,%r2         # Use as dest
+       la      %r2,0(%r4,%r2)  # Return dest + n
+       j       .L_Z196_start
+END(____mempcpy_z196)
+
 ENTRY(__memcpy_z196)
        .machine "z196"
+       lgr     %r1,%r2         # r1: Use as dest ; r2: Return dest
+.L_Z196_start:
        ltgr    %r4,%r4
        je      .L_Z196_4
        aghi    %r4,-1
-       lgr     %r1,%r2
        srlg    %r5,%r4,8
        ltgr    %r5,%r5
        jne     .L_Z196_5
@@ -58,11 +66,19 @@ ENTRY(__memcpy_z196)
        mvc     0(1,%r1),0(%r3)
 END(__memcpy_z196)
 
+ENTRY(____mempcpy_z10)
+       .machine "z10"
+       lgr     %r1,%r2         # Use as dest
+       la      %r2,0(%r4,%r2)  # Return dest + n
+       j       .L_Z10_start
+END(____mempcpy_z10)
+
 ENTRY(__memcpy_z10)
        .machine "z10"
+       lgr     %r1,%r2         # r1: Use as dest ; r2: Return dest
+.L_Z10_start:
        cgije   %r4,0,.L_Z10_4
        aghi    %r4,-1
-       lgr     %r1,%r2
        srlg    %r5,%r4,8
        cgijlh  %r5,0,.L_Z10_13
 .L_Z10_3:
@@ -84,14 +100,23 @@ ENTRY(__memcpy_z10)
        mvc     0(1,%r1),0(%r3)
 END(__memcpy_z10)
 
+# define __mempcpy ____mempcpy_default
 #endif /* SHARED && IS_IN (libc) */
 
+#define memcpy __memcpy_default
 #include "../memcpy.S"
+#undef memcpy
 
 #if defined SHARED && IS_IN (libc)
 .globl   __GI_memcpy
 .set     __GI_memcpy,__memcpy_default
+.globl   __GI_mempcpy
+.set     __GI_mempcpy,____mempcpy_default
+.globl   __GI___mempcpy
+.set     __GI___mempcpy,____mempcpy_default
 #else
 .globl   memcpy
 .set     memcpy,__memcpy_default
+.weak    mempcpy
+.set     mempcpy,__mempcpy
 #endif