summaryrefslogtreecommitdiff
path: root/gcc/ipa-devirt.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-09-08 16:42:21 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2013-09-08 16:42:21 +0000
commite2fa5d74eb579749f3b615135ce6c8abbc76f5cf (patch)
tree6aaf6ed20bc90f69bf381f4674ecd79f8abee69c /gcc/ipa-devirt.c
parent332db80a4abdb5cb51ee7eb226ddef2c26739f02 (diff)
downloadgcc-e2fa5d74eb579749f3b615135ce6c8abbc76f5cf.tar.gz
* testsuite/g++.dg/ipa/devirt-11.C: Update template.
* testsuite/g++.dg/ipa/devirt-16.C: New testcase. * testsuite/g++.dg/ipa/devirt-17.C: New testcase. * testsuite/g++.dg/ipa/devirt-18.C: New testcase. * cgraphunit.c (walk_polymorphic_call_targets): Permit 0 possible targets and devirtualize to BUILT_IN_UNREACHABLE. * timevar.def (TV_IPA_UNREACHABLE): New timevar. * ipa.c (walk_polymorphic_call_targets): New function. (symtab_remove_unreachable_nodes): Use it; do not keep all virtual functions; use the new timevar. * ipa-devirt.c (maybe_record_node): Do not insert static nodes that was removed from the program. (record_binfo): If BINFO corresponds to an anonymous namespace, we may not consider it in the walk when its vtable is dead. (possible_polymorphic_call_targets_1): Pass anonymous flag to record_binfo. (devirt_variable_node_removal_hook): New function. (possible_polymorphic_call_targets): Also register devirt_variable_node_removal_hook. (ipa_devirt): Do not do non-speculative devirtualization. (gate_ipa_devirt): One execute if devirtualizing speculatively. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@202368 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-devirt.c')
-rw-r--r--gcc/ipa-devirt.c72
1 files changed, 43 insertions, 29 deletions
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 2a50284c9b6..96622b25b1b 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -570,6 +570,8 @@ maybe_record_node (vec <cgraph_node *> &nodes,
&& fcode != BUILT_IN_TRAP
&& !pointer_set_insert (inserted, target)
&& (target_node = cgraph_get_node (target)) != NULL
+ && (TREE_PUBLIC (target)
+ || target_node->symbol.definition)
&& symtab_real_symbol_p ((symtab_node)target_node))
{
pointer_set_insert (cached_polymorphic_call_targets,
@@ -591,6 +593,8 @@ maybe_record_node (vec <cgraph_node *> &nodes,
MATCHED_VTABLES tracks virtual tables we already did lookup
for virtual function in.
+
+ ANONYMOUS is true if BINFO is part of anonymous namespace.
*/
static void
@@ -600,7 +604,8 @@ record_binfo (vec <cgraph_node *> &nodes,
tree type_binfo,
HOST_WIDE_INT otr_token,
pointer_set_t *inserted,
- pointer_set_t *matched_vtables)
+ pointer_set_t *matched_vtables,
+ bool anonymous)
{
tree type = BINFO_TYPE (binfo);
int i;
@@ -611,6 +616,19 @@ record_binfo (vec <cgraph_node *> &nodes,
if (types_same_for_odr (type, otr_type)
&& !pointer_set_insert (matched_vtables, BINFO_VTABLE (type_binfo)))
{
+ /* For types in anonymous namespace first check if the respective vtable
+ is alive. If not, we know the type can't be called. */
+ if (!flag_ltrans && anonymous)
+ {
+ tree vtable = BINFO_VTABLE (type_binfo);
+ struct varpool_node *vnode;
+
+ if (TREE_CODE (vtable) == POINTER_PLUS_EXPR)
+ vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0);
+ vnode = varpool_get_node (vtable);
+ if (!vnode || !vnode->symbol.definition)
+ return;
+ }
tree target = gimple_get_virt_method_for_binfo (otr_token, type_binfo);
if (target)
maybe_record_node (nodes, target, inserted);
@@ -626,7 +644,7 @@ record_binfo (vec <cgraph_node *> &nodes,
is shared with the outer type. */
BINFO_VTABLE (base_binfo) ? base_binfo : type_binfo,
otr_token, inserted,
- matched_vtables);
+ matched_vtables, anonymous);
}
/* Lookup virtual methods matching OTR_TYPE (with OFFSET and OTR_TOKEN)
@@ -646,7 +664,7 @@ possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
unsigned int i;
record_binfo (nodes, binfo, otr_type, binfo, otr_token, inserted,
- matched_vtables);
+ matched_vtables, type->anonymous_namespace);
for (i = 0; i < type->derived_types.length(); i++)
possible_polymorphic_call_targets_1 (nodes, inserted,
matched_vtables,
@@ -735,6 +753,18 @@ devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
free_polymorphic_call_targets_hash ();
}
+/* When virtual table is removed, we may need to flush the cache. */
+
+static void
+devirt_variable_node_removal_hook (struct varpool_node *n,
+ void *d ATTRIBUTE_UNUSED)
+{
+ if (cached_polymorphic_call_targets
+ && DECL_VIRTUAL_P (n->symbol.decl)
+ && type_in_anonymous_namespace_p (DECL_CONTEXT (n->symbol.decl)))
+ free_polymorphic_call_targets_hash ();
+}
+
/* Return vector containing possible targets of polymorphic call of type
OTR_TYPE caling method OTR_TOKEN with OFFSET. If FINALp is non-NULL,
store true if the list is complette.
@@ -782,8 +812,12 @@ possible_polymorphic_call_targets (tree otr_type,
cached_polymorphic_call_targets = pointer_set_create ();
polymorphic_call_target_hash.create (23);
if (!node_removal_hook_holder)
- node_removal_hook_holder =
- cgraph_add_node_removal_hook (&devirt_node_removal_hook, NULL);
+ {
+ node_removal_hook_holder =
+ cgraph_add_node_removal_hook (&devirt_node_removal_hook, NULL);
+ varpool_add_node_removal_hook (&devirt_variable_node_removal_hook,
+ NULL);
+ }
}
/* Lookup cached answer. */
@@ -928,11 +962,8 @@ likely_target_p (struct cgraph_node *n)
}
/* The ipa-devirt pass.
- This performs very trivial devirtualization:
- 1) when polymorphic call is known to have precisely one target,
- turn it into direct call
- 2) when polymorphic call has only one likely target in the unit,
- turn it into speculative call. */
+ When polymorphic call has only one likely target in the unit,
+ turn it into speculative call. */
static unsigned int
ipa_devirt (void)
@@ -965,26 +996,9 @@ ipa_devirt (void)
if (dump_file)
dump_possible_polymorphic_call_targets
(dump_file, e);
+
npolymorphic++;
- if (final)
- {
- gcc_assert (targets.length());
- if (targets.length() == 1)
- {
- if (dump_file)
- fprintf (dump_file,
- "Devirtualizing call in %s/%i to %s/%i\n",
- cgraph_node_name (n), n->symbol.order,
- cgraph_node_name (targets[0]), targets[0]->symbol.order);
- cgraph_make_edge_direct (e, targets[0]);
- ndevirtualized++;
- update = true;
- continue;
- }
- }
- if (!flag_devirtualize_speculatively)
- continue;
if (!cgraph_maybe_hot_edge_p (e))
{
if (dump_file)
@@ -1114,7 +1128,7 @@ ipa_devirt (void)
static bool
gate_ipa_devirt (void)
{
- return flag_devirtualize && !in_lto_p && optimize;
+ return flag_devirtualize_speculatively && !in_lto_p && optimize;
}
namespace {