summaryrefslogtreecommitdiff
path: root/gcc/ipa-cp.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2014-02-03 20:41:30 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2014-02-03 20:41:30 +0000
commit02636da31efc7369d7ebe5a4bb190627ca8150ac (patch)
treeae16bce09c999f0a1aa07a51255fd97b90ea03c7 /gcc/ipa-cp.c
parent9cf883aa1a39b1a8db9028b36d3292005202193b (diff)
downloadgcc-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.c43
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;