aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorYury Gribov <tetra2005@gmail.com>2017-07-21 19:48:51 +0000
committerYury Gribov <ygribov@gcc.gnu.org>2017-07-21 19:48:51 +0000
commit325fe81618c822b8cac4fd31c1ec57066ef338cf (patch)
treed8eef4564991b0292b0db768be536f9bd4d883cd /gcc
parentd5c125ca0cd017c96b5996b8e934a5d755f5a577 (diff)
downloadgcc-325fe81618c822b8cac4fd31c1ec57066ef338cf.zip
gcc-325fe81618c822b8cac4fd31c1ec57066ef338cf.tar.gz
gcc-325fe81618c822b8cac4fd31c1ec57066ef338cf.tar.bz2
re PR middle-end/56727 (Recursive call goes through the PLT unnecessarily)
2017-07-21 Yury Gribov <tetra2005@gmail.com> PR middle-end/56727 * ipa-visibility (function_and_variable_visibility): Convert recursive PLT call to direct call if appropriate. * gcc.dg/pr56727-1.c: New test. * gcc.dg/pr56727-2.c: New test. From-SVN: r250442
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/ipa-visibility.c31
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr56727-1.c23
-rw-r--r--gcc/testsuite/gcc.dg/pr56727-2.c16
5 files changed, 82 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2033b33..55937a8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2017-07-21 Yury Gribov <tetra2005@gmail.com>
+
+ PR middle-end/56727
+ * ipa-visibility (function_and_variable_visibility): Convert
+ recursive PLT call to direct call if appropriate.
+
2017-07-21 Andrew Pinski <apinski@cavium.com>
* tree-ssa-sccvn.c (vn_nary_op_eq): Check BIT_INSERT_EXPR's
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index 17186e9..2132170 100644
--- a/gcc/ipa-visibility.c
+++ b/gcc/ipa-visibility.c
@@ -83,6 +83,7 @@ along with GCC; see the file COPYING3. If not see
#include "cgraph.h"
#include "calls.h"
#include "varasm.h"
+#include "ipa-utils.h"
/* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
@@ -617,6 +618,36 @@ function_and_variable_visibility (bool whole_program)
/* All aliases should be procssed at this point. */
gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
+ FOR_EACH_DEFINED_FUNCTION (node)
+ {
+ if (node->get_availability () != AVAIL_INTERPOSABLE
+ || DECL_EXTERNAL (node->decl)
+ || node->has_aliases_p ())
+ continue;
+
+ cgraph_node *alias = 0;
+ for (cgraph_edge *e = node->callees; e; e = e->next_callee)
+ {
+ /* Recursive function calls usually can't be interposed. */
+
+ if (!e->recursive_p ())
+ continue;
+
+ if (!alias)
+ {
+ alias = dyn_cast<cgraph_node *> (node->noninterposable_alias ());
+ gcc_assert (alias && alias != node);
+ }
+
+ e->redirect_callee (alias);
+ if (gimple_has_body_p (e->caller->decl))
+ {
+ push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
+ e->redirect_call_stmt_to_callee ();
+ pop_cfun ();
+ }
+ }
+ }
FOR_EACH_FUNCTION (node)
{
int flags = flags_from_decl_or_type (node->decl);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 530a4ab..6ee65b1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-07-21 Yury Gribov <tetra2005@gmail.com>
+
+ PR middle-end/56727
+ * gcc.dg/pr56727-1.c: New test.
+ * gcc.dg/pr56727-2.c: New test.
+
2017-07-21 Steven Munroe <munroesj@gcc.gnu.org>
* gcc.target/powerpc/mmx-check.h: New file.
diff --git a/gcc/testsuite/gcc.dg/pr56727-1.c b/gcc/testsuite/gcc.dg/pr56727-1.c
new file mode 100644
index 0000000..ffc1335
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr56727-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -fPIC" } */
+/* { dg-final { scan-assembler-not "@(PLT|plt)" { target i?86-*-* x86_64-*-* powerpc*-*-* } } } */
+
+#define define_func(type) \
+ void f_ ## type (type b) { f_ ## type (0); } \
+ void __attribute__((noinline, noclone)) f_noinline_ ## type (type b) \
+ { f_noinline_ ## type (0); }
+
+define_func(char)
+define_func(short)
+define_func(int)
+define_func(long)
+
+int foo(int n)
+{
+ return (n == 1 || n == 2) ? 1 : foo(n-1) * foo(n-2);
+}
+
+int __attribute__((noinline, noclone)) foo_noinline(int n)
+{
+ return (n == 1 || n == 2) ? 1 : foo_noinline(n-1) * foo_noinline(n-2);
+}
diff --git a/gcc/testsuite/gcc.dg/pr56727-2.c b/gcc/testsuite/gcc.dg/pr56727-2.c
new file mode 100644
index 0000000..a285d57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr56727-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target fpic } } */
+/* { dg-options "-O2 -fPIC" } */
+/* { dg-final { scan-assembler "@(PLT|plt)" { target i?86-*-* x86_64-*-* powerpc*-*-* } } } */
+
+__attribute__((noinline, noclone))
+void f (short b)
+{
+ f (0);
+}
+
+static void g (short) __attribute__ ((alias ("f")));
+
+void h ()
+{
+ g (0);
+}