cgraph.h (cgraph_indirect_call_info): Removed field thunk_delta.

2011-09-02  Martin Jambor  <mjambor@suse.cz>

	* cgraph.h (cgraph_indirect_call_info): Removed field thunk_delta.
	* gimple-fold.c (gimple_get_virt_method_for_binfo): Rewritten to use
	BINFO_VTABLE.  Parameter delta removed, all callers updated.
	* tree.c (free_lang_data_in_binfo): Clear BINFO_VIRTUALs instead
	BINFO_VTABLE.
	* cgraph.c (cgraph_make_edge_direct): Removed parameter delta, updated
	all calls.
	* cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Removed
	handling of thunk_delta.
	* ipa-cp.c (get_indirect_edge_target): Removed parameter delta.
	(devirtualization_time_bonus): Do not handle thunk deltas.
	(ipcp_discover_new_direct_edges): Likewise.
	* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
	(try_make_edge_direct_simple_call): Likewise.
	(try_make_edge_direct_virtual_call): Likewise.
	* lto-cgraph.c (output_cgraph_opt_summary_p): Likewise.  Mark
	parameter set as unused.
	(output_edge_opt_summary): Likewise.  Mark both parameters as unused.
	* lto-cgraph.c (output_cgraph_opt_summary_p): Likewise.  Mark
	parameter set as unused.
	(output_edge_opt_summary): Likewise.  Mark both parameters as unused.
	(input_edge_opt_summary): Likewise.
	* lto-streamer-out.c (lto_output_ts_binfo_tree_pointers): Do not stream
	BINFO_VIRTUALS at all.
	* lto-streamer-in.c (lto_input_ts_binfo_tree_pointers): Likewise.

	* testsuite/g++.dg/ipa/devirt-3.C: Added a distraction method.
	* testsuite/g++.dg/ipa/ivinline-7.C: Added a test for direct call
	discovery, xfailed test for inlining.
	* testsuite/g++.dg/ipa/ivinline-9.C: Likewise.

From-SVN: r178472
This commit is contained in:
Martin Jambor 2011-09-02 15:26:30 +02:00 committed by Martin Jambor
parent 5d882cc1da
commit 81fa35bd59
17 changed files with 135 additions and 151 deletions

View File

@ -1,3 +1,31 @@
2011-09-02 Martin Jambor <mjambor@suse.cz>
* cgraph.h (cgraph_indirect_call_info): Removed field thunk_delta.
* gimple-fold.c (gimple_get_virt_method_for_binfo): Rewritten to use
BINFO_VTABLE. Parameter delta removed, all callers updated.
* tree.c (free_lang_data_in_binfo): Clear BINFO_VIRTUALs instead
BINFO_VTABLE.
* cgraph.c (cgraph_make_edge_direct): Removed parameter delta, updated
all calls.
* cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Removed
handling of thunk_delta.
* ipa-cp.c (get_indirect_edge_target): Removed parameter delta.
(devirtualization_time_bonus): Do not handle thunk deltas.
(ipcp_discover_new_direct_edges): Likewise.
* ipa-prop.c (ipa_make_edge_direct_to_target): Likewise.
(try_make_edge_direct_simple_call): Likewise.
(try_make_edge_direct_virtual_call): Likewise.
* lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
parameter set as unused.
(output_edge_opt_summary): Likewise. Mark both parameters as unused.
* lto-cgraph.c (output_cgraph_opt_summary_p): Likewise. Mark
parameter set as unused.
(output_edge_opt_summary): Likewise. Mark both parameters as unused.
(input_edge_opt_summary): Likewise.
* lto-streamer-out.c (lto_output_ts_binfo_tree_pointers): Do not stream
BINFO_VIRTUALS at all.
* lto-streamer-in.c (lto_input_ts_binfo_tree_pointers): Likewise.
2011-09-02 Richard Guenther <rguenther@suse.de> 2011-09-02 Richard Guenther <rguenther@suse.de>
* tree-ssa-ccp.c (fold_builtin_alloca_for_var): Do not * tree-ssa-ccp.c (fold_builtin_alloca_for_var): Do not

View File

@ -835,7 +835,7 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt)
struct cgraph_node *new_callee = cgraph_get_node (decl); struct cgraph_node *new_callee = cgraph_get_node (decl);
gcc_checking_assert (new_callee); gcc_checking_assert (new_callee);
cgraph_make_edge_direct (e, new_callee, 0); cgraph_make_edge_direct (e, new_callee);
} }
push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
@ -1161,11 +1161,9 @@ cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n)
pointer (first parameter) to compensate for skipping a thunk adjustment. */ pointer (first parameter) to compensate for skipping a thunk adjustment. */
void void
cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee, cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee)
HOST_WIDE_INT delta)
{ {
edge->indirect_unknown_callee = 0; edge->indirect_unknown_callee = 0;
edge->indirect_info->thunk_delta = delta;
/* Get the edge out of the indirect edge list. */ /* Get the edge out of the indirect edge list. */
if (edge->prev_callee) if (edge->prev_callee)

View File

@ -314,9 +314,6 @@ struct GTY(()) cgraph_indirect_call_info
HOST_WIDE_INT anc_offset; HOST_WIDE_INT anc_offset;
/* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */ /* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */
HOST_WIDE_INT otr_token; HOST_WIDE_INT otr_token;
/* Delta by which must be added to this parameter to compensate for a skipped
this adjusting thunk. */
HOST_WIDE_INT thunk_delta;
/* Type of the object from OBJ_TYPE_REF_OBJECT. */ /* Type of the object from OBJ_TYPE_REF_OBJECT. */
tree otr_type; tree otr_type;
/* Index of the parameter that is called. */ /* Index of the parameter that is called. */
@ -507,8 +504,7 @@ struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type,
struct cgraph_node *cgraph_create_function_alias (tree, tree); struct cgraph_node *cgraph_create_function_alias (tree, tree);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *); void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *, void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
HOST_WIDE_INT);
bool cgraph_only_called_directly_p (struct cgraph_node *); bool cgraph_only_called_directly_p (struct cgraph_node *);
struct cgraph_asm_node *cgraph_add_asm_node (tree); struct cgraph_asm_node *cgraph_add_asm_node (tree);

View File

@ -2367,7 +2367,6 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
tree decl = gimple_call_fndecl (e->call_stmt); tree decl = gimple_call_fndecl (e->call_stmt);
gimple new_stmt; gimple new_stmt;
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
bool gsi_computed = false;
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
struct cgraph_node *node; struct cgraph_node *node;
#endif #endif
@ -2398,21 +2397,6 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
} }
} }
if (e->indirect_info &&
e->indirect_info->thunk_delta != 0
&& (!e->callee->clone.combined_args_to_skip
|| !bitmap_bit_p (e->callee->clone.combined_args_to_skip, 0)))
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file, " Thunk delta is "
HOST_WIDE_INT_PRINT_DEC "\n", e->indirect_info->thunk_delta);
gsi = gsi_for_stmt (e->call_stmt);
gsi_computed = true;
gimple_adjust_this_by_delta (&gsi,
size_int (e->indirect_info->thunk_delta));
e->indirect_info->thunk_delta = 0;
}
if (e->callee->clone.combined_args_to_skip) if (e->callee->clone.combined_args_to_skip)
{ {
int lp_nr; int lp_nr;
@ -2426,8 +2410,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
&& TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME) && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt; SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
if (!gsi_computed) gsi = gsi_for_stmt (e->call_stmt);
gsi = gsi_for_stmt (e->call_stmt);
gsi_replace (&gsi, new_stmt, false); gsi_replace (&gsi, new_stmt, false);
/* We need to defer cleaning EH info on the new statement to /* We need to defer cleaning EH info on the new statement to
fixup-cfg. We may not have dominator information at this point fixup-cfg. We may not have dominator information at this point

View File

@ -982,51 +982,6 @@ gimple_fold_builtin (gimple stmt)
return result; return result;
} }
/* Return a declaration of a function which an OBJ_TYPE_REF references. TOKEN
is integer form of OBJ_TYPE_REF_TOKEN of the reference expression.
KNOWN_BINFO carries the binfo describing the true type of
OBJ_TYPE_REF_OBJECT(REF). If a call to the function must be accompanied
with a this adjustment, the constant which should be added to this pointer
is stored to *DELTA. If REFUSE_THUNKS is true, return NULL if the function
is a thunk (other than a this adjustment which is dealt with by DELTA). */
tree
gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo,
tree *delta)
{
HOST_WIDE_INT i;
tree v, fndecl;
v = BINFO_VIRTUALS (known_binfo);
/* If there is no virtual methods leave the OBJ_TYPE_REF alone. */
if (!v)
return NULL_TREE;
i = 0;
while (i != token)
{
i += (TARGET_VTABLE_USES_DESCRIPTORS
? TARGET_VTABLE_USES_DESCRIPTORS : 1);
v = TREE_CHAIN (v);
}
/* If BV_VCALL_INDEX is non-NULL, give up. */
if (TREE_TYPE (v))
return NULL_TREE;
fndecl = TREE_VALUE (v);
/* When cgraph node is missing and function is not public, we cannot
devirtualize. This can happen in WHOPR when the actual method
ends up in other partition, because we found devirtualization
possibility too late. */
if (!can_refer_decl_in_current_unit_p (TREE_VALUE (v)))
return NULL_TREE;
*delta = TREE_PURPOSE (v);
gcc_checking_assert (host_integerp (*delta, 0));
return fndecl;
}
/* Generate code adjusting the first parameter of a call statement determined /* Generate code adjusting the first parameter of a call statement determined
by GSI by DELTA. */ by GSI by DELTA. */
@ -1149,7 +1104,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
callee = gimple_call_fn (stmt); callee = gimple_call_fn (stmt);
if (callee && TREE_CODE (callee) == OBJ_TYPE_REF) if (callee && TREE_CODE (callee) == OBJ_TYPE_REF)
{ {
tree binfo, fndecl, delta, obj; tree binfo, fndecl, obj;
HOST_WIDE_INT token; HOST_WIDE_INT token;
if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE) if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
@ -1163,10 +1118,9 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
if (!binfo) if (!binfo)
return false; return false;
token = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee)); token = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
fndecl = gimple_get_virt_method_for_binfo (token, binfo, &delta); fndecl = gimple_get_virt_method_for_binfo (token, binfo);
if (!fndecl) if (!fndecl)
return false; return false;
gcc_assert (integer_zerop (delta));
gimple_call_set_fndecl (stmt, fndecl); gimple_call_set_fndecl (stmt, fndecl);
return true; return true;
} }
@ -3064,6 +3018,60 @@ fold_const_aggregate_ref (tree t)
return fold_const_aggregate_ref_1 (t, NULL); return fold_const_aggregate_ref_1 (t, NULL);
} }
/* Return a declaration of a function which an OBJ_TYPE_REF references. TOKEN
is integer form of OBJ_TYPE_REF_TOKEN of the reference expression.
KNOWN_BINFO carries the binfo describing the true type of
OBJ_TYPE_REF_OBJECT(REF). */
tree
gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
{
unsigned HOST_WIDE_INT offset, size;
tree v, fn;
v = BINFO_VTABLE (known_binfo);
/* If there is no virtual methods table, leave the OBJ_TYPE_REF alone. */
if (!v)
return NULL_TREE;
if (TREE_CODE (v) == POINTER_PLUS_EXPR)
{
offset = tree_low_cst (TREE_OPERAND (v, 1), 1) * BITS_PER_UNIT;
v = TREE_OPERAND (v, 0);
}
else
offset = 0;
if (TREE_CODE (v) != ADDR_EXPR)
return NULL_TREE;
v = TREE_OPERAND (v, 0);
if (TREE_CODE (v) != VAR_DECL
|| !DECL_VIRTUAL_P (v)
|| !DECL_INITIAL (v))
return NULL_TREE;
gcc_checking_assert (TREE_CODE (TREE_TYPE (v)) == ARRAY_TYPE);
size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (v))), 1);
offset += token * size;
fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), DECL_INITIAL (v),
offset, size);
if (!fn)
return NULL_TREE;
gcc_assert (TREE_CODE (fn) == ADDR_EXPR
|| TREE_CODE (fn) == FDESC_EXPR);
fn = TREE_OPERAND (fn, 0);
gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
/* When cgraph node is missing and function is not public, we cannot
devirtualize. This can happen in WHOPR when the actual method
ends up in other partition, because we found devirtualization
possibility too late. */
if (!can_refer_decl_in_current_unit_p (fn))
return NULL_TREE;
return fn;
}
/* Return true iff VAL is a gimple expression that is known to be /* Return true iff VAL is a gimple expression that is known to be
non-negative. Restricted to floating-point inputs. */ non-negative. Restricted to floating-point inputs. */

View File

@ -909,7 +909,7 @@ unsigned get_gimple_rhs_num_ops (enum tree_code);
gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL); gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
const char *gimple_decl_printable_name (tree, int); const char *gimple_decl_printable_name (tree, int);
bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace); bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace);
tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree, tree *); tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree); void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree);
tree gimple_extract_devirt_binfo_from_cst (tree); tree gimple_extract_devirt_binfo_from_cst (tree);
/* Returns true iff T is a valid GIMPLE statement. */ /* Returns true iff T is a valid GIMPLE statement. */

View File

@ -1110,11 +1110,10 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
/* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS
(which can contain both constants and binfos) or KNOWN_BINFOS (which can be (which can contain both constants and binfos) or KNOWN_BINFOS (which can be
NULL) return the destination. If simple thunk delta must be applied too, NULL) return the destination. */
store it to DELTA. */
static tree static tree
get_indirect_edge_target (struct cgraph_edge *ie, tree *delta, get_indirect_edge_target (struct cgraph_edge *ie,
VEC (tree, heap) *known_vals, VEC (tree, heap) *known_vals,
VEC (tree, heap) *known_binfos) VEC (tree, heap) *known_binfos)
{ {
@ -1132,10 +1131,7 @@ get_indirect_edge_target (struct cgraph_edge *ie, tree *delta,
if (t && if (t &&
TREE_CODE (t) == ADDR_EXPR TREE_CODE (t) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL) && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
{ return TREE_OPERAND (t, 0);
*delta = NULL_TREE;
return TREE_OPERAND (t, 0);
}
else else
return NULL_TREE; return NULL_TREE;
} }
@ -1159,7 +1155,7 @@ get_indirect_edge_target (struct cgraph_edge *ie, tree *delta,
binfo = get_binfo_at_offset (binfo, anc_offset, otr_type); binfo = get_binfo_at_offset (binfo, anc_offset, otr_type);
if (!binfo) if (!binfo)
return NULL_TREE; return NULL_TREE;
return gimple_get_virt_method_for_binfo (token, binfo, delta); return gimple_get_virt_method_for_binfo (token, binfo);
} }
else else
{ {
@ -1168,7 +1164,7 @@ get_indirect_edge_target (struct cgraph_edge *ie, tree *delta,
binfo = get_binfo_at_offset (t, anc_offset, otr_type); binfo = get_binfo_at_offset (t, anc_offset, otr_type);
if (!binfo) if (!binfo)
return NULL_TREE; return NULL_TREE;
return gimple_get_virt_method_for_binfo (token, binfo, delta); return gimple_get_virt_method_for_binfo (token, binfo);
} }
} }
@ -1187,9 +1183,9 @@ devirtualization_time_bonus (struct cgraph_node *node,
{ {
struct cgraph_node *callee; struct cgraph_node *callee;
struct inline_summary *isummary; struct inline_summary *isummary;
tree delta, target; tree target;
target = get_indirect_edge_target (ie, &delta, known_csts, known_binfos); target = get_indirect_edge_target (ie, known_csts, known_binfos);
if (!target) if (!target)
continue; continue;
@ -1674,12 +1670,12 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node,
for (ie = node->indirect_calls; ie; ie = next_ie) for (ie = node->indirect_calls; ie; ie = next_ie)
{ {
tree delta, target; tree target;
next_ie = ie->next_callee; next_ie = ie->next_callee;
target = get_indirect_edge_target (ie, &delta, known_vals, NULL); target = get_indirect_edge_target (ie, known_vals, NULL);
if (target) if (target)
ipa_make_edge_direct_to_target (ie, target, delta); ipa_make_edge_direct_to_target (ie, target);
} }
} }

View File

@ -1614,12 +1614,10 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs,
} }
/* If TARGET is an addr_expr of a function declaration, make it the destination /* If TARGET is an addr_expr of a function declaration, make it the destination
of an indirect edge IE and return the edge. Otherwise, return NULL. Delta, of an indirect edge IE and return the edge. Otherwise, return NULL. */
if non-NULL, is an integer constant that must be added to this pointer
(first parameter). */
struct cgraph_edge * struct cgraph_edge *
ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, tree delta) ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
{ {
struct cgraph_node *callee; struct cgraph_node *callee;
@ -1632,11 +1630,11 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, tree delta)
return NULL; return NULL;
ipa_check_create_node_params (); ipa_check_create_node_params ();
/* We can not make edges to inline clones. It is bug that someone removed the cgraph /* We can not make edges to inline clones. It is bug that someone removed
node too early. */ the cgraph node too early. */
gcc_assert (!callee->global.inlined_to); gcc_assert (!callee->global.inlined_to);
cgraph_make_edge_direct (ie, callee, delta ? tree_low_cst (delta, 0) : 0); cgraph_make_edge_direct (ie, callee);
if (dump_file) if (dump_file)
{ {
fprintf (dump_file, "ipa-prop: Discovered %s call to a known target " fprintf (dump_file, "ipa-prop: Discovered %s call to a known target "
@ -1648,13 +1646,6 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, tree delta)
print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM); print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM);
else else
fprintf (dump_file, "with uid %i\n", ie->lto_stmt_uid); fprintf (dump_file, "with uid %i\n", ie->lto_stmt_uid);
if (delta)
{
fprintf (dump_file, " Thunk delta is ");
print_generic_expr (dump_file, delta, 0);
fprintf (dump_file, "\n");
}
} }
callee = cgraph_function_or_thunk_node (callee, NULL); callee = cgraph_function_or_thunk_node (callee, NULL);
@ -1683,7 +1674,7 @@ try_make_edge_direct_simple_call (struct cgraph_edge *ie,
else else
return NULL; return NULL;
return ipa_make_edge_direct_to_target (ie, target, NULL_TREE); return ipa_make_edge_direct_to_target (ie, target);
} }
/* Try to find a destination for indirect edge IE that corresponds to a /* Try to find a destination for indirect edge IE that corresponds to a
@ -1695,7 +1686,7 @@ static struct cgraph_edge *
try_make_edge_direct_virtual_call (struct cgraph_edge *ie, try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
struct ipa_jump_func *jfunc) struct ipa_jump_func *jfunc)
{ {
tree binfo, type, target, delta; tree binfo, type, target;
HOST_WIDE_INT token; HOST_WIDE_INT token;
if (jfunc->type == IPA_JF_KNOWN_TYPE) if (jfunc->type == IPA_JF_KNOWN_TYPE)
@ -1710,12 +1701,12 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
type = ie->indirect_info->otr_type; type = ie->indirect_info->otr_type;
binfo = get_binfo_at_offset (binfo, ie->indirect_info->anc_offset, type); binfo = get_binfo_at_offset (binfo, ie->indirect_info->anc_offset, type);
if (binfo) if (binfo)
target = gimple_get_virt_method_for_binfo (token, binfo, &delta); target = gimple_get_virt_method_for_binfo (token, binfo);
else else
return NULL; return NULL;
if (target) if (target)
return ipa_make_edge_direct_to_target (ie, target, delta); return ipa_make_edge_direct_to_target (ie, target);
else else
return NULL; return NULL;
} }

View File

@ -367,8 +367,7 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
VEC (cgraph_edge_p, heap) **new_edges); VEC (cgraph_edge_p, heap) **new_edges);
/* Indirect edge and binfo processing. */ /* Indirect edge and binfo processing. */
struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree, struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree);
tree);
/* Functions related to both. */ /* Functions related to both. */
void ipa_analyze_node (struct cgraph_node *); void ipa_analyze_node (struct cgraph_node *);

View File

@ -1501,22 +1501,9 @@ input_cgraph (void)
/* True when we need optimization summary for NODE. */ /* True when we need optimization summary for NODE. */
static int static int
output_cgraph_opt_summary_p (struct cgraph_node *node, cgraph_node_set set) output_cgraph_opt_summary_p (struct cgraph_node *node,
cgraph_node_set set ATTRIBUTE_UNUSED)
{ {
struct cgraph_edge *e;
if (cgraph_node_in_set_p (node, set))
{
for (e = node->callees; e; e = e->next_callee)
if (e->indirect_info
&& e->indirect_info->thunk_delta != 0)
return true;
for (e = node->indirect_calls; e; e = e->next_callee)
if (e->indirect_info->thunk_delta != 0)
return true;
}
return (node->clone_of return (node->clone_of
&& (node->clone.tree_map && (node->clone.tree_map
|| node->clone.args_to_skip || node->clone.args_to_skip
@ -1525,13 +1512,9 @@ output_cgraph_opt_summary_p (struct cgraph_node *node, cgraph_node_set set)
/* Output optimization summary for EDGE to OB. */ /* Output optimization summary for EDGE to OB. */
static void static void
output_edge_opt_summary (struct output_block *ob, output_edge_opt_summary (struct output_block *ob ATTRIBUTE_UNUSED,
struct cgraph_edge *edge) struct cgraph_edge *edge ATTRIBUTE_UNUSED)
{ {
if (edge->indirect_info)
streamer_write_hwi (ob, edge->indirect_info->thunk_delta);
else
streamer_write_hwi (ob, 0);
} }
/* Output optimization summary for NODE to OB. */ /* Output optimization summary for NODE to OB. */
@ -1631,17 +1614,9 @@ output_cgraph_opt_summary (cgraph_node_set set)
/* Input optimisation summary of EDGE. */ /* Input optimisation summary of EDGE. */
static void static void
input_edge_opt_summary (struct cgraph_edge *edge, input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED,
struct lto_input_block *ib_main) struct lto_input_block *ib_main ATTRIBUTE_UNUSED)
{ {
HOST_WIDE_INT thunk_delta;
thunk_delta = streamer_read_hwi (ib_main);
if (thunk_delta != 0)
{
gcc_assert (!edge->indirect_info);
edge->indirect_info = cgraph_allocate_init_indirect_info ();
edge->indirect_info->thunk_delta = thunk_delta;
}
} }
/* Input optimisation summary of NODE. */ /* Input optimisation summary of NODE. */

View File

@ -1,3 +1,10 @@
2011-09-02 Martin Jambor <mjambor@suse.cz>
* g++.dg/ipa/devirt-3.C: Added a distraction method.
* g++.dg/ipa/ivinline-7.C: Added a test for direct call discovery,
xfailed test for inlining.
* g++.dg/ipa/ivinline-9.C: Likewise.
2011-09-01 Ira Rosen <ira.rosen@linaro.org> 2011-09-01 Ira Rosen <ira.rosen@linaro.org>
PR tree-optimization/50178 PR tree-optimization/50178

View File

@ -9,6 +9,7 @@ class A
{ {
public: public:
int data; int data;
virtual float distraction (float f);
virtual int foo (int i); virtual int foo (int i);
}; };
@ -24,6 +25,12 @@ public:
virtual int foo (int i); virtual int foo (int i);
}; };
float A::distraction (float f)
{
f += 6.2;
return f/2;
}
int A::foo (int i) int A::foo (int i)
{ {
return i + 1; return i + 1;

View File

@ -75,5 +75,6 @@ int main (int argc, char *argv[])
return 0; return 0;
} }
/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" } } */ /* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::.*foo" "inline" } } */
/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" { xfail *-*-* } } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */ /* { dg-final { cleanup-ipa-dump "inline" } } */

View File

@ -89,5 +89,6 @@ int main (int argc, char *argv[])
return 0; return 0;
} }
/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" } } */ /* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target.*B::.*foo" "inline" } } */
/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline" { xfail *-*-* } } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */ /* { dg-final { cleanup-ipa-dump "inline" } } */

View File

@ -841,7 +841,6 @@ lto_input_ts_binfo_tree_pointers (struct lto_input_block *ib,
BINFO_OFFSET (expr) = stream_read_tree (ib, data_in); BINFO_OFFSET (expr) = stream_read_tree (ib, data_in);
BINFO_VTABLE (expr) = stream_read_tree (ib, data_in); BINFO_VTABLE (expr) = stream_read_tree (ib, data_in);
BINFO_VIRTUALS (expr) = stream_read_tree (ib, data_in);
BINFO_VPTR_FIELD (expr) = stream_read_tree (ib, data_in); BINFO_VPTR_FIELD (expr) = stream_read_tree (ib, data_in);
len = streamer_read_uhwi (ib); len = streamer_read_uhwi (ib);

View File

@ -701,11 +701,6 @@ write_ts_binfo_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
stream_write_tree (ob, BINFO_OFFSET (expr), ref_p); stream_write_tree (ob, BINFO_OFFSET (expr), ref_p);
stream_write_tree (ob, BINFO_VTABLE (expr), ref_p); stream_write_tree (ob, BINFO_VTABLE (expr), ref_p);
/* BINFO_VIRTUALS is used to drive type based devirtualizatoin. It often links
together large portions of programs making it harder to partition. Becuase
devirtualization is interesting before inlining, only, there is no real
need to ship it into ltrans partition. */
stream_write_tree (ob, flag_wpa ? NULL : BINFO_VIRTUALS (expr), ref_p);
stream_write_tree (ob, BINFO_VPTR_FIELD (expr), ref_p); stream_write_tree (ob, BINFO_VPTR_FIELD (expr), ref_p);
streamer_write_uhwi (ob, VEC_length (tree, BINFO_BASE_ACCESSES (expr))); streamer_write_uhwi (ob, VEC_length (tree, BINFO_BASE_ACCESSES (expr)));

View File

@ -4397,7 +4397,7 @@ free_lang_data_in_one_sizepos (tree *expr_p)
/* Reset all the fields in a binfo node BINFO. We only keep /* Reset all the fields in a binfo node BINFO. We only keep
BINFO_VIRTUALS, which is used by gimple_fold_obj_type_ref. */ BINFO_VTABLE, which is used by gimple_fold_obj_type_ref. */
static void static void
free_lang_data_in_binfo (tree binfo) free_lang_data_in_binfo (tree binfo)
@ -4407,7 +4407,7 @@ free_lang_data_in_binfo (tree binfo)
gcc_assert (TREE_CODE (binfo) == TREE_BINFO); gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
BINFO_VTABLE (binfo) = NULL_TREE; BINFO_VIRTUALS (binfo) = NULL_TREE;
BINFO_BASE_ACCESSES (binfo) = NULL; BINFO_BASE_ACCESSES (binfo) = NULL;
BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE; BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
BINFO_SUBVTT_INDEX (binfo) = NULL_TREE; BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;