diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2014-10-05 07:02:19 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2014-10-05 05:02:19 +0000 |
commit | 0127c169d155ecdad955d1b27cbc9e34ea981d42 (patch) | |
tree | d2428ebac5861155cb99905a9e92c774a2f64be7 /gcc/ipa-polymorphic-call.c | |
parent | 2add94cd4415d64ea2a075abfa1ce74a9ee39053 (diff) | |
download | gcc-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.c | 38 |
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 |