Add INLINE_SYSCALL_ERROR_RETURN_VALUE
commitfb1cf108115f7e2e4510859693431b3473657d77
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 13 Oct 2015 18:58:53 +0000 (13 11:58 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 13 Oct 2015 18:59:15 +0000 (13 11:59 -0700)
tree5c1579a854a37ac677b5647273ce5fccba600e4a
parent0a5768fe9c2e2870269c3a0920f88d9c22d73e33
Add INLINE_SYSCALL_ERROR_RETURN_VALUE

For ia32 PIC, the first thing of many syscalls does is to call
__x86.get_pc_thunk.reg to load PC into reg in case there is an error,
which is required for setting errno.  In most cases, there are no
errors.  But we still call __x86.get_pc_thunk.reg.  This patch adds
INLINE_SYSCALL_ERROR_RETURN_VALUE so that i386 can optimize setting
errno by branching to the internal __syscall_error without PLT.

With i386 INLINE_SYSCALL_ERROR_RETURN_VALUE and i386 syscall inlining
optimization for GCC 5, for sysdeps/unix/sysv/linux/fchmodat.c with
-O2 -march=i686 -mtune=generic, GCC 5.2 now generates:

<fchmodat>:
   0: push   %ebx
   1: mov    0x14(%esp),%eax
   5: mov    0x8(%esp),%ebx
   9: mov    0xc(%esp),%ecx
   d: mov    0x10(%esp),%edx
  11: test   $0xfffffeff,%eax
  16: jne    38 <fchmodat+0x38>
  18: test   $0x1,%ah
  1b: jne    48 <fchmodat+0x48>
  1d: mov    $0x132,%eax
  22: call   *%gs:0x10
  29: cmp    $0xfffff000,%eax
  2e: ja     58 <fchmodat+0x58>
  30: pop    %ebx
  31: ret
  32: lea    0x0(%esi),%esi
  38: pop    %ebx
  39: mov    $0xffffffea,%eax
  3e: jmp    3f <fchmodat+0x3f> 3f: R_386_PC32 __syscall_error
  43: nop
  44: lea    0x0(%esi,%eiz,1),%esi
  48: pop    %ebx
  49: mov    $0xffffffa1,%eax
  4e: jmp    4f <fchmodat+0x4f> 4f: R_386_PC32 __syscall_error
  53: nop
  54: lea    0x0(%esi,%eiz,1),%esi
  58: pop    %ebx
  59: jmp    5a <fchmodat+0x5a> 5a: R_386_PC32 __syscall_error

instead of

<fchmodat>:
   0: sub    $0x8,%esp
   3: mov    0x18(%esp),%eax
   7: mov    %ebx,(%esp)
   a: call   b <fchmodat+0xb> b: R_386_PC32 __x86.get_pc_thunk.bx
   f: add    $0x2,%ebx 11: R_386_GOTPC _GLOBAL_OFFSET_TABLE_
  15: mov    %edi,0x4(%esp)
  19: test   $0xfffffeff,%eax
  1e: jne    70 <fchmodat+0x70>
  20: test   $0x1,%ah
  23: jne    88 <fchmodat+0x88>
  25: mov    0x14(%esp),%edx
  29: mov    0x10(%esp),%ecx
  2d: mov    0xc(%esp),%edi
  31: xchg   %ebx,%edi
  33: mov    $0x132,%eax
  38: call   *%gs:0x10
  3f: xchg   %edi,%ebx
  41: cmp    $0xfffff000,%eax
  46: ja     58 <fchmodat+0x58>
  48: mov    (%esp),%ebx
  4b: mov    0x4(%esp),%edi
  4f: add    $0x8,%esp
  52: ret
  53: nop
  54: lea    0x0(%esi,%eiz,1),%esi
  58: mov    0x0(%ebx),%edx 5a: R_386_TLS_GOTIE __libc_errno
  5e: neg    %eax
  60: mov    %eax,%gs:(%edx)
  63: mov    $0xffffffff,%eax
  68: jmp    48 <fchmodat+0x48>
  6a: lea    0x0(%esi),%esi
  70: mov    0x0(%ebx),%eax 72: R_386_TLS_GOTIE __libc_errno
  76: movl   $0x16,%gs:(%eax)
  7d: mov    $0xffffffff,%eax
  82: jmp    48 <fchmodat+0x48>
  84: lea    0x0(%esi,%eiz,1),%esi
  88: mov    0x0(%ebx),%eax 8a: R_386_TLS_GOTIE __libc_errno
  8e: movl   $0x5f,%gs:(%eax)
  95: mov    $0xffffffff,%eax
  9a: jmp    48 <fchmodat+0x48>

* sysdeps/unix/sysv/linux/sysdep.h: New file.
* sysdeps/unix/sysv/linux/i386/sysdep.c: Likewise.
* sysdeps/unix/sysv/linux/alpha/sysdep.h: Include
<sysdeps/unix/sysv/linux/sysdep.h>.
* sysdeps/unix/sysv/linux/arm/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/generic/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/hppa/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/ia64/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/m68k/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/microblaze/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/mips/mips32/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/sh/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/sparc/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise.
* sysdeps/unix/sysv/linux/i386/Makefile [$(subdir) == csu]
(sysdep-dl-routines): Add sysdep.
[$(subdir) == nptl] (libpthread-routines): Likewise.
[$(subdir) == rt] (librt-routines): Likewise.
* sysdeps/unix/sysv/linux/i386/clone.S (__clone): Don't check
PIC when branching to SYSCALL_ERROR_LABEL.
* sysdeps/unix/sysv/linux/i386/sysdep.S: Removed.
* sysdeps/unix/sysv/linux/i386/sysdep.h: Include
<sysdeps/unix/sysv/linux/sysdep.h>.
(SYSCALL_ERROR_LABEL): Changed to __syscall_error.
(SYSCALL_ERROR_ERRNO): Removed.
(SYSCALL_ERROR_HANDLER): Changed to empty.
(SYSCALL_ERROR_HANDLER_TLS_STORE): Likewise.
(__syscall_error): New prototype.
[IS_IN (libc)] (INLINE_SYSCALL): New macro.
(INLINE_SYSCALL_ERROR_RETURN_VALUE): Likewise.
23 files changed:
ChangeLog
sysdeps/unix/sysv/linux/alpha/sysdep.h
sysdeps/unix/sysv/linux/arm/sysdep.h
sysdeps/unix/sysv/linux/generic/sysdep.h
sysdeps/unix/sysv/linux/hppa/sysdep.h
sysdeps/unix/sysv/linux/i386/Makefile
sysdeps/unix/sysv/linux/i386/clone.S
sysdeps/unix/sysv/linux/i386/sysdep.c [copied from sysdeps/unix/sysv/linux/i386/sysdep.S with 53% similarity]
sysdeps/unix/sysv/linux/i386/sysdep.h
sysdeps/unix/sysv/linux/ia64/sysdep.h
sysdeps/unix/sysv/linux/m68k/sysdep.h
sysdeps/unix/sysv/linux/microblaze/sysdep.h
sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h
sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h
sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h
sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
sysdeps/unix/sysv/linux/sh/sysdep.h
sysdeps/unix/sysv/linux/sparc/sysdep.h
sysdeps/unix/sysv/linux/sysdep.h [moved from sysdeps/unix/sysv/linux/i386/sysdep.S with 51% similarity]
sysdeps/unix/sysv/linux/x86_64/sysdep.h