diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-02-03 20:41:30 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-02-03 20:41:30 +0000 |
commit | 02636da31efc7369d7ebe5a4bb190627ca8150ac (patch) | |
tree | ae16bce09c999f0a1aa07a51255fd97b90ea03c7 /gcc/ipa-cp.c | |
parent | 9cf883aa1a39b1a8db9028b36d3292005202193b (diff) | |
download | gcc-02636da31efc7369d7ebe5a4bb190627ca8150ac.tar.gz |
PR ipa/59831
* g++.dg/ipa/devirt-24.C: New testcase.
* ipa-cp.c (ipa_get_indirect_edge_target_1): Give up on -fno-devirtualize;
Try to devirtualize by the knowledge of virtual table pointer given by
aggregate propagation.
* ipa-prop.c (try_make_edge_direct_virtual_call): Likewise.
ipa_print_node_jump_functions): Dump also offset that
is relevant for polymorphic calls.
(determine_known_aggregate_parts): Add arg_type parameter; use it
instead of determining the type from pointer type.
(ipa_compute_jump_functions_for_edge): Update call of
determine_known_aggregate_parts.
* gimple-fold.c (gimple_get_virt_method_for_vtable): Break out from ...
(gimple_get_virt_method_for_binfo): ... here; simplify using
vtable_pointer_value_to_vtable.
* gimple-fold.h (gimple_get_virt_method_for_vtable): Declare.
* ipa-devirt.c (subbinfo_with_vtable_at_offset): Turn OFFSET parameter
to unsigned HOST_WIDE_INT; Use vtable_pointer_value_to_vtable.
(vtable_pointer_value_to_vtable): Break out from ...; handle also
POINTER_PLUS_EXPR.
(vtable_pointer_value_to_binfo): ... here.
* ipa-utils.h (vtable_pointer_value_to_vtable): Declare.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207439 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-cp.c')
-rw-r--r-- | gcc/ipa-cp.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 10fa4b6c236..18a5a03a5e1 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -1479,7 +1479,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, HOST_WIDE_INT token, anc_offset; tree otr_type; tree t; - tree target; + tree target = NULL; if (param_index == -1 || known_vals.length () <= (unsigned int) param_index) @@ -1527,14 +1527,53 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, return NULL_TREE; } + if (!flag_devirtualize) + return NULL_TREE; + gcc_assert (!ie->indirect_info->agg_contents); token = ie->indirect_info->otr_token; anc_offset = ie->indirect_info->offset; otr_type = ie->indirect_info->otr_type; - t = known_vals[param_index]; + t = NULL; + + /* Try to work out value of virtual table pointer value in replacemnets. */ + if (!t && agg_reps && !ie->indirect_info->by_ref) + { + while (agg_reps) + { + if (agg_reps->index == param_index + && agg_reps->offset == ie->indirect_info->offset + && agg_reps->by_ref) + { + t = agg_reps->value; + break; + } + agg_reps = agg_reps->next; + } + } + + /* Try to work out value of virtual table pointer value in known + aggregate values. */ + if (!t && known_aggs.length () > (unsigned int) param_index + && !ie->indirect_info->by_ref) + { + struct ipa_agg_jump_function *agg; + agg = known_aggs[param_index]; + t = ipa_find_agg_cst_for_param (agg, ie->indirect_info->offset, + true); + } + + /* If we found the virtual table pointer, lookup the binfo. */ + if (t) + t = vtable_pointer_value_to_binfo (t); + + /* Did we work out BINFO via type propagation? */ if (!t && known_binfos.length () > (unsigned int) param_index) t = known_binfos[param_index]; + /* Or do we know the constant value of pointer? */ + if (!t) + t = known_vals[param_index]; if (!t) return NULL_TREE; |