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
This commit is contained in:
parent
1a985ca83a
commit
4d7cf10d21
|
@ -1,3 +1,20 @@
|
|||
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>
|
||||
|
||||
* doc/invoke.texi (SH options): Document missing processor variant
|
||||
|
|
198
gcc/ipa-devirt.c
198
gcc/ipa-devirt.c
|
@ -141,10 +141,6 @@ static bool odr_types_equivalent_p (tree, tree, bool, bool *,
|
|||
|
||||
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. */
|
||||
static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
|
||||
|
@ -1853,23 +1849,13 @@ contains_polymorphic_type_p (const_tree type)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Clear speculative info from CONTEXT. */
|
||||
|
||||
static void
|
||||
clear_speculation (ipa_polymorphic_call_context *context)
|
||||
{
|
||||
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
|
||||
/* THIS->OUTER_TYPE is a type of memory object where object of EXPECTED_TYPE
|
||||
is contained at THIS->OFFSET. Walk the memory representation of
|
||||
THIS->OUTER_TYPE and find the outermost class type that match
|
||||
EXPECTED_TYPE or contain EXPECTED_TYPE as a base. Update THIS
|
||||
to represent it.
|
||||
|
||||
For example when CONTEXT represents type
|
||||
For example when THIS represents type
|
||||
class A
|
||||
{
|
||||
int a;
|
||||
|
@ -1880,32 +1866,31 @@ clear_speculation (ipa_polymorphic_call_context *context)
|
|||
sizeof(int).
|
||||
|
||||
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. */
|
||||
|
||||
static bool
|
||||
get_class_context (ipa_polymorphic_call_context *context,
|
||||
tree expected_type)
|
||||
bool
|
||||
ipa_polymorphic_call_context::restrict_to_inner_class (tree expected_type)
|
||||
{
|
||||
tree type = context->outer_type;
|
||||
HOST_WIDE_INT offset = context->offset;
|
||||
tree type = outer_type;
|
||||
HOST_WIDE_INT cur_offset = offset;
|
||||
bool speculative = false;
|
||||
bool speculation_valid = false;
|
||||
bool valid = false;
|
||||
|
||||
if (!context->outer_type)
|
||||
if (!outer_type)
|
||||
{
|
||||
type = context->outer_type = expected_type;
|
||||
context->offset = offset = 0;
|
||||
type = outer_type = expected_type;
|
||||
offset = cur_offset = 0;
|
||||
}
|
||||
|
||||
if (context->speculative_outer_type == context->outer_type
|
||||
&& (!context->maybe_derived_type
|
||||
|| context->speculative_maybe_derived_type))
|
||||
if (speculative_outer_type == outer_type
|
||||
&& (!maybe_derived_type
|
||||
|| speculative_maybe_derived_type))
|
||||
{
|
||||
context->speculative_outer_type = NULL;
|
||||
context->speculative_offset = 0;
|
||||
context->speculative_maybe_derived_type = false;
|
||||
speculative_outer_type = NULL;
|
||||
speculative_offset = 0;
|
||||
speculative_maybe_derived_type = false;
|
||||
}
|
||||
|
||||
/* See if speculative type seem to be derrived from outer_type.
|
||||
|
@ -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
|
||||
the loop bellow will correctly update SPECULATIVE_OUTER_TYPE
|
||||
and SPECULATIVE_MAYBE_DERIVED_TYPE. */
|
||||
if (context->speculative_outer_type
|
||||
&& context->speculative_offset >= context->offset
|
||||
&& contains_type_p (context->speculative_outer_type,
|
||||
context->offset - context->speculative_offset,
|
||||
context->outer_type))
|
||||
speculation_valid = context->maybe_derived_type;
|
||||
if (speculative_outer_type
|
||||
&& speculative_offset >= offset
|
||||
&& contains_type_p (speculative_outer_type,
|
||||
offset - speculative_offset,
|
||||
outer_type))
|
||||
speculation_valid = maybe_derived_type;
|
||||
else
|
||||
clear_speculation (context);
|
||||
clear_speculation ();
|
||||
|
||||
/* Find the sub-object the constant actually refers to and mark whether it is
|
||||
an artificial one (as opposed to a user-defined one).
|
||||
|
@ -1950,19 +1935,19 @@ get_class_context (ipa_polymorphic_call_context *context,
|
|||
gcc_assert (valid);
|
||||
|
||||
/* If we did not match the offset, just give up on speculation. */
|
||||
if (offset != 0
|
||||
|| (types_same_for_odr (context->speculative_outer_type,
|
||||
context->outer_type)
|
||||
&& (context->maybe_derived_type
|
||||
== context->speculative_maybe_derived_type)))
|
||||
clear_speculation (context);
|
||||
if (cur_offset != 0
|
||||
|| (types_same_for_odr (speculative_outer_type,
|
||||
outer_type)
|
||||
&& (maybe_derived_type
|
||||
== speculative_maybe_derived_type)))
|
||||
clear_speculation ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Type can not contain itself on an non-zero offset. In that case
|
||||
just give up. */
|
||||
if (offset != 0)
|
||||
if (cur_offset != 0)
|
||||
{
|
||||
valid = false;
|
||||
goto give_up;
|
||||
|
@ -1971,17 +1956,17 @@ get_class_context (ipa_polymorphic_call_context *context,
|
|||
/* If speculation is not valid or we determined type precisely,
|
||||
we are done. */
|
||||
if (!speculation_valid
|
||||
|| !context->maybe_derived_type)
|
||||
|| !maybe_derived_type)
|
||||
{
|
||||
clear_speculation (context);
|
||||
clear_speculation ();
|
||||
return true;
|
||||
}
|
||||
/* Otherwise look into speculation now. */
|
||||
else
|
||||
{
|
||||
speculative = true;
|
||||
type = context->speculative_outer_type;
|
||||
offset = context->speculative_offset;
|
||||
type = speculative_outer_type;
|
||||
cur_offset = speculative_offset;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1997,7 +1982,7 @@ get_class_context (ipa_polymorphic_call_context *context,
|
|||
|
||||
pos = int_bit_position (fld);
|
||||
size = tree_to_uhwi (DECL_SIZE (fld));
|
||||
if (pos <= offset && (pos + size) > offset)
|
||||
if (pos <= cur_offset && (pos + size) > cur_offset)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2005,23 +1990,23 @@ get_class_context (ipa_polymorphic_call_context *context,
|
|||
goto give_up;
|
||||
|
||||
type = TYPE_MAIN_VARIANT (TREE_TYPE (fld));
|
||||
offset -= pos;
|
||||
cur_offset -= pos;
|
||||
/* DECL_ARTIFICIAL represents a basetype. */
|
||||
if (!DECL_ARTIFICIAL (fld))
|
||||
{
|
||||
if (!speculative)
|
||||
{
|
||||
context->outer_type = type;
|
||||
context->offset = offset;
|
||||
outer_type = type;
|
||||
offset = cur_offset;
|
||||
/* As soon as we se an field containing the type,
|
||||
we know we are not looking for derivations. */
|
||||
context->maybe_derived_type = false;
|
||||
maybe_derived_type = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->speculative_outer_type = type;
|
||||
context->speculative_offset = offset;
|
||||
context->speculative_maybe_derived_type = false;
|
||||
speculative_outer_type = type;
|
||||
speculative_offset = cur_offset;
|
||||
speculative_maybe_derived_type = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2033,19 +2018,19 @@ get_class_context (ipa_polymorphic_call_context *context,
|
|||
if (!tree_fits_shwi_p (TYPE_SIZE (subtype))
|
||||
|| !tree_to_shwi (TYPE_SIZE (subtype)) <= 0)
|
||||
goto give_up;
|
||||
offset = offset % tree_to_shwi (TYPE_SIZE (subtype));
|
||||
cur_offset = cur_offset % tree_to_shwi (TYPE_SIZE (subtype));
|
||||
type = subtype;
|
||||
if (!speculative)
|
||||
{
|
||||
context->outer_type = type;
|
||||
context->offset = offset;
|
||||
context->maybe_derived_type = false;
|
||||
outer_type = type;
|
||||
offset = cur_offset;
|
||||
maybe_derived_type = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->speculative_outer_type = type;
|
||||
context->speculative_offset = offset;
|
||||
context->speculative_maybe_derived_type = false;
|
||||
speculative_outer_type = type;
|
||||
speculative_offset = cur_offset;
|
||||
speculative_maybe_derived_type = false;
|
||||
}
|
||||
}
|
||||
/* Give up on anything else. */
|
||||
|
@ -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
|
||||
most generic query. */
|
||||
give_up:
|
||||
clear_speculation (context);
|
||||
clear_speculation ();
|
||||
if (valid)
|
||||
return true;
|
||||
context->outer_type = expected_type;
|
||||
context->offset = 0;
|
||||
context->maybe_derived_type = true;
|
||||
context->maybe_in_construction = true;
|
||||
outer_type = expected_type;
|
||||
offset = 0;
|
||||
maybe_derived_type = true;
|
||||
maybe_in_construction = true;
|
||||
/* POD can be changed to an instance of a polymorphic type by
|
||||
placement new. Here we play safe and assume that any
|
||||
non-polymorphic type is POD. */
|
||||
|
@ -2071,7 +2056,7 @@ give_up:
|
|||
|| !polymorphic_type_binfo_p (TYPE_BINFO (type)))
|
||||
&& (!TYPE_SIZE (type)
|
||||
|| 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)))))
|
||||
return true;
|
||||
return false;
|
||||
|
@ -2083,10 +2068,10 @@ static bool
|
|||
contains_type_p (tree outer_type, HOST_WIDE_INT offset,
|
||||
tree otr_type)
|
||||
{
|
||||
ipa_polymorphic_call_context context = {offset, 0,
|
||||
TYPE_MAIN_VARIANT (outer_type),
|
||||
NULL, false, true, false};
|
||||
return get_class_context (&context, otr_type);
|
||||
ipa_polymorphic_call_context context;
|
||||
context.offset = offset;
|
||||
context.outer_type = TYPE_MAIN_VARIANT (outer_type);
|
||||
return context.restrict_to_inner_class (otr_type);
|
||||
}
|
||||
|
||||
/* 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)
|
|||
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.
|
||||
INSTANCE is pointer to the outer instance as returned by
|
||||
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)
|
|||
So it is not suitable for use withing fold_stmt and similar uses. */
|
||||
|
||||
bool
|
||||
get_dynamic_type (tree instance,
|
||||
ipa_polymorphic_call_context *context,
|
||||
tree otr_object,
|
||||
tree otr_type,
|
||||
gimple call)
|
||||
ipa_polymorphic_call_context::get_dynamic_type (tree instance,
|
||||
tree otr_object,
|
||||
tree otr_type,
|
||||
gimple call)
|
||||
{
|
||||
struct type_change_info tci;
|
||||
ao_ref ao;
|
||||
|
@ -2863,7 +2847,7 @@ get_dynamic_type (tree instance,
|
|||
tree instance_ref = NULL;
|
||||
gimple stmt = call;
|
||||
|
||||
if (!context->maybe_in_construction && !context->maybe_derived_type)
|
||||
if (!maybe_in_construction && !maybe_derived_type)
|
||||
return false;
|
||||
|
||||
/* We need to obtain refernce to virtual table pointer. It is better
|
||||
|
@ -2916,11 +2900,11 @@ get_dynamic_type (tree instance,
|
|||
or from INSTANCE with offset OFFSET. */
|
||||
if (base_ref
|
||||
&& ((TREE_CODE (base_ref) == MEM_REF
|
||||
&& ((offset2 == context->offset
|
||||
&& ((offset2 == offset
|
||||
&& TREE_OPERAND (base_ref, 0) == instance)
|
||||
|| (!offset2 && TREE_OPERAND (base_ref, 0) == otr_object)))
|
||||
|| (DECL_P (instance) && base_ref == instance
|
||||
&& offset2 == context->offset)))
|
||||
&& offset2 == offset)))
|
||||
{
|
||||
stmt = SSA_NAME_DEF_STMT (ref);
|
||||
instance_ref = ref_exp;
|
||||
|
@ -2959,13 +2943,13 @@ get_dynamic_type (tree instance,
|
|||
print_generic_expr (dump_file, otr_object, TDF_SLIM);
|
||||
fprintf (dump_file, " Outer instance pointer: ");
|
||||
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: ");
|
||||
print_generic_expr (dump_file, instance_ref, TDF_SLIM);
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
|
||||
tci.offset = context->offset;
|
||||
tci.offset = offset;
|
||||
tci.instance = instance;
|
||||
tci.vtbl_ptr_ref = instance_ref;
|
||||
gcc_assert (TREE_CODE (instance) != MEM_REF);
|
||||
|
@ -3021,17 +3005,17 @@ get_dynamic_type (tree instance,
|
|||
and we can stop, we will never see the calls into constructors of
|
||||
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
|
||||
only if there was dyanmic type store that may affect given variable
|
||||
(seen_unanalyzed_store) */
|
||||
|
||||
if (!tci.type_maybe_changed)
|
||||
{
|
||||
if (!context->outer_type || tci.seen_unanalyzed_store)
|
||||
if (!outer_type || tci.seen_unanalyzed_store)
|
||||
return false;
|
||||
if (context->maybe_in_construction)
|
||||
context->maybe_in_construction = false;
|
||||
if (maybe_in_construction)
|
||||
maybe_in_construction = false;
|
||||
if (dump_file)
|
||||
fprintf (dump_file, " No dynamic type change found.\n");
|
||||
return true;
|
||||
|
@ -3044,25 +3028,25 @@ get_dynamic_type (tree instance,
|
|||
if (!tci.speculative
|
||||
/* Again in instances located in static storage we are interested only
|
||||
in constructor stores. */
|
||||
|| (context->outer_type
|
||||
|| (outer_type
|
||||
&& !tci.seen_unanalyzed_store
|
||||
&& context->offset == tci.offset
|
||||
&& offset == tci.offset
|
||||
&& types_same_for_odr (tci.known_current_type,
|
||||
context->outer_type)))
|
||||
outer_type)))
|
||||
{
|
||||
context->outer_type = tci.known_current_type;
|
||||
context->offset = tci.known_current_offset;
|
||||
context->maybe_in_construction = false;
|
||||
context->maybe_derived_type = false;
|
||||
outer_type = tci.known_current_type;
|
||||
offset = tci.known_current_offset;
|
||||
maybe_in_construction = false;
|
||||
maybe_derived_type = false;
|
||||
if (dump_file)
|
||||
fprintf (dump_file, " Determined dynamic type.\n");
|
||||
}
|
||||
else if (!context->speculative_outer_type
|
||||
|| context->speculative_maybe_derived_type)
|
||||
else if (!speculative_outer_type
|
||||
|| speculative_maybe_derived_type)
|
||||
{
|
||||
context->speculative_outer_type = tci.known_current_type;
|
||||
context->speculative_offset = tci.known_current_offset;
|
||||
context->speculative_maybe_derived_type = false;
|
||||
speculative_outer_type = tci.known_current_type;
|
||||
speculative_offset = tci.known_current_offset;
|
||||
speculative_maybe_derived_type = false;
|
||||
if (dump_file)
|
||||
fprintf (dump_file, " Determined speculative dynamic type.\n");
|
||||
}
|
||||
|
@ -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. */
|
||||
if (!speculative_targetsp || !context.speculative_outer_type)
|
||||
clear_speculation (&context);
|
||||
context.clear_speculation ();
|
||||
|
||||
type = get_odr_type (otr_type, true);
|
||||
|
||||
|
@ -3263,7 +3247,7 @@ possible_polymorphic_call_targets (tree otr_type,
|
|||
|
||||
/* Lookup the outer class type we want to walk. */
|
||||
if ((context.outer_type || context.speculative_outer_type)
|
||||
&& !get_class_context (&context, otr_type))
|
||||
&& !context.restrict_to_inner_class (otr_type))
|
||||
{
|
||||
if (completep)
|
||||
*completep = false;
|
||||
|
@ -3274,7 +3258,7 @@ possible_polymorphic_call_targets (tree otr_type,
|
|||
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
|
||||
|| TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type);
|
||||
|
||||
|
|
|
@ -2356,9 +2356,9 @@ ipa_analyze_call_uses (struct func_body_info *fbi, gimple call)
|
|||
&otr_type, &otr_token,
|
||||
&context, call);
|
||||
|
||||
if (get_dynamic_type (instance, &context,
|
||||
OBJ_TYPE_REF_OBJECT (target),
|
||||
otr_type, call))
|
||||
if (context.get_dynamic_type (instance,
|
||||
OBJ_TYPE_REF_OBJECT (target),
|
||||
otr_type, call))
|
||||
{
|
||||
gcc_assert (TREE_CODE (otr_type) == RECORD_TYPE);
|
||||
cs->indirect_info->polymorphic = true;
|
||||
|
|
|
@ -36,7 +36,9 @@ struct ipa_dfs_info {
|
|||
|
||||
/* Context of polymorphic call. This is used by ipa-devirt walkers of the
|
||||
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
|
||||
at offset OFFSET. When information is not 100% reliable, we
|
||||
use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */
|
||||
|
@ -51,10 +53,58 @@ struct ipa_polymorphic_call_context {
|
|||
/* True if speculative outer object may be of derived type. We always
|
||||
speculate that construction does not happen. */
|
||||
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". */
|
||||
extern const ipa_polymorphic_call_context ipa_dummy_polymorphic_call_context;
|
||||
/* Build polymorphic call context for indirect call E. */
|
||||
|
||||
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 */
|
||||
void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);
|
||||
|
@ -95,7 +145,6 @@ tree get_polymorphic_call_info (tree, tree, tree *,
|
|||
HOST_WIDE_INT *,
|
||||
ipa_polymorphic_call_context *,
|
||||
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 *,
|
||||
tree, tree, HOST_WIDE_INT);
|
||||
bool decl_maybe_in_construction_p (tree, tree, gimple, tree);
|
||||
|
@ -121,13 +170,7 @@ possible_polymorphic_call_targets (struct cgraph_edge *e,
|
|||
int *nonconstruction_targets = NULL)
|
||||
{
|
||||
gcc_checking_assert (e->indirect_info->polymorphic);
|
||||
ipa_polymorphic_call_context context = {e->indirect_info->offset,
|
||||
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};
|
||||
ipa_polymorphic_call_context context(e);
|
||||
return possible_polymorphic_call_targets (e->indirect_info->otr_type,
|
||||
e->indirect_info->otr_token,
|
||||
context,
|
||||
|
@ -163,13 +206,7 @@ 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->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};
|
||||
ipa_polymorphic_call_context context(e);
|
||||
dump_possible_polymorphic_call_targets (f, e->indirect_info->otr_type,
|
||||
e->indirect_info->otr_token,
|
||||
context);
|
||||
|
@ -182,11 +219,7 @@ inline bool
|
|||
possible_polymorphic_call_target_p (struct cgraph_edge *e,
|
||||
struct cgraph_node *n)
|
||||
{
|
||||
ipa_polymorphic_call_context context = {e->indirect_info->offset, 0,
|
||||
e->indirect_info->outer_type, NULL,
|
||||
e->indirect_info->maybe_in_construction,
|
||||
e->indirect_info->maybe_derived_type,
|
||||
false};
|
||||
ipa_polymorphic_call_context context(e);
|
||||
return possible_polymorphic_call_target_p (e->indirect_info->otr_type,
|
||||
e->indirect_info->otr_token,
|
||||
context, n);
|
||||
|
@ -199,10 +232,11 @@ 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)),
|
||||
ipa_dummy_polymorphic_call_context,
|
||||
context,
|
||||
n);
|
||||
}
|
||||
#endif /* GCC_IPA_UTILS_H */
|
||||
|
|
|
@ -4374,8 +4374,7 @@ eliminate_dom_walker::before_dom_children (basic_block b)
|
|||
fn,
|
||||
&otr_type, &otr_token, &context, stmt);
|
||||
|
||||
get_dynamic_type (instance, &context,
|
||||
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
|
||||
= possible_polymorphic_call_targets (obj_type_ref_class (fn),
|
||||
|
|
Loading…
Reference in New Issue