[2/2] Remove ancient GCC string inlines

Message ID 000b01d10518$befeab10$3cfc0130$@com
State Superseded
Headers

Commit Message

Wilco Dijkstra Oct. 12, 2015, 6:06 p.m. UTC
  > Joseph Myers wrote:
> On Mon, 12 Oct 2015, Wilco Dijkstra wrote:
> 
> > ../sysdeps/unix/sysv/linux/i386/sysdep.h:409:12: error: '__NR_set_thread_area' undeclared
> (first use
> > in this function)

> So, you need to find out why your compiler installation isn't finding an
> appropriate asm/unistd.h, and fix that problem.

It seems that the multilibs weren't properly installed somehow. With these it suddenly
started to work! Strange that configure doesn't check you've got the right headers and
report a meaningful error...

Sysdeps/string-inlines.c is indeed built on x86, so I have updated my patch to avoid
namespace issues on x86. The fails are (same set as before my patch):

build/glibc_x86/tests.sum:FAIL: c++-types-check
build/glibc_x86/tests.sum:FAIL: grp/testgrp
build/glibc_x86/tests.sum:FAIL: localedata/bug-iconv-trans
build/glibc_x86/tests.sum:FAIL: localedata/tst-wctype
build/glibc_x86/tests.sum:FAIL: localedata/tst_mblen
build/glibc_x86/tests.sum:FAIL: localedata/tst_mbrlen
build/glibc_x86/tests.sum:FAIL: localedata/tst_mbrtowc
build/glibc_x86/tests.sum:FAIL: localedata/tst_mbsrtowcs
build/glibc_x86/tests.sum:FAIL: localedata/tst_mbstowcs
build/glibc_x86/tests.sum:FAIL: localedata/tst_mbtowc
build/glibc_x86/tests.sum:FAIL: localedata/tst_swscanf
build/glibc_x86/tests.sum:FAIL: localedata/tst_wcrtomb
build/glibc_x86/tests.sum:FAIL: localedata/tst_wcsrtombs
build/glibc_x86/tests.sum:FAIL: localedata/tst_wcstombs
build/glibc_x86/tests.sum:FAIL: localedata/tst_wctob
build/glibc_x86/tests.sum:FAIL: localedata/tst_wctomb
build/glibc_x86/tests.sum:FAIL: posix/globtest

ChangeLog:
2015-10-12  Wilco Dijkstra  wdijkstr@arm.com

	* string/string-inlines.c (__STRING2_COPY_TYPE): Add, moved from string2.h.
	(__mempcpy_small): Likewise.
	(__strcpy_small): Likewise.
	(__stpcpy_small): Likewise.
	* string/bits/string2.h (__STRING2_COPY_TYPE): Remove.
	(__mempcpy_small): Remove.
	(__strcpy_small): Remove.
	(__stpcpy_small): Remove.
	* sysdeps/i386/string-inlines.c: Include string/string-inlines.c.
---
 string/bits/string2.h         | 372 ------------------------------------------
 string/string-inlines.c       | 346 +++++++++++++++++++++++++++++++++++++++
 sysdeps/i386/string-inlines.c |  14 +-
 3 files changed, 347 insertions(+), 385 deletions(-)
  

Comments

Joseph Myers Oct. 12, 2015, 6:10 p.m. UTC | #1
On Mon, 12 Oct 2015, Wilco Dijkstra wrote:

> 	* string/string-inlines.c (__STRING2_COPY_TYPE): Add, moved from string2.h.

> 	* string/bits/string2.h (__STRING2_COPY_TYPE): Remove.

Does this move of __STRING2_COPY_TYPE mean the patch fixes [BZ #18712]?
  
Wilco Dijkstra Oct. 13, 2015, 3:08 p.m. UTC | #2
> Joseph Myers wrote:
> On Mon, 12 Oct 2015, Wilco Dijkstra wrote:
> 
> > 	* string/string-inlines.c (__STRING2_COPY_TYPE): Add, moved from string2.h.
> 
> > 	* string/bits/string2.h (__STRING2_COPY_TYPE): Remove.
> 
> Does this move of __STRING2_COPY_TYPE mean the patch fixes [BZ #18712]?

It does indeed. It also ensures that future changes of _STRING_ARCH_unaligned no
longer cause backwards compatibility issues due to the inline functions using
different ABIs depending on the _STRING_ARCH_unaligned setting (I didn't find a
BZ entry for this one).

Wilco
  
Joseph Myers Oct. 13, 2015, 3:21 p.m. UTC | #3
On Tue, 13 Oct 2015, Wilco Dijkstra wrote:

> It does indeed. It also ensures that future changes of 
> _STRING_ARCH_unaligned no longer cause backwards compatibility issues 
> due to the inline functions using different ABIs depending on the 
> _STRING_ARCH_unaligned setting (I didn't find a BZ entry for this one).

Please explain further.  ABI issues should only ever apply for out-of-line 
copies of inline functions, and we need to support old executables and 
shared libraries (as opposed to old .o / .a files) indefinitely.

Thus, if _STRING_ARCH_unaligned affects the ABI for any of the functions 
moved out of line, we need to ensure that they are built with the ABI 
applicable for the glibc versions in which the inlines were present, not 
one relating to a future different definition of _STRING_ARCH_unaligned.  
If changes to _STRING_ARCH_unaligned are contemplated, we may need to have 
a separate ABI macro for use only for building these out-of-line 
functions.  And we need to understand whether any architecture has changed 
its definition of _STRING_ARCH_unaligned during the lifetime of these 
inlines, so that we can determine the most compatible definition of the 
new macro for such an architecture (probably the one contemporary with GCC 
versions for which these inlines were relevant, rather than any more 
recent optimized value of that macro).

One issue of concern would be that 
sysdeps/m68k/m680x0/m68020/bits/string.h defines _STRING_ARCH_unaligned to 
1, but the ABI isn't meant to differ depending on whether the m68020/ 
directory is or is not used (there's only one classic m68k ABI listed at 
<https://sourceware.org/glibc/wiki/ABIList>).
  
Wilco Dijkstra Oct. 13, 2015, 4:33 p.m. UTC | #4
> Joseph Myers wrote:
> On Tue, 13 Oct 2015, Wilco Dijkstra wrote:
> 
> > It does indeed. It also ensures that future changes of
> > _STRING_ARCH_unaligned no longer cause backwards compatibility issues
> > due to the inline functions using different ABIs depending on the
> > _STRING_ARCH_unaligned setting (I didn't find a BZ entry for this one).
> 
> Please explain further.  ABI issues should only ever apply for out-of-line
> copies of inline functions, and we need to support old executables and
> shared libraries (as opposed to old .o / .a files) indefinitely.
> 
> Thus, if _STRING_ARCH_unaligned affects the ABI for any of the functions
> moved out of line, we need to ensure that they are built with the ABI
> applicable for the glibc versions in which the inlines were present, not
> one relating to a future different definition of _STRING_ARCH_unaligned.

Correct. The out-of-line copies of the inlines have an ABI that changes with 
the _STRING_ARCH_unaligned setting, so they should use a different define
that cannot be changed after the initial GLIBC version for a new target.

> If changes to _STRING_ARCH_unaligned are contemplated, we may need to have
> a separate ABI macro for use only for building these out-of-line
> functions.  And we need to understand whether any architecture has changed
> its definition of _STRING_ARCH_unaligned during the lifetime of these
> inlines, so that we can determine the most compatible definition of the
> new macro for such an architecture (probably the one contemporary with GCC
> versions for which these inlines were relevant, rather than any more
> recent optimized value of that macro).

A quick search in the ChangeLog/git log doesn't show up any recent changes. 
Changing it for AArch64 is safe as there isn't an old enough compiler that
could have generated out of line copies of these inline functions.

> One issue of concern would be that
> sysdeps/m68k/m680x0/m68020/bits/string.h defines _STRING_ARCH_unaligned to
> 1, but the ABI isn't meant to differ depending on whether the m68020/
> directory is or is not used (there's only one classic m68k ABI listed at
> <https://sourceware.org/glibc/wiki/ABIList>).

That looks like an actual ABI incompatibility that we cannot fix 
(68000 binaries may not work with a GLIBC built for 68020).

Wilco
  
Andreas Schwab Oct. 13, 2015, 5:23 p.m. UTC | #5
Joseph Myers <joseph@codesourcery.com> writes:

> One issue of concern would be that 
> sysdeps/m68k/m680x0/m68020/bits/string.h defines _STRING_ARCH_unaligned to 
> 1, but the ABI isn't meant to differ depending on whether the m68020/ 
> directory is or is not used (there's only one classic m68k ABI listed at 
> <https://sourceware.org/glibc/wiki/ABIList>).

m68k-linux doesn't support pre-68020.

Andreas.
  
Joseph Myers Oct. 13, 2015, 5:29 p.m. UTC | #6
On Tue, 13 Oct 2015, Andreas Schwab wrote:

> Joseph Myers <joseph@codesourcery.com> writes:
> 
> > One issue of concern would be that 
> > sysdeps/m68k/m680x0/m68020/bits/string.h defines _STRING_ARCH_unaligned to 
> > 1, but the ABI isn't meant to differ depending on whether the m68020/ 
> > directory is or is not used (there's only one classic m68k ABI listed at 
> > <https://sourceware.org/glibc/wiki/ABIList>).
> 
> m68k-linux doesn't support pre-68020.

In that case I suggest simplifying the sysdeps directory structure 
(removing the m68020/ directory level, moving its contents directly into 
m680x0/), much like HJ merged i486 directories into the i386 directories.
  

Patch

diff --git a/string/bits/string2.h b/string/bits/string2.h
index bd8c404..f8ea1f9 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -51,20 +51,6 @@ 
 # include <endian.h>
 # include <bits/types.h>
 
-#else
-/* These are a few types we need for the optimizations if we cannot
-   use unaligned memory accesses.  */
-# define __STRING2_COPY_TYPE(N) \
-  typedef struct { unsigned char __arr[N]; }				      \
-    __attribute__ ((__packed__)) __STRING2_COPY_ARR##N
-__STRING2_COPY_TYPE (2);
-__STRING2_COPY_TYPE (3);
-__STRING2_COPY_TYPE (4);
-__STRING2_COPY_TYPE (5);
-__STRING2_COPY_TYPE (6);
-__STRING2_COPY_TYPE (7);
-__STRING2_COPY_TYPE (8);
-# undef __STRING2_COPY_TYPE
 #endif
 
 /* Dereferencing a pointer arg to run sizeof on it fails for the void
@@ -97,135 +83,10 @@  __STRING2_COPY_TYPE (8);
    we have to use the name `__mempcpy'.  */
 #   define mempcpy(dest, src, n) __mempcpy (dest, src, n)
 #  endif
-
-#  if defined _FORCE_INLINES
-#   if _STRING_ARCH_unaligned
-__STRING_INLINE void *__mempcpy_small (void *, char, char, char, char,
-				       __uint16_t, __uint16_t, __uint32_t,
-				       __uint32_t, size_t);
-__STRING_INLINE void *
-__mempcpy_small (void *__dest1,
-		 char __src0_1, char __src2_1, char __src4_1, char __src6_1,
-		 __uint16_t __src0_2, __uint16_t __src4_2,
-		 __uint32_t __src0_4, __uint32_t __src4_4,
-		 size_t __srclen)
-{
-  union {
-    __uint32_t __ui;
-    __uint16_t __usi;
-    unsigned char __uc;
-    unsigned char __c;
-  } *__u = __dest1;
-  switch ((unsigned int) __srclen)
-    {
-    case 1:
-      __u->__c = __src0_1;
-      __u = __extension__ ((void *) __u + 1);
-      break;
-    case 2:
-      __u->__usi = __src0_2;
-      __u = __extension__ ((void *) __u + 2);
-      break;
-    case 3:
-      __u->__usi = __src0_2;
-      __u = __extension__ ((void *) __u + 2);
-      __u->__c = __src2_1;
-      __u = __extension__ ((void *) __u + 1);
-      break;
-    case 4:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      break;
-    case 5:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__c = __src4_1;
-      __u = __extension__ ((void *) __u + 1);
-      break;
-    case 6:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__usi = __src4_2;
-      __u = __extension__ ((void *) __u + 2);
-      break;
-    case 7:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__usi = __src4_2;
-      __u = __extension__ ((void *) __u + 2);
-      __u->__c = __src6_1;
-      __u = __extension__ ((void *) __u + 1);
-      break;
-    case 8:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__ui = __src4_4;
-      __u = __extension__ ((void *) __u + 4);
-      break;
-    }
-  return (void *) __u;
-}
-#   else
-__STRING_INLINE void *__mempcpy_small (void *, char, __STRING2_COPY_ARR2,
-				       __STRING2_COPY_ARR3,
-				       __STRING2_COPY_ARR4,
-				       __STRING2_COPY_ARR5,
-				       __STRING2_COPY_ARR6,
-				       __STRING2_COPY_ARR7,
-				       __STRING2_COPY_ARR8, size_t);
-__STRING_INLINE void *
-__mempcpy_small (void *__dest, char __src1,
-		 __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
-		 __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
-		 __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
-		 __STRING2_COPY_ARR8 __src8, size_t __srclen)
-{
-  union {
-    char __c;
-    __STRING2_COPY_ARR2 __sca2;
-    __STRING2_COPY_ARR3 __sca3;
-    __STRING2_COPY_ARR4 __sca4;
-    __STRING2_COPY_ARR5 __sca5;
-    __STRING2_COPY_ARR6 __sca6;
-    __STRING2_COPY_ARR7 __sca7;
-    __STRING2_COPY_ARR8 __sca8;
-  } *__u = __dest;
-  switch ((unsigned int) __srclen)
-    {
-    case 1:
-      __u->__c = __src1;
-      break;
-    case 2:
-      __extension__ __u->__sca2 = __src2;
-      break;
-    case 3:
-      __extension__ __u->__sca3 = __src3;
-      break;
-    case 4:
-      __extension__ __u->__sca4 = __src4;
-      break;
-    case 5:
-      __extension__ __u->__sca5 = __src5;
-      break;
-    case 6:
-      __extension__ __u->__sca6 = __src6;
-      break;
-    case 7:
-      __extension__ __u->__sca7 = __src7;
-      break;
-    case 8:
-      __extension__ __u->__sca8 = __src8;
-      break;
-    }
-  return __extension__ ((void *) __u + __srclen);
-}
-#   endif
-#  endif
 # endif
 #endif
 
 
-/* Return pointer to C in S.  */
 #ifndef _HAVE_STRING_ARCH_strchr
 extern void *__rawmemchr (const void *__s, int __c);
 # if __GNUC_PREREQ (3, 2)
@@ -243,121 +104,6 @@  extern void *__rawmemchr (const void *__s, int __c);
 #endif
 
 
-/* Copy SRC to DEST.  */
-#if defined _FORCE_INLINES
-# if _STRING_ARCH_unaligned
-__STRING_INLINE char *__strcpy_small (char *, __uint16_t, __uint16_t,
-				      __uint32_t, __uint32_t, size_t);
-__STRING_INLINE char *
-__strcpy_small (char *__dest,
-		__uint16_t __src0_2, __uint16_t __src4_2,
-		__uint32_t __src0_4, __uint32_t __src4_4,
-		size_t __srclen)
-{
-  union {
-    __uint32_t __ui;
-    __uint16_t __usi;
-    unsigned char __uc;
-  } *__u = (void *) __dest;
-  switch ((unsigned int) __srclen)
-    {
-    case 1:
-      __u->__uc = '\0';
-      break;
-    case 2:
-      __u->__usi = __src0_2;
-      break;
-    case 3:
-      __u->__usi = __src0_2;
-      __u = __extension__ ((void *) __u + 2);
-      __u->__uc = '\0';
-      break;
-    case 4:
-      __u->__ui = __src0_4;
-      break;
-    case 5:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__uc = '\0';
-      break;
-    case 6:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__usi = __src4_2;
-      break;
-    case 7:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__usi = __src4_2;
-      __u = __extension__ ((void *) __u + 2);
-      __u->__uc = '\0';
-      break;
-    case 8:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__ui = __src4_4;
-      break;
-    }
-  return __dest;
-}
-# else
-__STRING_INLINE char *__strcpy_small (char *, __STRING2_COPY_ARR2,
-				      __STRING2_COPY_ARR3,
-				      __STRING2_COPY_ARR4,
-				      __STRING2_COPY_ARR5,
-				      __STRING2_COPY_ARR6,
-				      __STRING2_COPY_ARR7,
-				      __STRING2_COPY_ARR8, size_t);
-__STRING_INLINE char *
-__strcpy_small (char *__dest,
-		__STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
-		__STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
-		__STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
-		__STRING2_COPY_ARR8 __src8, size_t __srclen)
-{
-  union {
-    char __c;
-    __STRING2_COPY_ARR2 __sca2;
-    __STRING2_COPY_ARR3 __sca3;
-    __STRING2_COPY_ARR4 __sca4;
-    __STRING2_COPY_ARR5 __sca5;
-    __STRING2_COPY_ARR6 __sca6;
-    __STRING2_COPY_ARR7 __sca7;
-    __STRING2_COPY_ARR8 __sca8;
-  } *__u = (void *) __dest;
-  switch ((unsigned int) __srclen)
-    {
-    case 1:
-      __u->__c = '\0';
-      break;
-    case 2:
-      __extension__ __u->__sca2 = __src2;
-      break;
-    case 3:
-      __extension__ __u->__sca3 = __src3;
-      break;
-    case 4:
-      __extension__ __u->__sca4 = __src4;
-      break;
-    case 5:
-      __extension__ __u->__sca5 = __src5;
-      break;
-    case 6:
-      __extension__ __u->__sca6 = __src6;
-      break;
-    case 7:
-      __extension__ __u->__sca7 = __src7;
-      break;
-    case 8:
-      __extension__ __u->__sca8 = __src8;
-      break;
-  }
-  return __dest;
-}
-# endif
-#endif
-
-
 /* Copy SRC to DEST, returning pointer to final NUL byte.  */
 #ifdef __USE_GNU
 # if !defined _HAVE_STRING_ARCH_stpcpy || defined _FORCE_INLINES
@@ -369,124 +115,6 @@  __strcpy_small (char *__dest,
    we have to use the name `__stpcpy'.  */
 #   define stpcpy(dest, src) __stpcpy (dest, src)
 #  endif
-
-#  if defined _FORCE_INLINES
-#   if _STRING_ARCH_unaligned
-__STRING_INLINE char *__stpcpy_small (char *, __uint16_t, __uint16_t,
-				      __uint32_t, __uint32_t, size_t);
-__STRING_INLINE char *
-__stpcpy_small (char *__dest,
-		__uint16_t __src0_2, __uint16_t __src4_2,
-		__uint32_t __src0_4, __uint32_t __src4_4,
-		size_t __srclen)
-{
-  union {
-    unsigned int __ui;
-    unsigned short int __usi;
-    unsigned char __uc;
-    char __c;
-  } *__u = (void *) __dest;
-  switch ((unsigned int) __srclen)
-    {
-    case 1:
-      __u->__uc = '\0';
-      break;
-    case 2:
-      __u->__usi = __src0_2;
-      __u = __extension__ ((void *) __u + 1);
-      break;
-    case 3:
-      __u->__usi = __src0_2;
-      __u = __extension__ ((void *) __u + 2);
-      __u->__uc = '\0';
-      break;
-    case 4:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 3);
-      break;
-    case 5:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__uc = '\0';
-      break;
-    case 6:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__usi = __src4_2;
-      __u = __extension__ ((void *) __u + 1);
-      break;
-    case 7:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__usi = __src4_2;
-      __u = __extension__ ((void *) __u + 2);
-      __u->__uc = '\0';
-      break;
-    case 8:
-      __u->__ui = __src0_4;
-      __u = __extension__ ((void *) __u + 4);
-      __u->__ui = __src4_4;
-      __u = __extension__ ((void *) __u + 3);
-      break;
-    }
-  return &__u->__c;
-}
-#   else
-__STRING_INLINE char *__stpcpy_small (char *, __STRING2_COPY_ARR2,
-				      __STRING2_COPY_ARR3,
-				      __STRING2_COPY_ARR4,
-				      __STRING2_COPY_ARR5,
-				      __STRING2_COPY_ARR6,
-				      __STRING2_COPY_ARR7,
-				      __STRING2_COPY_ARR8, size_t);
-__STRING_INLINE char *
-__stpcpy_small (char *__dest,
-		__STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
-		__STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
-		__STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
-		__STRING2_COPY_ARR8 __src8, size_t __srclen)
-{
-  union {
-    char __c;
-    __STRING2_COPY_ARR2 __sca2;
-    __STRING2_COPY_ARR3 __sca3;
-    __STRING2_COPY_ARR4 __sca4;
-    __STRING2_COPY_ARR5 __sca5;
-    __STRING2_COPY_ARR6 __sca6;
-    __STRING2_COPY_ARR7 __sca7;
-    __STRING2_COPY_ARR8 __sca8;
-  } *__u = (void *) __dest;
-  switch ((unsigned int) __srclen)
-    {
-    case 1:
-      __u->__c = '\0';
-      break;
-    case 2:
-      __extension__ __u->__sca2 = __src2;
-      break;
-    case 3:
-      __extension__ __u->__sca3 = __src3;
-      break;
-    case 4:
-      __extension__ __u->__sca4 = __src4;
-      break;
-    case 5:
-      __extension__ __u->__sca5 = __src5;
-      break;
-    case 6:
-      __extension__ __u->__sca6 = __src6;
-      break;
-    case 7:
-      __extension__ __u->__sca7 = __src7;
-      break;
-    case 8:
-      __extension__ __u->__sca8 = __src8;
-      break;
-  }
-  return __dest + __srclen - 1;
-}
-#   endif
-#  endif
 # endif
 #endif
 
diff --git a/string/string-inlines.c b/string/string-inlines.c
index 0445be7..432d58d 100644
--- a/string/string-inlines.c
+++ b/string/string-inlines.c
@@ -32,3 +32,349 @@ 
 #undef __NO_INLINE__
 #include <bits/string.h>
 #include <bits/string2.h>
+
+/* These are a few types we need for the optimizations if we cannot
+   use unaligned memory accesses.  */
+# define __STRING2_COPY_TYPE(N) \
+  typedef struct { unsigned char __arr[N]; }				      \
+    __attribute__ ((__packed__)) __STRING2_COPY_ARR##N
+__STRING2_COPY_TYPE (2);
+__STRING2_COPY_TYPE (3);
+__STRING2_COPY_TYPE (4);
+__STRING2_COPY_TYPE (5);
+__STRING2_COPY_TYPE (6);
+__STRING2_COPY_TYPE (7);
+__STRING2_COPY_TYPE (8);
+# undef __STRING2_COPY_TYPE
+
+
+#if _STRING_ARCH_unaligned
+__STRING_INLINE void *__mempcpy_small (void *, char, char, char, char,
+				       __uint16_t, __uint16_t, __uint32_t,
+				       __uint32_t, size_t);
+__STRING_INLINE void *
+__mempcpy_small (void *__dest1,
+		 char __src0_1, char __src2_1, char __src4_1, char __src6_1,
+		 __uint16_t __src0_2, __uint16_t __src4_2,
+		 __uint32_t __src0_4, __uint32_t __src4_4,
+		 size_t __srclen)
+{
+  union {
+    __uint32_t __ui;
+    __uint16_t __usi;
+    unsigned char __uc;
+    unsigned char __c;
+  } *__u = __dest1;
+  switch ((unsigned int) __srclen)
+    {
+    case 1:
+      __u->__c = __src0_1;
+      __u = __extension__ ((void *) __u + 1);
+      break;
+    case 2:
+      __u->__usi = __src0_2;
+      __u = __extension__ ((void *) __u + 2);
+      break;
+    case 3:
+      __u->__usi = __src0_2;
+      __u = __extension__ ((void *) __u + 2);
+      __u->__c = __src2_1;
+      __u = __extension__ ((void *) __u + 1);
+      break;
+    case 4:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      break;
+    case 5:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__c = __src4_1;
+      __u = __extension__ ((void *) __u + 1);
+      break;
+    case 6:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__usi = __src4_2;
+      __u = __extension__ ((void *) __u + 2);
+      break;
+    case 7:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__usi = __src4_2;
+      __u = __extension__ ((void *) __u + 2);
+      __u->__c = __src6_1;
+      __u = __extension__ ((void *) __u + 1);
+      break;
+    case 8:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__ui = __src4_4;
+      __u = __extension__ ((void *) __u + 4);
+      break;
+    }
+  return (void *) __u;
+}
+
+#else
+
+__STRING_INLINE void *
+__mempcpy_small (void *__dest, char __src1,
+		 __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
+		 __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
+		 __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
+		 __STRING2_COPY_ARR8 __src8, size_t __srclen)
+{
+  union {
+    char __c;
+    __STRING2_COPY_ARR2 __sca2;
+    __STRING2_COPY_ARR3 __sca3;
+    __STRING2_COPY_ARR4 __sca4;
+    __STRING2_COPY_ARR5 __sca5;
+    __STRING2_COPY_ARR6 __sca6;
+    __STRING2_COPY_ARR7 __sca7;
+    __STRING2_COPY_ARR8 __sca8;
+  } *__u = __dest;
+  switch ((unsigned int) __srclen)
+    {
+    case 1:
+      __u->__c = __src1;
+      break;
+    case 2:
+      __extension__ __u->__sca2 = __src2;
+      break;
+    case 3:
+      __extension__ __u->__sca3 = __src3;
+      break;
+    case 4:
+      __extension__ __u->__sca4 = __src4;
+      break;
+    case 5:
+      __extension__ __u->__sca5 = __src5;
+      break;
+    case 6:
+      __extension__ __u->__sca6 = __src6;
+      break;
+    case 7:
+      __extension__ __u->__sca7 = __src7;
+      break;
+    case 8:
+      __extension__ __u->__sca8 = __src8;
+      break;
+    }
+  return __extension__ ((void *) __u + __srclen);
+}
+#endif
+
+# if _STRING_ARCH_unaligned
+__STRING_INLINE char *
+__strcpy_small (char *__dest,
+		__uint16_t __src0_2, __uint16_t __src4_2,
+		__uint32_t __src0_4, __uint32_t __src4_4,
+		size_t __srclen)
+{
+  union {
+    __uint32_t __ui;
+    __uint16_t __usi;
+    unsigned char __uc;
+  } *__u = (void *) __dest;
+  switch ((unsigned int) __srclen)
+    {
+    case 1:
+      __u->__uc = '\0';
+      break;
+    case 2:
+      __u->__usi = __src0_2;
+      break;
+    case 3:
+      __u->__usi = __src0_2;
+      __u = __extension__ ((void *) __u + 2);
+      __u->__uc = '\0';
+      break;
+    case 4:
+      __u->__ui = __src0_4;
+      break;
+    case 5:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__uc = '\0';
+      break;
+    case 6:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__usi = __src4_2;
+      break;
+    case 7:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__usi = __src4_2;
+      __u = __extension__ ((void *) __u + 2);
+      __u->__uc = '\0';
+      break;
+    case 8:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__ui = __src4_4;
+      break;
+    }
+  return __dest;
+}
+
+#else
+
+__STRING_INLINE char *
+__strcpy_small (char *__dest,
+		__STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
+		__STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
+		__STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
+		__STRING2_COPY_ARR8 __src8, size_t __srclen)
+{
+  union {
+    char __c;
+    __STRING2_COPY_ARR2 __sca2;
+    __STRING2_COPY_ARR3 __sca3;
+    __STRING2_COPY_ARR4 __sca4;
+    __STRING2_COPY_ARR5 __sca5;
+    __STRING2_COPY_ARR6 __sca6;
+    __STRING2_COPY_ARR7 __sca7;
+    __STRING2_COPY_ARR8 __sca8;
+  } *__u = (void *) __dest;
+  switch ((unsigned int) __srclen)
+    {
+    case 1:
+      __u->__c = '\0';
+      break;
+    case 2:
+      __extension__ __u->__sca2 = __src2;
+      break;
+    case 3:
+      __extension__ __u->__sca3 = __src3;
+      break;
+    case 4:
+      __extension__ __u->__sca4 = __src4;
+      break;
+    case 5:
+      __extension__ __u->__sca5 = __src5;
+      break;
+    case 6:
+      __extension__ __u->__sca6 = __src6;
+      break;
+    case 7:
+      __extension__ __u->__sca7 = __src7;
+      break;
+    case 8:
+      __extension__ __u->__sca8 = __src8;
+      break;
+  }
+  return __dest;
+}
+#endif
+
+
+#if _STRING_ARCH_unaligned
+__STRING_INLINE char *
+__stpcpy_small (char *__dest,
+		__uint16_t __src0_2, __uint16_t __src4_2,
+		__uint32_t __src0_4, __uint32_t __src4_4,
+		size_t __srclen)
+{
+  union {
+    unsigned int __ui;
+    unsigned short int __usi;
+    unsigned char __uc;
+    char __c;
+  } *__u = (void *) __dest;
+  switch ((unsigned int) __srclen)
+    {
+    case 1:
+      __u->__uc = '\0';
+      break;
+    case 2:
+      __u->__usi = __src0_2;
+      __u = __extension__ ((void *) __u + 1);
+      break;
+    case 3:
+      __u->__usi = __src0_2;
+      __u = __extension__ ((void *) __u + 2);
+      __u->__uc = '\0';
+      break;
+    case 4:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 3);
+      break;
+    case 5:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__uc = '\0';
+      break;
+    case 6:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__usi = __src4_2;
+      __u = __extension__ ((void *) __u + 1);
+      break;
+    case 7:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__usi = __src4_2;
+      __u = __extension__ ((void *) __u + 2);
+      __u->__uc = '\0';
+      break;
+    case 8:
+      __u->__ui = __src0_4;
+      __u = __extension__ ((void *) __u + 4);
+      __u->__ui = __src4_4;
+      __u = __extension__ ((void *) __u + 3);
+      break;
+    }
+  return &__u->__c;
+}
+
+#else
+
+__STRING_INLINE char *
+__stpcpy_small (char *__dest,
+		__STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
+		__STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
+		__STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
+		__STRING2_COPY_ARR8 __src8, size_t __srclen)
+{
+  union {
+    char __c;
+    __STRING2_COPY_ARR2 __sca2;
+    __STRING2_COPY_ARR3 __sca3;
+    __STRING2_COPY_ARR4 __sca4;
+    __STRING2_COPY_ARR5 __sca5;
+    __STRING2_COPY_ARR6 __sca6;
+    __STRING2_COPY_ARR7 __sca7;
+    __STRING2_COPY_ARR8 __sca8;
+  } *__u = (void *) __dest;
+  switch ((unsigned int) __srclen)
+    {
+    case 1:
+      __u->__c = '\0';
+      break;
+    case 2:
+      __extension__ __u->__sca2 = __src2;
+      break;
+    case 3:
+      __extension__ __u->__sca3 = __src3;
+      break;
+    case 4:
+      __extension__ __u->__sca4 = __src4;
+      break;
+    case 5:
+      __extension__ __u->__sca5 = __src5;
+      break;
+    case 6:
+      __extension__ __u->__sca6 = __src6;
+      break;
+    case 7:
+      __extension__ __u->__sca7 = __src7;
+      break;
+    case 8:
+      __extension__ __u->__sca8 = __src8;
+      break;
+  }
+  return __dest + __srclen - 1;
+}
+#endif
diff --git a/sysdeps/i386/string-inlines.c b/sysdeps/i386/string-inlines.c
index 862a431..de1f71c 100644
--- a/sysdeps/i386/string-inlines.c
+++ b/sysdeps/i386/string-inlines.c
@@ -19,23 +19,11 @@ 
     functions.  These functions are declared additionally here if
     inlining is not possible.  */
 
-#undef __USE_STRING_INLINES
-#define __USE_STRING_INLINES
-#define _FORCE_INLINES
-#define __STRING_INLINE /* empty */
-#define __NO_INLINE__
-
 /* This is to avoid PLT entries for the x86 version.  */
 #define __memcpy_g __memcpy_g_internal
 #define __strchr_g __strchr_g_internal
 
-#include <string.h>
-#undef index
-#undef rindex
-
-#undef __NO_INLINE__
-#include <bits/string.h>
-#include <bits/string2.h>
+#include <string/string-inlines.c>
 
 void *
 (__memcpy_c) (void *d, const void *s, size_t n)