aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-polymorphic-call.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-10-05 07:02:19 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2014-10-05 05:02:19 +0000
commit0127c169d155ecdad955d1b27cbc9e34ea981d42 (patch)
treed2428ebac5861155cb99905a9e92c774a2f64be7 /gcc/ipa-polymorphic-call.c
parent2add94cd4415d64ea2a075abfa1ce74a9ee39053 (diff)
downloadgcc-0127c169d155ecdad955d1b27cbc9e34ea981d42.zip
gcc-0127c169d155ecdad955d1b27cbc9e34ea981d42.tar.gz
gcc-0127c169d155ecdad955d1b27cbc9e34ea981d42.tar.bz2
ipa-polymorphic-call.c (walk_ssa_copies): Recognize NULL pointer checks.
* ipa-polymorphic-call.c (walk_ssa_copies): Recognize NULL pointer checks. (ipa_polymorphic_call_context::get_dynamic_type): Return true if type doesn't change. * cgraph.h (cgraph_indirect_call_info): New flag. * cgraph.c (cgraph_node::create_indirect_edge): Initialize it. (cgraph_node::dump): Dump it. * ipa-prop.c (ipa_analyze_call_uses): Ignore return valud of context.get_dynamic_type. (ipa_make_edge_direct_to_target): Do not speculate edge that is already speuclative. (try_make_edge_direct_virtual_call): Use VPTR_CHANGED; Do not speculate to __builtin_unreachable (ipa_write_indirect_edge_info, ipa_read_indirect_edge_info): Stream vptr_changed. * ipa-cp.c (ipa_get_indirect_edge_target_1): Use vptr_changed. * g++.dg/ipa/devirt-47.C: New testcase. From-SVN: r215898
Diffstat (limited to 'gcc/ipa-polymorphic-call.c')
-rw-r--r--gcc/ipa-polymorphic-call.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c
index ecbd78c..74226f2 100644
--- a/gcc/ipa-polymorphic-call.c
+++ b/gcc/ipa-polymorphic-call.c
@@ -760,11 +760,37 @@ walk_ssa_copies (tree op)
while (TREE_CODE (op) == SSA_NAME
&& !SSA_NAME_IS_DEFAULT_DEF (op)
&& SSA_NAME_DEF_STMT (op)
- && gimple_assign_single_p (SSA_NAME_DEF_STMT (op)))
+ && (gimple_assign_single_p (SSA_NAME_DEF_STMT (op))
+ || gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI))
{
- if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
- return op;
- op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
+ /* Special case
+ if (ptr == 0)
+ ptr = 0;
+ else
+ ptr = ptr.foo;
+ This pattern is implicitly produced for casts to non-primary
+ bases. When doing context analysis, we do not really care
+ about the case pointer is NULL, becuase the call will be
+ undefined anyway. */
+ if (gimple_code (SSA_NAME_DEF_STMT (op)) == GIMPLE_PHI)
+ {
+ gimple phi = SSA_NAME_DEF_STMT (op);
+
+ if (gimple_phi_num_args (phi) != 2)
+ return op;
+ if (integer_zerop (gimple_phi_arg_def (phi, 0)))
+ op = gimple_phi_arg_def (phi, 1);
+ else if (integer_zerop (gimple_phi_arg_def (phi, 1)))
+ op = gimple_phi_arg_def (phi, 0);
+ else
+ return op;
+ }
+ else
+ {
+ if (gimple_assign_load_p (SSA_NAME_DEF_STMT (op)))
+ return op;
+ op = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (op));
+ }
STRIP_NOPS (op);
}
return op;
@@ -1371,6 +1397,8 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
is set), try to walk memory writes and find the actual construction of the
instance.
+ Return true if memory is unchanged from function entry.
+
We do not include this analysis in the context analysis itself, because
it needs memory SSA to be fully built and the walk may be expensive.
So it is not suitable for use withing fold_stmt and similar uses. */
@@ -1615,7 +1643,7 @@ ipa_polymorphic_call_context::get_dynamic_type (tree instance,
function_entry_reached ? " (multiple types encountered)" : "");
}
- return true;
+ return false;
}
/* See if speculation given by SPEC_OUTER_TYPE, SPEC_OFFSET and SPEC_MAYBE_DERIVED_TYPE