Commit 6f8091fc by Jan Hubicka Committed by Jan Hubicka

ipa-utils.h (ipa_polymorphic_call_context): Turn into class; add ctors.


	* ipa-utils.h (ipa_polymorphic_call_context): Turn into class; add ctors.
	(possible_polymorphic_call_targets, dump_possible_polymorphic_call_targets,
	possible_polymorphic_call_target_p, possible_polymorphic_call_target_p): Simplify.
	(get_dynamic_type): Remove.
	* ipa-devirt.c (ipa_dummy_polymorphic_call_context): Remove.
	(clear_speculation): Bring to ipa-deivrt.h
	(get_class_context): Rename to ...
	(ipa_polymorphic_call_context::restrict_to_inner_class): ... this one.
	(contains_type_p): Update.
	(get_dynamic_type): Rename to ...
	ipa_polymorphic_call_context::get_dynamic_type(): ... this one.
	(possible_polymorphic_call_targets): UPdate.
	* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Update.
	* ipa-prop.c (ipa_analyze_call_uses): Update.

From-SVN: r215418
parent 8e1ba78f
2014-09-19 Jan Hubicka <hubicka@ucw.cz> 2014-09-19 Jan Hubicka <hubicka@ucw.cz>
* ipa-utils.h (ipa_polymorphic_call_context): Turn into class; add ctors.
(possible_polymorphic_call_targets, dump_possible_polymorphic_call_targets,
possible_polymorphic_call_target_p, possible_polymorphic_call_target_p): Simplify.
(get_dynamic_type): Remove.
* ipa-devirt.c (ipa_dummy_polymorphic_call_context): Remove.
(clear_speculation): Bring to ipa-deivrt.h
(get_class_context): Rename to ...
(ipa_polymorphic_call_context::restrict_to_inner_class): ... this one.
(contains_type_p): Update.
(get_dynamic_type): Rename to ...
ipa_polymorphic_call_context::get_dynamic_type(): ... this one.
(possible_polymorphic_call_targets): UPdate.
* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Update.
* ipa-prop.c (ipa_analyze_call_uses): Update.
2014-09-19 Jan Hubicka <hubicka@ucw.cz>
* ipa-visibility.c (varpool_node::externally_visible_p): Do not * ipa-visibility.c (varpool_node::externally_visible_p): Do not
privatize dynamic TLS variables. privatize dynamic TLS variables.
...@@ -884,21 +884,15 @@ cgraph_node::create_indirect_edge (gimple call_stmt, int ecf_flags, ...@@ -884,21 +884,15 @@ cgraph_node::create_indirect_edge (gimple call_stmt, int ecf_flags,
&& (target = gimple_call_fn (call_stmt)) && (target = gimple_call_fn (call_stmt))
&& virtual_method_call_p (target)) && virtual_method_call_p (target))
{ {
tree otr_type; ipa_polymorphic_call_context context (decl, target, call_stmt);
HOST_WIDE_INT otr_token;
ipa_polymorphic_call_context context;
get_polymorphic_call_info (decl,
target,
&otr_type, &otr_token,
&context, call_stmt);
/* Only record types can have virtual calls. */ /* Only record types can have virtual calls. */
gcc_assert (TREE_CODE (otr_type) == RECORD_TYPE);
edge->indirect_info->polymorphic = true; edge->indirect_info->polymorphic = true;
edge->indirect_info->param_index = -1; edge->indirect_info->param_index = -1;
edge->indirect_info->otr_token = otr_token; edge->indirect_info->otr_token
edge->indirect_info->otr_type = otr_type; = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
edge->indirect_info->otr_type = obj_type_ref_class (target);
gcc_assert (TREE_CODE (edge->indirect_info->otr_type) == RECORD_TYPE);
edge->indirect_info->outer_type = context.outer_type; edge->indirect_info->outer_type = context.outer_type;
edge->indirect_info->speculative_outer_type edge->indirect_info->speculative_outer_type
= context.speculative_outer_type; = context.speculative_outer_type;
......
...@@ -2563,8 +2563,8 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) ...@@ -2563,8 +2563,8 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
{ {
if (dump_file && virtual_method_call_p (callee) if (dump_file && virtual_method_call_p (callee)
&& !possible_polymorphic_call_target_p && !possible_polymorphic_call_target_p
(callee, cgraph_node::get (gimple_call_addr_fndecl (callee, stmt, cgraph_node::get (gimple_call_addr_fndecl
(OBJ_TYPE_REF_EXPR (callee))))) (OBJ_TYPE_REF_EXPR (callee)))))
{ {
fprintf (dump_file, fprintf (dump_file,
"Type inheritance inconsistent devirtualization of "); "Type inheritance inconsistent devirtualization of ");
......
...@@ -1618,14 +1618,11 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ...@@ -1618,14 +1618,11 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
if (TREE_CODE (t) != TREE_BINFO) if (TREE_CODE (t) != TREE_BINFO)
{ {
ipa_polymorphic_call_context context; ipa_polymorphic_call_context context (t, ie->indirect_info->otr_type,
anc_offset);
vec <cgraph_node *>targets; vec <cgraph_node *>targets;
bool final; bool final;
if (!get_polymorphic_call_info_from_invariant
(&context, t, ie->indirect_info->otr_type,
anc_offset))
return NULL_TREE;
targets = possible_polymorphic_call_targets targets = possible_polymorphic_call_targets
(ie->indirect_info->otr_type, (ie->indirect_info->otr_type,
ie->indirect_info->otr_token, ie->indirect_info->otr_token,
......
...@@ -2347,14 +2347,13 @@ ipa_analyze_call_uses (struct func_body_info *fbi, gimple call) ...@@ -2347,14 +2347,13 @@ ipa_analyze_call_uses (struct func_body_info *fbi, gimple call)
{ {
tree otr_type; tree otr_type;
HOST_WIDE_INT otr_token; HOST_WIDE_INT otr_token;
ipa_polymorphic_call_context context;
tree instance; tree instance;
tree target = gimple_call_fn (call); tree target = gimple_call_fn (call);
ipa_polymorphic_call_context context (current_function_decl,
target, call, &instance);
instance = get_polymorphic_call_info (current_function_decl, otr_type = obj_type_ref_class (target);
target, otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
&otr_type, &otr_token,
&context, call);
if (context.get_dynamic_type (instance, if (context.get_dynamic_type (instance,
OBJ_TYPE_REF_OBJECT (target), OBJ_TYPE_REF_OBJECT (target),
...@@ -2609,7 +2608,7 @@ ipa_intraprocedural_devirtualization (gimple call) ...@@ -2609,7 +2608,7 @@ ipa_intraprocedural_devirtualization (gimple call)
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
if (fndecl) if (fndecl)
gcc_assert (possible_polymorphic_call_target_p gcc_assert (possible_polymorphic_call_target_p
(otr, cgraph_node::get (fndecl))); (otr, call, cgraph_node::get (fndecl)));
#endif #endif
return fndecl; return fndecl;
} }
...@@ -3121,14 +3120,12 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, ...@@ -3121,14 +3120,12 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
if (TREE_CODE (binfo) != TREE_BINFO) if (TREE_CODE (binfo) != TREE_BINFO)
{ {
ipa_polymorphic_call_context context; ipa_polymorphic_call_context context (binfo,
ie->indirect_info->otr_type,
ie->indirect_info->offset);
vec <cgraph_node *>targets; vec <cgraph_node *>targets;
bool final; bool final;
if (!get_polymorphic_call_info_from_invariant
(&context, binfo, ie->indirect_info->otr_type,
ie->indirect_info->offset))
return NULL;
targets = possible_polymorphic_call_targets targets = possible_polymorphic_call_targets
(ie->indirect_info->otr_type, (ie->indirect_info->otr_type,
ie->indirect_info->otr_token, ie->indirect_info->otr_token,
......
...@@ -53,12 +53,28 @@ public: ...@@ -53,12 +53,28 @@ public:
/* True if speculative outer object may be of derived type. We always /* True if speculative outer object may be of derived type. We always
speculate that construction does not happen. */ speculate that construction does not happen. */
bool speculative_maybe_derived_type; bool speculative_maybe_derived_type;
/* True if the context is invalid and all calls should be redirected
to BUILTIN_UNREACHABLE. */
bool invalid;
/* Build empty "I know nothing" context. */ /* Build empty "I know nothing" context. */
ipa_polymorphic_call_context (); ipa_polymorphic_call_context ();
/* Build polymorphic call context for indirect call E. */ /* Build polymorphic call context for indirect call E. */
ipa_polymorphic_call_context (cgraph_edge *e); ipa_polymorphic_call_context (cgraph_edge *e);
/* Build polymorphic call context for IP invariant CST.
If specified, OTR_TYPE specify the type of polymorphic call
that takes CST+OFFSET as a prameter. */
ipa_polymorphic_call_context (tree cst, tree otr_type = NULL,
HOST_WIDE_INT offset = 0);
/* Build context for pointer REF contained in FNDECL at statement STMT.
if INSTANCE is non-NULL, return pointer to the object described by
the context. */
ipa_polymorphic_call_context (tree fndecl, tree ref, gimple stmt,
tree *instance = NULL);
/* Look for vtable stores or constructor calls to work out dynamic type
of memory location. */
bool get_dynamic_type (tree, tree, tree, gimple);
/* Make context non-speculative. */ /* Make context non-speculative. */
void clear_speculation (); void clear_speculation ();
...@@ -67,9 +83,9 @@ public: ...@@ -67,9 +83,9 @@ public:
containing EXPECTED_TYPE as base class. */ containing EXPECTED_TYPE as base class. */
bool restrict_to_inner_class (tree expected_type); bool restrict_to_inner_class (tree expected_type);
/* Look for vtable stores or constructor calls to work out dynamic type private:
of memory location. */ void set_by_decl (tree, HOST_WIDE_INT);
bool get_dynamic_type (tree, tree, tree, gimple); bool set_by_invariant (tree, tree, HOST_WIDE_INT);
}; };
/* Build polymorphic call context for indirect call E. */ /* Build polymorphic call context for indirect call E. */
...@@ -77,6 +93,8 @@ public: ...@@ -77,6 +93,8 @@ public:
inline inline
ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e) ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e)
{ {
gcc_checking_assert (e->indirect_info->polymorphic);
offset = e->indirect_info->offset; offset = e->indirect_info->offset;
speculative_offset = e->indirect_info->speculative_offset; speculative_offset = e->indirect_info->speculative_offset;
outer_type = e->indirect_info->outer_type; outer_type = e->indirect_info->outer_type;
...@@ -84,16 +102,22 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e) ...@@ -84,16 +102,22 @@ ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e)
maybe_in_construction = e->indirect_info->maybe_in_construction; maybe_in_construction = e->indirect_info->maybe_in_construction;
maybe_derived_type = e->indirect_info->maybe_derived_type; maybe_derived_type = e->indirect_info->maybe_derived_type;
speculative_maybe_derived_type = e->indirect_info->speculative_maybe_derived_type; speculative_maybe_derived_type = e->indirect_info->speculative_maybe_derived_type;
invalid = false;
} }
/* Build empty "I know nothing" context. */ /* Build empty "I know nothing" context. */
inline inline
ipa_polymorphic_call_context::ipa_polymorphic_call_context () ipa_polymorphic_call_context::ipa_polymorphic_call_context ()
: offset(0), speculative_offset(0), outer_type(NULL),
speculative_outer_type(NULL), maybe_in_construction(false),
maybe_derived_type(false), speculative_maybe_derived_type(false)
{ {
offset = 0;
speculative_offset = 0;
outer_type = NULL;
speculative_outer_type = NULL;
maybe_in_construction = true;
maybe_derived_type = true;
speculative_maybe_derived_type = false;
invalid = false;
} }
/* Make context non-speculative. */ /* Make context non-speculative. */
...@@ -131,22 +155,17 @@ void update_type_inheritance_graph (void); ...@@ -131,22 +155,17 @@ void update_type_inheritance_graph (void);
vec <cgraph_node *> vec <cgraph_node *>
possible_polymorphic_call_targets (tree, HOST_WIDE_INT, possible_polymorphic_call_targets (tree, HOST_WIDE_INT,
ipa_polymorphic_call_context, ipa_polymorphic_call_context,
bool *final = NULL, bool *copletep = NULL,
void **cache_token = NULL, void **cache_token = NULL,
int *nonconstruction_targets = NULL); int *nonconstruction_targets = NULL);
odr_type get_odr_type (tree, bool insert = false); odr_type get_odr_type (tree, bool insert = false);
bool possible_polymorphic_call_target_p (tree ref, gimple stmt, struct cgraph_node *n);
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 &); const ipa_polymorphic_call_context &);
bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT, bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &, const ipa_polymorphic_call_context &,
struct cgraph_node *); struct cgraph_node *);
tree method_class_type (const_tree); tree method_class_type (const_tree);
tree get_polymorphic_call_info (tree, tree, tree *,
HOST_WIDE_INT *,
ipa_polymorphic_call_context *,
gimple call = NULL);
bool get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *,
tree, tree, HOST_WIDE_INT);
bool decl_maybe_in_construction_p (tree, tree, gimple, tree); bool decl_maybe_in_construction_p (tree, tree, gimple, tree);
tree vtable_pointer_value_to_binfo (const_tree); tree vtable_pointer_value_to_binfo (const_tree);
bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *); bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *);
...@@ -155,7 +174,7 @@ bool contains_polymorphic_type_p (const_tree); ...@@ -155,7 +174,7 @@ bool contains_polymorphic_type_p (const_tree);
void register_odr_type (tree); void register_odr_type (tree);
/* Return vector containing possible targets of polymorphic call E. /* Return vector containing possible targets of polymorphic call E.
If FINALP is non-NULL, store true if the list is complette. If COMPLETEP is non-NULL, store true if the list is complette.
CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry
in the target cache. If user needs to visit every target list in the target cache. If user needs to visit every target list
just once, it can memoize them. just once, it can memoize them.
...@@ -166,16 +185,16 @@ void register_odr_type (tree); ...@@ -166,16 +185,16 @@ void register_odr_type (tree);
inline vec <cgraph_node *> inline vec <cgraph_node *>
possible_polymorphic_call_targets (struct cgraph_edge *e, possible_polymorphic_call_targets (struct cgraph_edge *e,
bool *final = NULL, bool *completep = NULL,
void **cache_token = NULL, void **cache_token = NULL,
int *nonconstruction_targets = NULL) int *nonconstruction_targets = NULL)
{ {
gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context(e); ipa_polymorphic_call_context context(e);
return possible_polymorphic_call_targets (e->indirect_info->otr_type, return possible_polymorphic_call_targets (e->indirect_info->otr_type,
e->indirect_info->otr_token, e->indirect_info->otr_token,
context, context,
final, cache_token, completep, cache_token,
nonconstruction_targets); nonconstruction_targets);
} }
...@@ -184,21 +203,16 @@ possible_polymorphic_call_targets (struct cgraph_edge *e, ...@@ -184,21 +203,16 @@ possible_polymorphic_call_targets (struct cgraph_edge *e,
inline vec <cgraph_node *> inline vec <cgraph_node *>
possible_polymorphic_call_targets (tree ref, possible_polymorphic_call_targets (tree ref,
gimple call, gimple call,
bool *final = NULL, bool *completep = NULL,
void **cache_token = NULL) void **cache_token = NULL)
{ {
tree otr_type; ipa_polymorphic_call_context context (current_function_decl, ref, call);
HOST_WIDE_INT otr_token;
ipa_polymorphic_call_context context;
get_polymorphic_call_info (current_function_decl,
ref,
&otr_type, &otr_token, &context, call);
return possible_polymorphic_call_targets (obj_type_ref_class (ref), return possible_polymorphic_call_targets (obj_type_ref_class (ref),
tree_to_uhwi tree_to_uhwi
(OBJ_TYPE_REF_TOKEN (ref)), (OBJ_TYPE_REF_TOKEN (ref)),
context, context,
final, cache_token); completep, cache_token);
} }
/* Dump possible targets of a polymorphic call E into F. */ /* Dump possible targets of a polymorphic call E into F. */
...@@ -206,8 +220,8 @@ possible_polymorphic_call_targets (tree ref, ...@@ -206,8 +220,8 @@ possible_polymorphic_call_targets (tree ref,
inline void inline void
dump_possible_polymorphic_call_targets (FILE *f, struct cgraph_edge *e) dump_possible_polymorphic_call_targets (FILE *f, struct cgraph_edge *e)
{ {
gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context(e); ipa_polymorphic_call_context context(e);
dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type, dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type,
e->indirect_info->otr_token, e->indirect_info->otr_token,
context); context);
...@@ -221,26 +235,12 @@ possible_polymorphic_call_target_p (struct cgraph_edge *e, ...@@ -221,26 +235,12 @@ possible_polymorphic_call_target_p (struct cgraph_edge *e,
struct cgraph_node *n) struct cgraph_node *n)
{ {
ipa_polymorphic_call_context context(e); ipa_polymorphic_call_context context(e);
return possible_polymorphic_call_target_p (e->indirect_info->otr_type, return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
e->indirect_info->otr_token, e->indirect_info->otr_token,
context, n); context, n);
} }
/* Return true if N can be possibly target of a polymorphic call of
OBJ_TYPE_REF expression CALL. */
inline bool
possible_polymorphic_call_target_p (tree call,
struct cgraph_node *n)
{
ipa_polymorphic_call_context context;
return possible_polymorphic_call_target_p (obj_type_ref_class (call),
tree_to_uhwi
(OBJ_TYPE_REF_TOKEN (call)),
context,
n);
}
/* Return true of T is type with One Definition Rule info attached. /* Return true of T is type with One Definition Rule info attached.
It means that either it is anonymous type or it has assembler name It means that either it is anonymous type or it has assembler name
set. */ set. */
......
...@@ -4277,16 +4277,11 @@ eliminate_dom_walker::before_dom_children (basic_block b) ...@@ -4277,16 +4277,11 @@ eliminate_dom_walker::before_dom_children (basic_block b)
&& flag_devirtualize && flag_devirtualize
&& virtual_method_call_p (fn)) && virtual_method_call_p (fn))
{ {
tree otr_type; tree otr_type = obj_type_ref_class (fn);
HOST_WIDE_INT otr_token;
ipa_polymorphic_call_context context;
tree instance; tree instance;
ipa_polymorphic_call_context context (current_function_decl, fn, stmt, &instance);
bool final; bool final;
instance = get_polymorphic_call_info (current_function_decl,
fn,
&otr_type, &otr_token, &context, stmt);
context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt); context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt);
vec <cgraph_node *>targets vec <cgraph_node *>targets
......
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