Commit 4d7cf10d 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: r214060
parent 1a985ca8
2014-08-15 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-08-15 Oleg Endo <olegendo@gcc.gnu.org> 2014-08-15 Oleg Endo <olegendo@gcc.gnu.org>
* doc/invoke.texi (SH options): Document missing processor variant * doc/invoke.texi (SH options): Document missing processor variant
......
...@@ -141,10 +141,6 @@ static bool odr_types_equivalent_p (tree, tree, bool, bool *, ...@@ -141,10 +141,6 @@ static bool odr_types_equivalent_p (tree, tree, bool, bool *,
static bool odr_violation_reported = false; static bool odr_violation_reported = false;
/* Dummy polymorphic call context. */
const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context
= {0, 0, NULL, NULL, false, true, true};
/* Pointer set of all call targets appearing in the cache. */ /* Pointer set of all call targets appearing in the cache. */
static hash_set<cgraph_node *> *cached_polymorphic_call_targets; static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
...@@ -1853,23 +1849,13 @@ contains_polymorphic_type_p (const_tree type) ...@@ -1853,23 +1849,13 @@ contains_polymorphic_type_p (const_tree type)
return false; return false;
} }
/* Clear speculative info from CONTEXT. */ /* THIS->OUTER_TYPE is a type of memory object where object of EXPECTED_TYPE
is contained at THIS->OFFSET. Walk the memory representation of
static void THIS->OUTER_TYPE and find the outermost class type that match
clear_speculation (ipa_polymorphic_call_context *context) EXPECTED_TYPE or contain EXPECTED_TYPE as a base. Update THIS
{
context->speculative_outer_type = NULL;
context->speculative_offset = 0;
context->speculative_maybe_derived_type = false;
}
/* CONTEXT->OUTER_TYPE is a type of memory object where object of EXPECTED_TYPE
is contained at CONTEXT->OFFSET. Walk the memory representation of
CONTEXT->OUTER_TYPE and find the outermost class type that match
EXPECTED_TYPE or contain EXPECTED_TYPE as a base. Update CONTEXT
to represent it. to represent it.
For example when CONTEXT represents type For example when THIS represents type
class A class A
{ {
int a; int a;
...@@ -1880,32 +1866,31 @@ clear_speculation (ipa_polymorphic_call_context *context) ...@@ -1880,32 +1866,31 @@ clear_speculation (ipa_polymorphic_call_context *context)
sizeof(int). sizeof(int).
If we can not find corresponding class, give up by setting If we can not find corresponding class, give up by setting
CONTEXT->OUTER_TYPE to EXPECTED_TYPE and CONTEXT->OFFSET to NULL. THIS->OUTER_TYPE to EXPECTED_TYPE and THIS->OFFSET to NULL.
Return true when lookup was sucesful. */ Return true when lookup was sucesful. */
static bool bool
get_class_context (ipa_polymorphic_call_context *context, ipa_polymorphic_call_context::restrict_to_inner_class (tree expected_type)
tree expected_type)
{ {
tree type = context->outer_type; tree type = outer_type;
HOST_WIDE_INT offset = context->offset; HOST_WIDE_INT cur_offset = offset;
bool speculative = false; bool speculative = false;
bool speculation_valid = false; bool speculation_valid = false;
bool valid = false; bool valid = false;
if (!context->outer_type) if (!outer_type)
{ {
type = context->outer_type = expected_type; type = outer_type = expected_type;
context->offset = offset = 0; offset = cur_offset = 0;
} }
if (context->speculative_outer_type == context->outer_type if (speculative_outer_type == outer_type
&& (!context->maybe_derived_type && (!maybe_derived_type
|| context->speculative_maybe_derived_type)) || speculative_maybe_derived_type))
{ {
context->speculative_outer_type = NULL; speculative_outer_type = NULL;
context->speculative_offset = 0; speculative_offset = 0;
context->speculative_maybe_derived_type = false; speculative_maybe_derived_type = false;
} }
/* See if speculative type seem to be derrived from outer_type. /* See if speculative type seem to be derrived from outer_type.
...@@ -1917,14 +1902,14 @@ get_class_context (ipa_polymorphic_call_context *context, ...@@ -1917,14 +1902,14 @@ get_class_context (ipa_polymorphic_call_context *context,
MAYBE_DERIVED_TYPE is false and we have full non-speculative information or MAYBE_DERIVED_TYPE is false and we have full non-speculative information or
the loop bellow will correctly update SPECULATIVE_OUTER_TYPE the loop bellow will correctly update SPECULATIVE_OUTER_TYPE
and SPECULATIVE_MAYBE_DERIVED_TYPE. */ and SPECULATIVE_MAYBE_DERIVED_TYPE. */
if (context->speculative_outer_type if (speculative_outer_type
&& context->speculative_offset >= context->offset && speculative_offset >= offset
&& contains_type_p (context->speculative_outer_type, && contains_type_p (speculative_outer_type,
context->offset - context->speculative_offset, offset - speculative_offset,
context->outer_type)) outer_type))
speculation_valid = context->maybe_derived_type; speculation_valid = maybe_derived_type;
else else
clear_speculation (context); clear_speculation ();
/* Find the sub-object the constant actually refers to and mark whether it is /* Find the sub-object the constant actually refers to and mark whether it is
an artificial one (as opposed to a user-defined one). an artificial one (as opposed to a user-defined one).
...@@ -1950,19 +1935,19 @@ get_class_context (ipa_polymorphic_call_context *context, ...@@ -1950,19 +1935,19 @@ get_class_context (ipa_polymorphic_call_context *context,
gcc_assert (valid); gcc_assert (valid);
/* If we did not match the offset, just give up on speculation. */ /* If we did not match the offset, just give up on speculation. */
if (offset != 0 if (cur_offset != 0
|| (types_same_for_odr (context->speculative_outer_type, || (types_same_for_odr (speculative_outer_type,
context->outer_type) outer_type)
&& (context->maybe_derived_type && (maybe_derived_type
== context->speculative_maybe_derived_type))) == speculative_maybe_derived_type)))
clear_speculation (context); clear_speculation ();
return true; return true;
} }
else else
{ {
/* Type can not contain itself on an non-zero offset. In that case /* Type can not contain itself on an non-zero offset. In that case
just give up. */ just give up. */
if (offset != 0) if (cur_offset != 0)
{ {
valid = false; valid = false;
goto give_up; goto give_up;
...@@ -1971,17 +1956,17 @@ get_class_context (ipa_polymorphic_call_context *context, ...@@ -1971,17 +1956,17 @@ get_class_context (ipa_polymorphic_call_context *context,
/* If speculation is not valid or we determined type precisely, /* If speculation is not valid or we determined type precisely,
we are done. */ we are done. */
if (!speculation_valid if (!speculation_valid
|| !context->maybe_derived_type) || !maybe_derived_type)
{ {
clear_speculation (context); clear_speculation ();
return true; return true;
} }
/* Otherwise look into speculation now. */ /* Otherwise look into speculation now. */
else else
{ {
speculative = true; speculative = true;
type = context->speculative_outer_type; type = speculative_outer_type;
offset = context->speculative_offset; cur_offset = speculative_offset;
continue; continue;
} }
} }
...@@ -1997,7 +1982,7 @@ get_class_context (ipa_polymorphic_call_context *context, ...@@ -1997,7 +1982,7 @@ get_class_context (ipa_polymorphic_call_context *context,
pos = int_bit_position (fld); pos = int_bit_position (fld);
size = tree_to_uhwi (DECL_SIZE (fld)); size = tree_to_uhwi (DECL_SIZE (fld));
if (pos <= offset && (pos + size) > offset) if (pos <= cur_offset && (pos + size) > cur_offset)
break; break;
} }
...@@ -2005,23 +1990,23 @@ get_class_context (ipa_polymorphic_call_context *context, ...@@ -2005,23 +1990,23 @@ get_class_context (ipa_polymorphic_call_context *context,
goto give_up; goto give_up;
type = TYPE_MAIN_VARIANT (TREE_TYPE (fld)); type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
offset -= pos; cur_offset -= pos;
/* DECL_ARTIFICIAL represents a basetype. */ /* DECL_ARTIFICIAL represents a basetype. */
if (!DECL_ARTIFICIAL (fld)) if (!DECL_ARTIFICIAL (fld))
{ {
if (!speculative) if (!speculative)
{ {
context->outer_type = type; outer_type = type;
context->offset = offset; offset = cur_offset;
/* As soon as we se an field containing the type, /* As soon as we se an field containing the type,
we know we are not looking for derivations. */ we know we are not looking for derivations. */
context->maybe_derived_type = false; maybe_derived_type = false;
} }
else else
{ {
context->speculative_outer_type = type; speculative_outer_type = type;
context->speculative_offset = offset; speculative_offset = cur_offset;
context->speculative_maybe_derived_type = false; speculative_maybe_derived_type = false;
} }
} }
} }
...@@ -2033,19 +2018,19 @@ get_class_context (ipa_polymorphic_call_context *context, ...@@ -2033,19 +2018,19 @@ get_class_context (ipa_polymorphic_call_context *context,
if (!tree_fits_shwi_p (TYPE_SIZE (subtype)) if (!tree_fits_shwi_p (TYPE_SIZE (subtype))
|| !tree_to_shwi (TYPE_SIZE (subtype)) <= 0) || !tree_to_shwi (TYPE_SIZE (subtype)) <= 0)
goto give_up; goto give_up;
offset = offset % tree_to_shwi (TYPE_SIZE (subtype)); cur_offset = cur_offset % tree_to_shwi (TYPE_SIZE (subtype));
type = subtype; type = subtype;
if (!speculative) if (!speculative)
{ {
context->outer_type = type; outer_type = type;
context->offset = offset; offset = cur_offset;
context->maybe_derived_type = false; maybe_derived_type = false;
} }
else else
{ {
context->speculative_outer_type = type; speculative_outer_type = type;
context->speculative_offset = offset; speculative_offset = cur_offset;
context->speculative_maybe_derived_type = false; speculative_maybe_derived_type = false;
} }
} }
/* Give up on anything else. */ /* Give up on anything else. */
...@@ -2056,13 +2041,13 @@ get_class_context (ipa_polymorphic_call_context *context, ...@@ -2056,13 +2041,13 @@ get_class_context (ipa_polymorphic_call_context *context,
/* If we failed to find subtype we look for, give up and fall back to the /* If we failed to find subtype we look for, give up and fall back to the
most generic query. */ most generic query. */
give_up: give_up:
clear_speculation (context); clear_speculation ();
if (valid) if (valid)
return true; return true;
context->outer_type = expected_type; outer_type = expected_type;
context->offset = 0; offset = 0;
context->maybe_derived_type = true; maybe_derived_type = true;
context->maybe_in_construction = true; maybe_in_construction = true;
/* POD can be changed to an instance of a polymorphic type by /* POD can be changed to an instance of a polymorphic type by
placement new. Here we play safe and assume that any placement new. Here we play safe and assume that any
non-polymorphic type is POD. */ non-polymorphic type is POD. */
...@@ -2071,7 +2056,7 @@ give_up: ...@@ -2071,7 +2056,7 @@ give_up:
|| !polymorphic_type_binfo_p (TYPE_BINFO (type))) || !polymorphic_type_binfo_p (TYPE_BINFO (type)))
&& (!TYPE_SIZE (type) && (!TYPE_SIZE (type)
|| TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
|| (offset + tree_to_uhwi (TYPE_SIZE (expected_type)) <= || (cur_offset + tree_to_uhwi (TYPE_SIZE (expected_type)) <=
tree_to_uhwi (TYPE_SIZE (type))))) tree_to_uhwi (TYPE_SIZE (type)))))
return true; return true;
return false; return false;
...@@ -2083,10 +2068,10 @@ static bool ...@@ -2083,10 +2068,10 @@ static bool
contains_type_p (tree outer_type, HOST_WIDE_INT offset, contains_type_p (tree outer_type, HOST_WIDE_INT offset,
tree otr_type) tree otr_type)
{ {
ipa_polymorphic_call_context context = {offset, 0, ipa_polymorphic_call_context context;
TYPE_MAIN_VARIANT (outer_type), context.offset = offset;
NULL, false, true, false}; context.outer_type = TYPE_MAIN_VARIANT (outer_type);
return get_class_context (&context, otr_type); return context.restrict_to_inner_class (otr_type);
} }
/* Lookup base of BINFO that has virtual table VTABLE with OFFSET. */ /* Lookup base of BINFO that has virtual table VTABLE with OFFSET. */
...@@ -2834,7 +2819,7 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data) ...@@ -2834,7 +2819,7 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
return false; return false;
} }
/* CONTEXT is polymorphic call context obtained from get_polymorphic_context. /* THIS is polymorphic call context obtained from get_polymorphic_context.
OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT. OTR_OBJECT is pointer to the instance returned by OBJ_TYPE_REF_OBJECT.
INSTANCE is pointer to the outer instance as returned by INSTANCE is pointer to the outer instance as returned by
get_polymorphic_context. To avoid creation of temporary expressions, get_polymorphic_context. To avoid creation of temporary expressions,
...@@ -2851,11 +2836,10 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data) ...@@ -2851,11 +2836,10 @@ check_stmt_for_type_change (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef, void *data)
So it is not suitable for use withing fold_stmt and similar uses. */ So it is not suitable for use withing fold_stmt and similar uses. */
bool bool
get_dynamic_type (tree instance, ipa_polymorphic_call_context::get_dynamic_type (tree instance,
ipa_polymorphic_call_context *context, tree otr_object,
tree otr_object, tree otr_type,
tree otr_type, gimple call)
gimple call)
{ {
struct type_change_info tci; struct type_change_info tci;
ao_ref ao; ao_ref ao;
...@@ -2863,7 +2847,7 @@ get_dynamic_type (tree instance, ...@@ -2863,7 +2847,7 @@ get_dynamic_type (tree instance,
tree instance_ref = NULL; tree instance_ref = NULL;
gimple stmt = call; gimple stmt = call;
if (!context->maybe_in_construction && !context->maybe_derived_type) if (!maybe_in_construction && !maybe_derived_type)
return false; return false;
/* We need to obtain refernce to virtual table pointer. It is better /* We need to obtain refernce to virtual table pointer. It is better
...@@ -2916,11 +2900,11 @@ get_dynamic_type (tree instance, ...@@ -2916,11 +2900,11 @@ get_dynamic_type (tree instance,
or from INSTANCE with offset OFFSET. */ or from INSTANCE with offset OFFSET. */
if (base_ref if (base_ref
&& ((TREE_CODE (base_ref) == MEM_REF && ((TREE_CODE (base_ref) == MEM_REF
&& ((offset2 == context->offset && ((offset2 == offset
&& TREE_OPERAND (base_ref, 0) == instance) && TREE_OPERAND (base_ref, 0) == instance)
|| (!offset2 && TREE_OPERAND (base_ref, 0) == otr_object))) || (!offset2 && TREE_OPERAND (base_ref, 0) == otr_object)))
|| (DECL_P (instance) && base_ref == instance || (DECL_P (instance) && base_ref == instance
&& offset2 == context->offset))) && offset2 == offset)))
{ {
stmt = SSA_NAME_DEF_STMT (ref); stmt = SSA_NAME_DEF_STMT (ref);
instance_ref = ref_exp; instance_ref = ref_exp;
...@@ -2959,13 +2943,13 @@ get_dynamic_type (tree instance, ...@@ -2959,13 +2943,13 @@ get_dynamic_type (tree instance,
print_generic_expr (dump_file, otr_object, TDF_SLIM); print_generic_expr (dump_file, otr_object, TDF_SLIM);
fprintf (dump_file, " Outer instance pointer: "); fprintf (dump_file, " Outer instance pointer: ");
print_generic_expr (dump_file, instance, TDF_SLIM); print_generic_expr (dump_file, instance, TDF_SLIM);
fprintf (dump_file, " offset: %i (bits)", (int)context->offset); fprintf (dump_file, " offset: %i (bits)", (int)offset);
fprintf (dump_file, " vtbl reference: "); fprintf (dump_file, " vtbl reference: ");
print_generic_expr (dump_file, instance_ref, TDF_SLIM); print_generic_expr (dump_file, instance_ref, TDF_SLIM);
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
tci.offset = context->offset; tci.offset = offset;
tci.instance = instance; tci.instance = instance;
tci.vtbl_ptr_ref = instance_ref; tci.vtbl_ptr_ref = instance_ref;
gcc_assert (TREE_CODE (instance) != MEM_REF); gcc_assert (TREE_CODE (instance) != MEM_REF);
...@@ -3021,17 +3005,17 @@ get_dynamic_type (tree instance, ...@@ -3021,17 +3005,17 @@ get_dynamic_type (tree instance,
and we can stop, we will never see the calls into constructors of and we can stop, we will never see the calls into constructors of
sub-objects in this code. sub-objects in this code.
Therefore if the static outer type was found (context->outer_type) Therefore if the static outer type was found (outer_type)
we can safely ignore tci.speculative that is set on calls and give up we can safely ignore tci.speculative that is set on calls and give up
only if there was dyanmic type store that may affect given variable only if there was dyanmic type store that may affect given variable
(seen_unanalyzed_store) */ (seen_unanalyzed_store) */
if (!tci.type_maybe_changed) if (!tci.type_maybe_changed)
{ {
if (!context->outer_type || tci.seen_unanalyzed_store) if (!outer_type || tci.seen_unanalyzed_store)
return false; return false;
if (context->maybe_in_construction) if (maybe_in_construction)
context->maybe_in_construction = false; maybe_in_construction = false;
if (dump_file) if (dump_file)
fprintf (dump_file, " No dynamic type change found.\n"); fprintf (dump_file, " No dynamic type change found.\n");
return true; return true;
...@@ -3044,25 +3028,25 @@ get_dynamic_type (tree instance, ...@@ -3044,25 +3028,25 @@ get_dynamic_type (tree instance,
if (!tci.speculative if (!tci.speculative
/* Again in instances located in static storage we are interested only /* Again in instances located in static storage we are interested only
in constructor stores. */ in constructor stores. */
|| (context->outer_type || (outer_type
&& !tci.seen_unanalyzed_store && !tci.seen_unanalyzed_store
&& context->offset == tci.offset && offset == tci.offset
&& types_same_for_odr (tci.known_current_type, && types_same_for_odr (tci.known_current_type,
context->outer_type))) outer_type)))
{ {
context->outer_type = tci.known_current_type; outer_type = tci.known_current_type;
context->offset = tci.known_current_offset; offset = tci.known_current_offset;
context->maybe_in_construction = false; maybe_in_construction = false;
context->maybe_derived_type = false; maybe_derived_type = false;
if (dump_file) if (dump_file)
fprintf (dump_file, " Determined dynamic type.\n"); fprintf (dump_file, " Determined dynamic type.\n");
} }
else if (!context->speculative_outer_type else if (!speculative_outer_type
|| context->speculative_maybe_derived_type) || speculative_maybe_derived_type)
{ {
context->speculative_outer_type = tci.known_current_type; speculative_outer_type = tci.known_current_type;
context->speculative_offset = tci.known_current_offset; speculative_offset = tci.known_current_offset;
context->speculative_maybe_derived_type = false; speculative_maybe_derived_type = false;
if (dump_file) if (dump_file)
fprintf (dump_file, " Determined speculative dynamic type.\n"); fprintf (dump_file, " Determined speculative dynamic type.\n");
} }
...@@ -3253,7 +3237,7 @@ possible_polymorphic_call_targets (tree otr_type, ...@@ -3253,7 +3237,7 @@ possible_polymorphic_call_targets (tree otr_type,
/* Do not bother to compute speculative info when user do not asks for it. */ /* Do not bother to compute speculative info when user do not asks for it. */
if (!speculative_targetsp || !context.speculative_outer_type) if (!speculative_targetsp || !context.speculative_outer_type)
clear_speculation (&context); context.clear_speculation ();
type = get_odr_type (otr_type, true); type = get_odr_type (otr_type, true);
...@@ -3263,7 +3247,7 @@ possible_polymorphic_call_targets (tree otr_type, ...@@ -3263,7 +3247,7 @@ possible_polymorphic_call_targets (tree otr_type,
/* Lookup the outer class type we want to walk. */ /* Lookup the outer class type we want to walk. */
if ((context.outer_type || context.speculative_outer_type) if ((context.outer_type || context.speculative_outer_type)
&& !get_class_context (&context, otr_type)) && !context.restrict_to_inner_class (otr_type))
{ {
if (completep) if (completep)
*completep = false; *completep = false;
...@@ -3274,7 +3258,7 @@ possible_polymorphic_call_targets (tree otr_type, ...@@ -3274,7 +3258,7 @@ possible_polymorphic_call_targets (tree otr_type,
return nodes; return nodes;
} }
/* Check that get_class_context kept the main variant. */ /* Check that restrict_to_inner_class kept the main variant. */
gcc_assert (!context.outer_type gcc_assert (!context.outer_type
|| TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type); || TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type);
......
...@@ -2356,9 +2356,9 @@ ipa_analyze_call_uses (struct func_body_info *fbi, gimple call) ...@@ -2356,9 +2356,9 @@ ipa_analyze_call_uses (struct func_body_info *fbi, gimple call)
&otr_type, &otr_token, &otr_type, &otr_token,
&context, call); &context, call);
if (get_dynamic_type (instance, &context, if (context.get_dynamic_type (instance,
OBJ_TYPE_REF_OBJECT (target), OBJ_TYPE_REF_OBJECT (target),
otr_type, call)) otr_type, call))
{ {
gcc_assert (TREE_CODE (otr_type) == RECORD_TYPE); gcc_assert (TREE_CODE (otr_type) == RECORD_TYPE);
cs->indirect_info->polymorphic = true; cs->indirect_info->polymorphic = true;
......
...@@ -36,7 +36,9 @@ struct ipa_dfs_info { ...@@ -36,7 +36,9 @@ struct ipa_dfs_info {
/* Context of polymorphic call. This is used by ipa-devirt walkers of the /* Context of polymorphic call. This is used by ipa-devirt walkers of the
type inheritance graph. */ type inheritance graph. */
struct ipa_polymorphic_call_context {
class ipa_polymorphic_call_context {
public:
/* The called object appears in an object of type OUTER_TYPE /* The called object appears in an object of type OUTER_TYPE
at offset OFFSET. When information is not 100% reliable, we at offset OFFSET. When information is not 100% reliable, we
use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */ use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */
...@@ -51,10 +53,58 @@ struct ipa_polymorphic_call_context { ...@@ -51,10 +53,58 @@ struct ipa_polymorphic_call_context {
/* 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;
/* Build empty "I know nothing" context. */
ipa_polymorphic_call_context ();
/* Build polymorphic call context for indirect call E. */
ipa_polymorphic_call_context (cgraph_edge *e);
/* Make context non-speculative. */
void clear_speculation ();
/* Walk container types and modify context to point to actual class
containing EXPECTED_TYPE as base class. */
bool restrict_to_inner_class (tree expected_type);
/* Look for vtable stores or constructor calls to work out dynamic type
of memory location. */
bool get_dynamic_type (tree, tree, tree, gimple);
}; };
/* Context representing "I know nothing". */ /* Build polymorphic call context for indirect call E. */
extern const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context;
inline
ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e)
{
offset = e->indirect_info->offset;
speculative_offset = e->indirect_info->speculative_offset;
outer_type = e->indirect_info->outer_type;
speculative_outer_type = e->indirect_info->speculative_outer_type;
maybe_in_construction = e->indirect_info->maybe_in_construction;
maybe_derived_type = e->indirect_info->maybe_derived_type;
speculative_maybe_derived_type = e->indirect_info->speculative_maybe_derived_type;
}
/* Build empty "I know nothing" context. */
inline
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)
{
}
/* Make context non-speculative. */
inline void
ipa_polymorphic_call_context::clear_speculation ()
{
speculative_outer_type = NULL;
speculative_offset = 0;
speculative_maybe_derived_type = false;
}
/* In ipa-utils.c */ /* In ipa-utils.c */
void ipa_print_order (FILE*, const char *, struct cgraph_node**, int); void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);
...@@ -95,7 +145,6 @@ tree get_polymorphic_call_info (tree, tree, tree *, ...@@ -95,7 +145,6 @@ tree get_polymorphic_call_info (tree, tree, tree *,
HOST_WIDE_INT *, HOST_WIDE_INT *,
ipa_polymorphic_call_context *, ipa_polymorphic_call_context *,
gimple call = NULL); gimple call = NULL);
bool get_dynamic_type (tree, ipa_polymorphic_call_context *, tree, tree, gimple);
bool get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *, bool get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *,
tree, tree, HOST_WIDE_INT); 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);
...@@ -121,13 +170,7 @@ possible_polymorphic_call_targets (struct cgraph_edge *e, ...@@ -121,13 +170,7 @@ possible_polymorphic_call_targets (struct cgraph_edge *e,
int *nonconstruction_targets = NULL) int *nonconstruction_targets = NULL)
{ {
gcc_checking_assert (e->indirect_info->polymorphic); gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context = {e->indirect_info->offset, ipa_polymorphic_call_context context(e);
e->indirect_info->speculative_offset,
e->indirect_info->outer_type,
e->indirect_info->speculative_outer_type,
e->indirect_info->maybe_in_construction,
e->indirect_info->maybe_derived_type,
e->indirect_info->speculative_maybe_derived_type};
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,
...@@ -163,13 +206,7 @@ inline void ...@@ -163,13 +206,7 @@ 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); gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context = {e->indirect_info->offset, ipa_polymorphic_call_context context(e);
e->indirect_info->speculative_offset,
e->indirect_info->outer_type,
e->indirect_info->speculative_outer_type,
e->indirect_info->maybe_in_construction,
e->indirect_info->maybe_derived_type,
e->indirect_info->speculative_maybe_derived_type};
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);
...@@ -182,11 +219,7 @@ inline bool ...@@ -182,11 +219,7 @@ inline bool
possible_polymorphic_call_target_p (struct cgraph_edge *e, possible_polymorphic_call_target_p (struct cgraph_edge *e,
struct cgraph_node *n) struct cgraph_node *n)
{ {
ipa_polymorphic_call_context context = {e->indirect_info->offset, 0, ipa_polymorphic_call_context context(e);
e->indirect_info->outer_type, NULL,
e->indirect_info->maybe_in_construction,
e->indirect_info->maybe_derived_type,
false};
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);
...@@ -199,10 +232,11 @@ inline bool ...@@ -199,10 +232,11 @@ inline bool
possible_polymorphic_call_target_p (tree call, possible_polymorphic_call_target_p (tree call,
struct cgraph_node *n) struct cgraph_node *n)
{ {
ipa_polymorphic_call_context context;
return possible_polymorphic_call_target_p (obj_type_ref_class (call), return possible_polymorphic_call_target_p (obj_type_ref_class (call),
tree_to_uhwi tree_to_uhwi
(OBJ_TYPE_REF_TOKEN (call)), (OBJ_TYPE_REF_TOKEN (call)),
ipa_dummy_polymorphic_call_context, context,
n); n);
} }
#endif /* GCC_IPA_UTILS_H */ #endif /* GCC_IPA_UTILS_H */
......
...@@ -4374,8 +4374,7 @@ eliminate_dom_walker::before_dom_children (basic_block b) ...@@ -4374,8 +4374,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
fn, fn,
&otr_type, &otr_token, &context, stmt); &otr_type, &otr_token, &context, stmt);
get_dynamic_type (instance, &context, context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt);
OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt);
vec <cgraph_node *>targets vec <cgraph_node *>targets
= possible_polymorphic_call_targets (obj_type_ref_class (fn), = possible_polymorphic_call_targets (obj_type_ref_class (fn),
......
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