diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2016-03-10 17:11:14 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2016-03-10 16:11:14 +0000 |
commit | 4f4ada6afb970674c3f33d895ec793491a026c1c (patch) | |
tree | 75330395a11be8ce2a0a3af9dc620e72f851a88a /gcc/ipa.c | |
parent | 079cd8548b540ceda89887711f6f7fb3a8fa49ec (diff) | |
download | gcc-4f4ada6afb970674c3f33d895ec793491a026c1c.zip gcc-4f4ada6afb970674c3f33d895ec793491a026c1c.tar.gz gcc-4f4ada6afb970674c3f33d895ec793491a026c1c.tar.bz2 |
re PR ipa/69589 (ICE in initialize_node_lattices, at ipa-cp.c:971)
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
From-SVN: r234115
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r-- | gcc/ipa.c | 49 |
1 files changed, 33 insertions, 16 deletions
@@ -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) |