diff options
author | Adhemerval Zanella <azanella@linux.vnet.ibm.com> | 2013-06-20 19:40:55 -0500 |
---|---|---|
committer | Ryan S. Arnold <rsa@linux.vnet.ibm.com> | 2013-07-26 12:56:47 -0500 |
commit | 5c616c0a75792d2836412d6c4ed5c71e8e754992 (patch) | |
tree | d662e38ab9072af8da711afaa7fc7decd71c2af7 | |
parent | 3ca2c50727b3e3e22eb3606135a18c6212f516d2 (diff) | |
download | glibc-5c616c0a75792d2836412d6c4ed5c71e8e754992.zip glibc-5c616c0a75792d2836412d6c4ed5c71e8e754992.tar.gz glibc-5c616c0a75792d2836412d6c4ed5c71e8e754992.tar.bz2 |
Fix loop construction to functions calls
Check wheter the compiler has the option -fno-tree-loop-distribute-patterns
to inhibit loop transformation to library calls and uses it on memset
and memmove default implementation to avoid recursive calls.
(backported from commit 85c2e6110c9a01ec817c30f1b7e20549d7229987)
This backport excluded the benchmark tests from the original commit.
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | config.h.in | 3 | ||||
-rwxr-xr-x | configure | 33 | ||||
-rw-r--r-- | configure.in | 18 | ||||
-rw-r--r-- | include/libc-symbols.h | 10 | ||||
-rw-r--r-- | string/memmove.c | 1 | ||||
-rw-r--r-- | string/memset.c | 1 | ||||
-rw-r--r-- | string/test-memmove.c | 1 | ||||
-rw-r--r-- | string/test-memset.c | 1 |
9 files changed, 82 insertions, 0 deletions
@@ -1,3 +1,17 @@ +2013-06-20 Adhemerval Zanella <azanella@linux.vnet.ibm.com> + + * config.h.in (HAVE_CC_INHIBIT_LOOP_TO_LIBCALL): New define. + * configure.in (libc_cv_cc_loop_to_function): Check if compiler + accepts -fno-tree-loop-distribute-patterns. + * include/libc-symbols.h (inhibit_loop_to_libcall): New macro. + * string/memmove.c (MEMMOVE): Disable loop transformation to avoid + recursive call. + * string/memset.c (memset): Likewise. + * string/test-memmove.c (simple_memmove): Disable loop transformation + to library calls. + * string/test-memset.c (simple_memset): Likewise. + * configure: Regenerated. + 2013-06-28 Ryan S. Arnold <rsa@linux.vnet.ibm.com> * sysdeps/powerpc/Makefile: Add comment about generating an offset to diff --git a/config.h.in b/config.h.in index f3fe6b8..b34aac2 100644 --- a/config.h.in +++ b/config.h.in @@ -69,6 +69,9 @@ /* Define if the compiler supports __builtin_memset. */ #undef HAVE_BUILTIN_MEMSET +/* Define if compiler accepts -ftree-loop-distribute-patterns. */ +#undef HAVE_CC_INHIBIT_LOOP_TO_LIBCALL + /* Define if the regparm attribute shall be used for local functions (gcc on ix86 only). */ #undef USE_REGPARMS @@ -605,6 +605,7 @@ have_selinux have_libcap have_libaudit LIBGD +libc_cv_cc_loop_to_function libc_cv_cc_submachine exceptions gnu89_inline @@ -7164,6 +7165,38 @@ $as_echo "$libc_cv_cc_submachine" >&6; } fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC accepts -fno-tree-loop-distribute-patterns with \ +__attribute__ ((__optimize__))" >&5 +$as_echo_n "checking if $CC accepts -fno-tree-loop-distribute-patterns with \ +__attribute__ ((__optimize__))... " >&6; } +if ${libc_cv_cc_loop_to_function+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat > conftest.c <<EOF +void +__attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns"))) +foo (void) {} +EOF +libc_cv_cc_loop_to_function=no +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -c conftest.c' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then + libc_cv_cc_loop_to_function=yes +fi +rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_loop_to_function" >&5 +$as_echo "$libc_cv_cc_loop_to_function" >&6; } +if test $libc_cv_cc_loop_to_function = yes; then + $as_echo "#define HAVE_CC_INHIBIT_LOOP_TO_LIBCALL 1" >>confdefs.h + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libgd" >&5 $as_echo_n "checking for libgd... " >&6; } if test "$with_gd" != "no"; then diff --git a/configure.in b/configure.in index d369382..379e77a 100644 --- a/configure.in +++ b/configure.in @@ -1928,6 +1928,24 @@ if test -n "$submachine"; then fi AC_SUBST(libc_cv_cc_submachine) +AC_CACHE_CHECK(if $CC accepts -fno-tree-loop-distribute-patterns with \ +__attribute__ ((__optimize__)), libc_cv_cc_loop_to_function, [dnl +cat > conftest.c <<EOF +void +__attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns"))) +foo (void) {} +EOF +libc_cv_cc_loop_to_function=no +if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS -c conftest.c]) +then + libc_cv_cc_loop_to_function=yes +fi +rm -f conftest*]) +if test $libc_cv_cc_loop_to_function = yes; then + AC_DEFINE(HAVE_CC_INHIBIT_LOOP_TO_LIBCALL) +fi +AC_SUBST(libc_cv_cc_loop_to_function) + dnl Check whether we have the gd library available. AC_MSG_CHECKING(for libgd) if test "$with_gd" != "no"; then diff --git a/include/libc-symbols.h b/include/libc-symbols.h index a626d59..8f2c046 100644 --- a/include/libc-symbols.h +++ b/include/libc-symbols.h @@ -783,4 +783,14 @@ for linking") #define libc_ifunc_hidden_def(name) \ libc_ifunc_hidden_def1 (__GI_##name, name) +/* Add the compiler optimization to inhibit loop transformation to library + calls. This is used to avoid recursive calls in memset and memmove + default implementations. */ +#ifdef HAVE_CC_INHIBIT_LOOP_TO_LIBCALL +# define inhibit_loop_to_libcall \ + __attribute__ ((__optimize__ ("-fno-tree-loop-distribute-patterns"))) +#else +# define inhibit_loop_to_libcall +#endif + #endif /* libc-symbols.h */ diff --git a/string/memmove.c b/string/memmove.c index bf7dcc1..c59e7a9 100644 --- a/string/memmove.c +++ b/string/memmove.c @@ -41,6 +41,7 @@ #endif rettype +inhibit_loop_to_libcall MEMMOVE (a1, a2, len) a1const void *a1; a2const void *a2; diff --git a/string/memset.c b/string/memset.c index 036cb5f..eb83c1b 100644 --- a/string/memset.c +++ b/string/memset.c @@ -21,6 +21,7 @@ #undef memset void * +inhibit_loop_to_libcall memset (dstpp, c, len) void *dstpp; int c; diff --git a/string/test-memmove.c b/string/test-memmove.c index 13c5aff..0a969c3 100644 --- a/string/test-memmove.c +++ b/string/test-memmove.c @@ -47,6 +47,7 @@ IMPL (memmove, 1) #endif char * +inhibit_loop_to_libcall simple_memmove (char *dst, const char *src, size_t n) { char *ret = dst; diff --git a/string/test-memset.c b/string/test-memset.c index af85a28..0432030 100644 --- a/string/test-memset.c +++ b/string/test-memset.c @@ -64,6 +64,7 @@ builtin_memset (char *s, int c, size_t n) #endif char * +inhibit_loop_to_libcall simple_memset (char *s, int c, size_t n) { char *r = s, *end = s + n; |