about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>2013-06-20 19:40:55 -0500
committerRyan S. Arnold <rsa@linux.vnet.ibm.com>2013-07-26 12:56:47 -0500
commit5c616c0a75792d2836412d6c4ed5c71e8e754992 (patch)
treed662e38ab9072af8da711afaa7fc7decd71c2af7
parent3ca2c50727b3e3e22eb3606135a18c6212f516d2 (diff)
downloadglibc-5c616c0a75792d2836412d6c4ed5c71e8e754992.tar.gz
glibc-5c616c0a75792d2836412d6c4ed5c71e8e754992.tar.xz
glibc-5c616c0a75792d2836412d6c4ed5c71e8e754992.zip
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--ChangeLog14
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure33
-rw-r--r--configure.in18
-rw-r--r--include/libc-symbols.h10
-rw-r--r--string/memmove.c1
-rw-r--r--string/memset.c1
-rw-r--r--string/test-memmove.c1
-rw-r--r--string/test-memset.c1
9 files changed, 82 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 685083b118..bf91984fd3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 f3fe6b88be..b34aac2f45 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
diff --git a/configure b/configure
index 8799b7de78..99e85bea67 100755
--- a/configure
+++ b/configure
@@ -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 d369382264..379e77a250 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 a626d593db..8f2c0467f0 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 bf7dcc1627..c59e7a9c2a 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 036cb5f624..eb83c1b5a8 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 13c5aff8a2..0a969c34ef 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 af85a28762..04320305fb 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;