Commit 68377e53 by Jan Hubicka Committed by Jan Hubicka

cgraph.c (cgraph_create_indirect_edge): Use get_polymorphic_call_info.


	* cgraph.c (cgraph_create_indirect_edge): Use get_polymorphic_call_info.
	* cgraph.h (cgraph_indirect_call_info): Add outer_type, maybe_in_construction
	and maybe_derived_type.
	* ipa-utils.h (ipa_polymorphic_call_context): New structure.
	(ipa_dummy_polymorphic_call_context): New global var.
	(possible_polymorphic_call_targets): Add context paramter.
	(dump_possible_polymorphic_call_targets): Likewise; update
	wrappers.
	(possible_polymorphic_call_target_p): Likewise.
	(get_polymorphic_call_info): New function.
	* ipa-devirt.c (ipa_dummy_polymorphic_call_context): New function.
	(add_type_duplicate): Remove forgotten debug output.
	(method_class_type): Add sanity check.
	(maybe_record_node): Add FINALP parameter.
	(record_binfo): Add OUTER_TYPE and OFFSET; walk the inner
	by info by get_binfo_at_offset.
	(possible_polymorphic_call_targets_1): Add OUTER_TYPE/OFFSET parameters;
	pass them to record-binfo.
	(polymorphic_call_target_d): Add context and FINAL.
	(polymorphic_call_target_hasher::hash): Hash context.
	(polymorphic_call_target_hasher::equal): Compare context.
	(free_polymorphic_call_targets_hash):
	(get_class_context): New function.
	(contains_type_p): New function.
	(get_polymorphic_call_info): New function.
	(walk_bases): New function.
	(possible_polymorphic_call_targets): Add context parameter; honnor it.
	(dump_possible_polymorphic_call_targets): Dump context.
	(possible_polymorphic_call_target_p): Add context.
	(update_type_inheritance_graph): Update comment.s
	(ipa_set_jf_known_type): Assert that compoentn type is known.
	(ipa_note_param_call): Do not tamper with offsets.
	(ipa_analyze_indirect_call_uses): When offset is being changed; clear
	outer type.
	(update_indirect_edges_after_inlining): Likewise.
	(ipa_write_indirect_edge_info): Stream new fields.
	(ipa_read_indirect_edge_info): Stream in new fields.

	* ipa/devirt9.C: Verify that the optimization happens already before.
	whole-program.

From-SVN: r205019
parent d345bb30
2013-11-19 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_create_indirect_edge): Use get_polymorphic_call_info.
* cgraph.h (cgraph_indirect_call_info): Add outer_type, maybe_in_construction
and maybe_derived_type.
* ipa-utils.h (ipa_polymorphic_call_context): New structure.
(ipa_dummy_polymorphic_call_context): New global var.
(possible_polymorphic_call_targets): Add context paramter.
(dump_possible_polymorphic_call_targets): Likewise; update
wrappers.
(possible_polymorphic_call_target_p): Likewise.
(get_polymorphic_call_info): New function.
* ipa-devirt.c (ipa_dummy_polymorphic_call_context): New function.
(add_type_duplicate): Remove forgotten debug output.
(method_class_type): Add sanity check.
(maybe_record_node): Add FINALP parameter.
(record_binfo): Add OUTER_TYPE and OFFSET; walk the inner
by info by get_binfo_at_offset.
(possible_polymorphic_call_targets_1): Add OUTER_TYPE/OFFSET parameters;
pass them to record-binfo.
(polymorphic_call_target_d): Add context and FINAL.
(polymorphic_call_target_hasher::hash): Hash context.
(polymorphic_call_target_hasher::equal): Compare context.
(free_polymorphic_call_targets_hash):
(get_class_context): New function.
(contains_type_p): New function.
(get_polymorphic_call_info): New function.
(walk_bases): New function.
(possible_polymorphic_call_targets): Add context parameter; honnor it.
(dump_possible_polymorphic_call_targets): Dump context.
(possible_polymorphic_call_target_p): Add context.
(update_type_inheritance_graph): Update comment.s
(ipa_set_jf_known_type): Assert that compoentn type is known.
(ipa_note_param_call): Do not tamper with offsets.
(ipa_analyze_indirect_call_uses): When offset is being changed; clear
outer type.
(update_indirect_edges_after_inlining): Likewise.
(ipa_write_indirect_edge_info): Stream new fields.
(ipa_read_indirect_edge_info): Stream in new fields.
2013-11-19 Jan Hubicka <jh@suse.cz>
* tree-pretty-print.c (dump_generic_node): Print class type of
OBJ_TYPE_REF.
......@@ -959,16 +959,26 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
&& (target = gimple_call_fn (call_stmt))
&& virtual_method_call_p (target))
{
tree type = obj_type_ref_class (target);
tree otr_type;
HOST_WIDE_INT otr_token;
ipa_polymorphic_call_context context;
get_polymorphic_call_info (caller->decl,
target,
&otr_type, &otr_token,
&context);
/* Only record types can have virtual calls. */
gcc_assert (TREE_CODE (type) == RECORD_TYPE);
gcc_assert (TREE_CODE (otr_type) == RECORD_TYPE);
edge->indirect_info->polymorphic = true;
edge->indirect_info->param_index = -1;
edge->indirect_info->otr_token
= tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
edge->indirect_info->otr_type = type;
edge->indirect_info->polymorphic = 1;
edge->indirect_info->otr_token = otr_token;
edge->indirect_info->otr_type = otr_type;
edge->indirect_info->outer_type = context.outer_type;
edge->indirect_info->offset = context.offset;
edge->indirect_info->maybe_in_construction
= context.maybe_in_construction;
edge->indirect_info->maybe_derived_type = context.maybe_derived_type;
}
edge->next_callee = caller->indirect_calls;
......
......@@ -434,7 +434,7 @@ struct GTY(()) cgraph_indirect_call_info
/* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */
HOST_WIDE_INT otr_token;
/* Type of the object from OBJ_TYPE_REF_OBJECT. */
tree otr_type;
tree otr_type, outer_type;
/* Index of the parameter that is called. */
int param_index;
/* ECF flags determined from the caller. */
......@@ -455,6 +455,8 @@ struct GTY(()) cgraph_indirect_call_info
/* When the previous bit is set, this one determines whether the destination
is loaded from a parameter passed by reference. */
unsigned by_ref : 1;
unsigned int maybe_in_construction : 1;
unsigned int maybe_derived_type : 1;
};
struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgraph_edge {
......
......@@ -386,6 +386,7 @@ ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
jfunc->value.known_type.offset = offset,
jfunc->value.known_type.base_type = base_type;
jfunc->value.known_type.component_type = component_type;
gcc_assert (component_type);
}
/* Set JFUNC to be a copy of another jmp (to be used by jump function
......@@ -1739,8 +1740,6 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt)
cs = cgraph_edge (node, stmt);
cs->indirect_info->param_index = param_index;
cs->indirect_info->offset = 0;
cs->indirect_info->polymorphic = 0;
cs->indirect_info->agg_contents = 0;
cs->indirect_info->member_ptr = 0;
return cs;
......@@ -1837,6 +1836,8 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
NULL, &by_ref))
{
struct cgraph_edge *cs = ipa_note_param_call (node, index, call);
if (cs->indirect_info->offset != offset)
cs->indirect_info->outer_type = NULL;
cs->indirect_info->offset = offset;
cs->indirect_info->agg_contents = 1;
cs->indirect_info->by_ref = by_ref;
......@@ -1934,6 +1935,8 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
&& parm_preserved_before_stmt_p (&parms_ainfo[index], call, rec))
{
struct cgraph_edge *cs = ipa_note_param_call (node, index, call);
if (cs->indirect_info->offset != offset)
cs->indirect_info->outer_type = NULL;
cs->indirect_info->offset = offset;
cs->indirect_info->agg_contents = 1;
cs->indirect_info->member_ptr = 1;
......@@ -2770,6 +2773,8 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs,
else
{
ici->param_index = ipa_get_jf_ancestor_formal_id (jfunc);
if (ipa_get_jf_ancestor_offset (jfunc))
ici->outer_type = NULL;
ici->offset += ipa_get_jf_ancestor_offset (jfunc);
}
}
......@@ -4084,12 +4089,15 @@ ipa_write_indirect_edge_info (struct output_block *ob,
bp_pack_value (&bp, ii->agg_contents, 1);
bp_pack_value (&bp, ii->member_ptr, 1);
bp_pack_value (&bp, ii->by_ref, 1);
bp_pack_value (&bp, ii->maybe_in_construction, 1);
bp_pack_value (&bp, ii->maybe_derived_type, 1);
streamer_write_bitpack (&bp);
if (ii->polymorphic)
{
streamer_write_hwi (ob, ii->otr_token);
stream_write_tree (ob, ii->otr_type, true);
stream_write_tree (ob, ii->outer_type, true);
}
}
......@@ -4111,10 +4119,13 @@ ipa_read_indirect_edge_info (struct lto_input_block *ib,
ii->agg_contents = bp_unpack_value (&bp, 1);
ii->member_ptr = bp_unpack_value (&bp, 1);
ii->by_ref = bp_unpack_value (&bp, 1);
ii->maybe_in_construction = bp_unpack_value (&bp, 1);
ii->maybe_derived_type = bp_unpack_value (&bp, 1);
if (ii->polymorphic)
{
ii->otr_token = (HOST_WIDE_INT) streamer_read_hwi (ib);
ii->otr_type = stream_read_tree (ib, data_in);
ii->outer_type = stream_read_tree (ib, data_in);
}
}
......
......@@ -34,6 +34,21 @@ struct ipa_dfs_info {
PTR aux;
};
/* Context of polymorphic call. This is used by ipa-devirt walkers of the
type inheritance graph. */
struct ipa_polymorphic_call_context {
/* The called object appears in an object of type OUTER_TYPE
at offset OFFSET. */
HOST_WIDE_INT offset;
tree outer_type;
/* True if outer object may be in construction or destruction. */
bool maybe_in_construction;
/* True if outer object may be of derived type. */
bool maybe_derived_type;
};
/* Context representing "I know nothing". */
extern const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context;
/* In ipa-utils.c */
void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);
......@@ -59,13 +74,19 @@ void build_type_inheritance_graph (void);
void update_type_inheritance_graph (void);
vec <cgraph_node *>
possible_polymorphic_call_targets (tree, HOST_WIDE_INT,
ipa_polymorphic_call_context,
bool *final = NULL,
void **cache_token = NULL);
odr_type get_odr_type (tree, bool insert = false);
void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT);
void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &);
bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &,
struct cgraph_node *n);
tree method_class_type (tree);
tree get_polymorphic_call_info (tree, tree, tree *,
HOST_WIDE_INT *,
ipa_polymorphic_call_context *);
/* Return vector containing possible targets of polymorphic call E.
If FINALP is non-NULL, store true if the list is complette.
......@@ -83,8 +104,27 @@ possible_polymorphic_call_targets (struct cgraph_edge *e,
void **cache_token = NULL)
{
gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context = {e->indirect_info->offset,
e->indirect_info->outer_type,
e->indirect_info->maybe_in_construction,
e->indirect_info->maybe_derived_type};
return possible_polymorphic_call_targets (e->indirect_info->otr_type,
e->indirect_info->otr_token,
context,
final, cache_token);
}
/* Same as above but taking OBJ_TYPE_REF as an parameter. */
inline vec <cgraph_node *>
possible_polymorphic_call_targets (tree call,
bool *final = NULL,
void **cache_token = NULL)
{
return possible_polymorphic_call_targets (obj_type_ref_class (call),
tree_to_uhwi
(OBJ_TYPE_REF_TOKEN (call)),
ipa_dummy_polymorphic_call_context,
final, cache_token);
}
......@@ -94,8 +134,13 @@ inline void
dump_possible_polymorphic_call_targets (FILE *f, struct cgraph_edge *e)
{
gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context = {e->indirect_info->offset,
e->indirect_info->outer_type,
e->indirect_info->maybe_in_construction,
e->indirect_info->maybe_derived_type};
dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type,
e->indirect_info->otr_token);
e->indirect_info->otr_token,
context);
}
/* Return true if N can be possibly target of a polymorphic call of
......@@ -105,8 +150,13 @@ inline bool
possible_polymorphic_call_target_p (struct cgraph_edge *e,
struct cgraph_node *n)
{
ipa_polymorphic_call_context context = {e->indirect_info->offset,
e->indirect_info->outer_type,
e->indirect_info->maybe_in_construction,
e->indirect_info->maybe_derived_type};
return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
e->indirect_info->otr_token, n);
e->indirect_info->otr_token,
context, n);
}
/* Return true if N can be possibly target of a polymorphic call of
......@@ -118,7 +168,8 @@ possible_polymorphic_call_target_p (tree call,
{
return possible_polymorphic_call_target_p (obj_type_ref_class (call),
tree_to_uhwi
(OBJ_TYPE_REF_TOKEN (call)),
(OBJ_TYPE_REF_TOKEN (call)),
ipa_dummy_polymorphic_call_context,
n);
}
#endif /* GCC_IPA_UTILS_H */
......
2013-11-19 Jan Hubicka <jh@suse.cz>
* ipa/devirt9.C: Verify that the optimization happens already before.
whole-program.
2013-11-19 Richard Biener <rguenther@suse.de>
PR tree-optimization/57517
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-ipa-inline" } */
/* { dg-options "-O2 -fdump-ipa-whole-program" } */
double foo ();
struct B
{
......@@ -27,5 +27,7 @@ bar ()
static C c;
c.c1 (60, (int) foo ());
}
/* { dg-final { scan-ipa-dump "Discovered a virtual call to a known target" "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
/* We optimize out this call just after early passes. Unfortunately
this unreachable removal is not logged in dump file. */
/* { dg-final { scan-ipa-dump 1 "OBJ_TYPE_REF" "whole-program" } } */
/* { dg-final { cleanup-ipa-dump "whole-program" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment