summaryrefslogtreecommitdiff
path: root/gcc/ipa.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2016-03-10 16:11:14 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2016-03-10 16:11:14 +0000
commit75e72311efdcc76e38aacbe9f503215f69de0285 (patch)
tree75330395a11be8ce2a0a3af9dc620e72f851a88a /gcc/ipa.c
parent76333f63d2ce20bec1e45e5e39358e20131cd3fe (diff)
downloadgcc-75e72311efdcc76e38aacbe9f503215f69de0285.tar.gz
PR lto/69589
* cgraph.c (cgraph_node::dump): Dump split_part and indirect_call_target. * cgraph.h (cgraph_node): Add indirect_call_target flag. * ipa.c (has_addr_references_p): Cleanup. (is_indirect_call_target_p): New. (walk_polymorphic_call_targets): Do not mark virtuals that may be called indirectly as local. (symbol_table::remove_unreachable_nodes): Compute indirect_call_target. * g++.dg/lto/pr69589_0.C: New testcase * g++.dg/lto/pr69589_1.C: New testcase git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@234115 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r--gcc/ipa.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 3c8fc00e6b5..6722d3b806e 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see
static bool
has_addr_references_p (struct cgraph_node *node,
- void *data ATTRIBUTE_UNUSED)
+ void *)
{
int i;
struct ipa_ref *ref = NULL;
@@ -52,6 +52,14 @@ has_addr_references_p (struct cgraph_node *node,
return false;
}
+/* Return true when NODE can be target of an indirect call. */
+
+static bool
+is_indirect_call_target_p (struct cgraph_node *node, void *)
+{
+ return node->indirect_call_target;
+}
+
/* Look for all functions inlined to NODE and update their inlined_to pointers
to INLINED_TO. */
@@ -172,23 +180,24 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
(TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl))))
continue;
- symtab_node *body = n->function_symbol ();
+ n->indirect_call_target = true;
+ symtab_node *body = n->function_symbol ();
/* Prior inlining, keep alive bodies of possible targets for
devirtualization. */
- if (n->definition
- && (before_inlining_p
- && opt_for_fn (body->decl, optimize)
- && opt_for_fn (body->decl, flag_devirtualize)))
- {
- /* Be sure that we will not optimize out alias target
- body. */
- if (DECL_EXTERNAL (n->decl)
- && n->alias
- && before_inlining_p)
- reachable->add (body);
- reachable->add (n);
- }
+ if (n->definition
+ && (before_inlining_p
+ && opt_for_fn (body->decl, optimize)
+ && opt_for_fn (body->decl, flag_devirtualize)))
+ {
+ /* Be sure that we will not optimize out alias target
+ body. */
+ if (DECL_EXTERNAL (n->decl)
+ && n->alias
+ && before_inlining_p)
+ reachable->add (body);
+ reachable->add (n);
+ }
/* Even after inlining we want to keep the possible targets in the
boundary, so late passes can still produce direct call even if
the chance for inlining is lost. */
@@ -323,6 +332,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
FOR_EACH_FUNCTION (node)
{
node->used_as_abstract_origin = false;
+ node->indirect_call_target = false;
if (node->definition
&& !node->global.inlined_to
&& !node->in_other_partition
@@ -659,7 +669,14 @@ symbol_table::remove_unreachable_nodes (FILE *file)
fprintf (file, " %s", node->name ());
node->address_taken = false;
changed = true;
- if (node->local_p ())
+ if (node->local_p ()
+ /* Virtual functions may be kept in cgraph just because
+ of possible later devirtualization. Do not mark them as
+ local too early so we won't optimize them out before
+ we are done with polymorphic call analysis. */
+ && (!before_inlining_p
+ || !node->call_for_symbol_and_aliases
+ (is_indirect_call_target_p, NULL, true)))
{
node->local.local = true;
if (file)