diff options
authorRich Felker <>2012-10-25 15:40:58 -0400
committerRich Felker <>2012-10-25 15:40:58 -0400
commit607b05aca683eee5bcdb7bf9af4ebf02adc635d9 (patch)
parent80a45458e0d9b75d508110bd880d0ae0432b0356 (diff)
use explicit visibility to optimize a few hot-path function calls
on x86 and some other archs, functions which make function calls which might go through a PLT incur a significant overhead cost loading the GOT register prior to making the call. this load is utterly useless in musl, since all calls are bound at library-creation time using -Bsymbolic-functions, but the compiler has no way of knowing this, and attempts to set the default visibility to protected have failed due to bugs in GCC and binutils. this commit simply manually assigns hidden/protected visibility, as appropriate, to a few internal-use-only functions which have many callers, or which have callers that are hot paths like getc/putc. it shaves about 5k off the i386 with -Os. many of the improvements are in syscall wrappers, where the benefit is just size and performance improvement is unmeasurable noise amid the syscall overhead. however, stdio may be measurably faster. if in the future there are toolchains that can do the same thing globally without introducing linking bugs, it might be worth considering removing these workarounds.
3 files changed, 13 insertions, 11 deletions
diff --git a/src/internal/libc.h b/src/internal/libc.h
index 703d9853..5ab4e679 100644
--- a/src/internal/libc.h
+++ b/src/internal/libc.h
@@ -46,10 +46,10 @@ extern struct __libc *__libc_loc(void) __attribute__((const));
/* Designed to avoid any overhead in non-threaded processes */
-void __lock(volatile int *);
-void __unlock(volatile int *);
-int __lockfile(FILE *);
-void __unlockfile(FILE *);
+void __lock(volatile int *) ATTR_LIBC_VISIBILITY;
+void __unlock(volatile int *) ATTR_LIBC_VISIBILITY;
+int __lockfile(FILE *) ATTR_LIBC_VISIBILITY;
+void __unlockfile(FILE *) ATTR_LIBC_VISIBILITY;
#define LOCK(x) (libc.threads_minus_1 ? (__lock(x),1) : ((void)(x),1))
#define UNLOCK(x) (libc.threads_minus_1 ? (__unlock(x),1) : ((void)(x),1))
diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h
index 279e91fd..80646f8c 100644
--- a/src/internal/stdio_impl.h
+++ b/src/internal/stdio_impl.h
@@ -74,10 +74,10 @@ size_t __string_read(FILE *, unsigned char *, size_t);
int __toread(FILE *);
int __towrite(FILE *);
-int __overflow(FILE *, int);
-int __oflow(FILE *);
-int __uflow(FILE *);
-int __underflow(FILE *);
+#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303)
+int __overflow(FILE *, int), __uflow(FILE *);
int __fseeko(FILE *, off_t, int);
int __fseeko_unlocked(FILE *, off_t, int);
diff --git a/src/internal/syscall.h b/src/internal/syscall.h
index 50409ef8..7381efea 100644
--- a/src/internal/syscall.h
+++ b/src/internal/syscall.h
@@ -1,9 +1,11 @@
-long __syscall_ret(unsigned long);
-long __syscall(long, ...);
-long __syscall_cp(long, long, long, long, long, long, long);
+#if defined(__PIC__) && (100*__GNUC__+__GNUC_MINOR__ >= 303)
+long __syscall_ret(unsigned long), __syscall(long, ...),
+ __syscall_cp(long, long, long, long, long, long, long);
#include <sys/syscall.h>
#include "syscall_arch.h"