cgraph.c (cgraph_create_indirect_edge): Discover polymorphic calls and record basic info into indirect_info.
* cgraph.c (cgraph_create_indirect_edge): Discover polymorphic calls and record basic info into indirect_info. * gimple-fold.c (gimple_fold_call): When doing BINFO based devirtualization, ignore objc function calls. * ipa-cp.c (initialize_node_lattices): Be ready for polymorphic call with no parm index info. * ipa-prop.c (ipa_analyze_call_uses): Likewise. * tree.c (virtual_method_call_p): New function. * tree.h (virtual_method_call_p): Declare. From-SVN: r201824
This commit is contained in:
parent
34fdd6b31e
commit
1d5755efee
7 changed files with 56 additions and 3 deletions
|
@ -1,3 +1,15 @@
|
|||
2013-08-18 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* cgraph.c (cgraph_create_indirect_edge): Discover
|
||||
polymorphic calls and record basic info into indirect_info.
|
||||
* gimple-fold.c (gimple_fold_call): When doing BINFO based
|
||||
devirtualization, ignore objc function calls.
|
||||
* ipa-cp.c (initialize_node_lattices): Be ready for polymorphic
|
||||
call with no parm index info.
|
||||
* ipa-prop.c (ipa_analyze_call_uses): Likewise.
|
||||
* tree.c (virtual_method_call_p): New function.
|
||||
* tree.h (virtual_method_call_p): Declare.
|
||||
|
||||
2013-08-16 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR middle-end/58179
|
||||
|
|
18
gcc/cgraph.c
18
gcc/cgraph.c
|
@ -925,6 +925,7 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
|
|||
{
|
||||
struct cgraph_edge *edge = cgraph_create_edge_1 (caller, NULL, call_stmt,
|
||||
count, freq);
|
||||
tree target;
|
||||
|
||||
edge->indirect_unknown_callee = 1;
|
||||
initialize_inline_failed (edge);
|
||||
|
@ -932,6 +933,23 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
|
|||
edge->indirect_info = cgraph_allocate_init_indirect_info ();
|
||||
edge->indirect_info->ecf_flags = ecf_flags;
|
||||
|
||||
/* Record polymorphic call info. */
|
||||
if (call_stmt
|
||||
&& (target = gimple_call_fn (call_stmt))
|
||||
&& virtual_method_call_p (target))
|
||||
{
|
||||
tree type = obj_type_ref_class (target);
|
||||
|
||||
|
||||
/* Only record types can have virtual calls. */
|
||||
gcc_assert (TREE_CODE (type) == RECORD_TYPE);
|
||||
edge->indirect_info->param_index = -1;
|
||||
edge->indirect_info->otr_token
|
||||
= tree_low_cst (OBJ_TYPE_REF_TOKEN (target), 1);
|
||||
edge->indirect_info->otr_type = type;
|
||||
edge->indirect_info->polymorphic = 1;
|
||||
}
|
||||
|
||||
edge->next_callee = caller->indirect_calls;
|
||||
if (caller->indirect_calls)
|
||||
caller->indirect_calls->prev_callee = edge;
|
||||
|
|
|
@ -1105,7 +1105,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
|
|||
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
else if (virtual_method_call_p (callee))
|
||||
{
|
||||
tree obj = OBJ_TYPE_REF_OBJECT (callee);
|
||||
tree binfo = gimple_extract_devirt_binfo_from_cst
|
||||
|
|
|
@ -734,7 +734,8 @@ initialize_node_lattices (struct cgraph_node *node)
|
|||
}
|
||||
|
||||
for (ie = node->indirect_calls; ie; ie = ie->next_callee)
|
||||
if (ie->indirect_info->polymorphic)
|
||||
if (ie->indirect_info->polymorphic
|
||||
&& ie->indirect_info->param_index >= 0)
|
||||
{
|
||||
gcc_checking_assert (ie->indirect_info->param_index >= 0);
|
||||
ipa_get_parm_lattices (info,
|
||||
|
|
|
@ -1922,7 +1922,7 @@ ipa_analyze_call_uses (struct cgraph_node *node,
|
|||
return;
|
||||
if (TREE_CODE (target) == SSA_NAME)
|
||||
ipa_analyze_indirect_call_uses (node, info, parms_ainfo, call, target);
|
||||
else if (TREE_CODE (target) == OBJ_TYPE_REF)
|
||||
else if (virtual_method_call_p (target))
|
||||
ipa_analyze_virtual_call_uses (node, info, call, target);
|
||||
}
|
||||
|
||||
|
|
21
gcc/tree.c
21
gcc/tree.c
|
@ -11864,6 +11864,27 @@ types_same_for_odr (tree type1, tree type2)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* TARGET is a call target of GIMPLE call statement
|
||||
(obtained by gimple_call_fn). Return true if it is
|
||||
OBJ_TYPE_REF representing an virtual call of C++ method.
|
||||
(As opposed to OBJ_TYPE_REF representing objc calls
|
||||
through a cast where middle-end devirtualization machinery
|
||||
can't apply.) */
|
||||
|
||||
bool
|
||||
virtual_method_call_p (tree target)
|
||||
{
|
||||
if (TREE_CODE (target) != OBJ_TYPE_REF)
|
||||
return false;
|
||||
target = TREE_TYPE (target);
|
||||
gcc_checking_assert (TREE_CODE (target) == POINTER_TYPE);
|
||||
target = TREE_TYPE (target);
|
||||
if (TREE_CODE (target) == FUNCTION_TYPE)
|
||||
return false;
|
||||
gcc_checking_assert (TREE_CODE (target) == METHOD_TYPE);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* REF is OBJ_TYPE_REF, return the class the ref corresponds to. */
|
||||
|
||||
tree
|
||||
|
|
|
@ -5974,6 +5974,7 @@ extern location_t tree_nonartificial_location (tree);
|
|||
extern tree block_ultimate_origin (const_tree);
|
||||
|
||||
extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree);
|
||||
extern bool virtual_method_call_p (tree);
|
||||
extern tree obj_type_ref_class (tree ref);
|
||||
extern bool types_same_for_odr (tree type1, tree type2);
|
||||
extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
|
||||
|
|
Loading…
Add table
Reference in a new issue