summaryrefslogtreecommitdiff
path: root/gcc/ipa-visibility.c
diff options
context:
space:
mode:
authorygribov <ygribov@138bc75d-0d04-0410-961f-82ee72b054a4>2017-07-21 19:48:51 +0000
committerygribov <ygribov@138bc75d-0d04-0410-961f-82ee72b054a4>2017-07-21 19:48:51 +0000
commit322f1ba9870da39ac02bcce3d6981ef564572af5 (patch)
treed8eef4564991b0292b0db768be536f9bd4d883cd /gcc/ipa-visibility.c
parent0091498ce888398014dac43f204cdfb80bb77564 (diff)
downloadgcc-322f1ba9870da39ac02bcce3d6981ef564572af5.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@250442 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-visibility.c')
-rw-r--r--gcc/ipa-visibility.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/gcc/ipa-visibility.c b/gcc/ipa-visibility.c
index 17186e9d2e6..21321703dbb 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);