Commit d570d364 by Jan Hubicka Committed by Jan Hubicka

ipa-utils.h (method_class_type, [...]): Constify.


	* ipa-utils.h (method_class_type, vtable_pointer_value_to_binfo,
	vtable_pointer_value_to_vtable): Constify.
	(contains_polymorphic_type_p): Declare.
	* ipa-devirt.c (method_class_type, vtable_pointer_value_to_binfo,
	vtable_pointer_value_to_vtable): Constify.
	(contains_polymorphic_type_p): New predicate.
	* ipa-prop.c (ipa_set_jf_known_type): Allow types containing
	polymorphic types.
	(ipa_set_ancestor_jf): Likewise.
	(detect_type_change): Return false in easy cases.
	(compute_complex_assign_jump_func): Require type to contain
	polymorphic type.
	(compute_known_type_jump_func): Likewise.

From-SVN: r212222
parent a90532fd
2014-07-01 Jan Hubicka <hubicka@ucw.cz> 2014-07-01 Jan Hubicka <hubicka@ucw.cz>
* ipa-utils.h (method_class_type, vtable_pointer_value_to_binfo,
vtable_pointer_value_to_vtable): Constify.
(contains_polymorphic_type_p): Declare.
* ipa-devirt.c (method_class_type, vtable_pointer_value_to_binfo,
vtable_pointer_value_to_vtable): Constify.
(contains_polymorphic_type_p): New predicate.
* ipa-prop.c (ipa_set_jf_known_type): Allow types containing
polymorphic types.
(ipa_set_ancestor_jf): Likewise.
(detect_type_change): Return false in easy cases.
(compute_complex_assign_jump_func): Require type to contain
polymorphic type.
(compute_known_type_jump_func): Likewise.
2014-07-01 Jan Hubicka <hubicka@ucw.cz>
* tree.c (decls_same_for_odr, decls_same_for_odr, * tree.c (decls_same_for_odr, decls_same_for_odr,
types_same_for_odr): Remove. types_same_for_odr): Remove.
(type_in_anonymous_namespace_p): Constify argument. (type_in_anonymous_namespace_p): Constify argument.
......
...@@ -742,7 +742,7 @@ dump_type_inheritance_graph (FILE *f) ...@@ -742,7 +742,7 @@ dump_type_inheritance_graph (FILE *f)
Lookup this pointer and get its type. */ Lookup this pointer and get its type. */
tree tree
method_class_type (tree t) method_class_type (const_tree t)
{ {
tree first_parm_type = TREE_VALUE (TYPE_ARG_TYPES (t)); tree first_parm_type = TREE_VALUE (TYPE_ARG_TYPES (t));
gcc_assert (TREE_CODE (t) == METHOD_TYPE); gcc_assert (TREE_CODE (t) == METHOD_TYPE);
...@@ -1187,6 +1187,31 @@ devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED) ...@@ -1187,6 +1187,31 @@ devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
free_polymorphic_call_targets_hash (); free_polymorphic_call_targets_hash ();
} }
/* Return true when TYPE contains an polymorphic type and thus is interesting
for devirtualization machinery. */
bool
contains_polymorphic_type_p (const_tree type)
{
type = TYPE_MAIN_VARIANT (type);
if (RECORD_OR_UNION_TYPE_P (type))
{
if (TYPE_BINFO (type)
&& polymorphic_type_binfo_p (TYPE_BINFO (type)))
return true;
for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
if (TREE_CODE (fld) == FIELD_DECL
&& !DECL_ARTIFICIAL (fld)
&& contains_polymorphic_type_p (TREE_TYPE (fld)))
return true;
return false;
}
if (TREE_CODE (type) == ARRAY_TYPE)
return contains_polymorphic_type_p (TREE_TYPE (type));
return false;
}
/* CONTEXT->OUTER_TYPE is a type of memory object where object of EXPECTED_TYPE /* CONTEXT->OUTER_TYPE is a type of memory object where object of EXPECTED_TYPE
is contained at CONTEXT->OFFSET. Walk the memory representation of is contained at CONTEXT->OFFSET. Walk the memory representation of
CONTEXT->OUTER_TYPE and find the outermost class type that match CONTEXT->OUTER_TYPE and find the outermost class type that match
...@@ -1349,7 +1374,8 @@ subbinfo_with_vtable_at_offset (tree binfo, unsigned HOST_WIDE_INT offset, ...@@ -1349,7 +1374,8 @@ subbinfo_with_vtable_at_offset (tree binfo, unsigned HOST_WIDE_INT offset,
Return false if T does not look like virtual table reference. */ Return false if T does not look like virtual table reference. */
bool bool
vtable_pointer_value_to_vtable (tree t, tree *v, unsigned HOST_WIDE_INT *offset) vtable_pointer_value_to_vtable (const_tree t, tree *v,
unsigned HOST_WIDE_INT *offset)
{ {
/* We expect &MEM[(void *)&virtual_table + 16B]. /* We expect &MEM[(void *)&virtual_table + 16B].
We obtain object's BINFO from the context of the virtual table. We obtain object's BINFO from the context of the virtual table.
...@@ -1395,7 +1421,7 @@ vtable_pointer_value_to_vtable (tree t, tree *v, unsigned HOST_WIDE_INT *offset) ...@@ -1395,7 +1421,7 @@ vtable_pointer_value_to_vtable (tree t, tree *v, unsigned HOST_WIDE_INT *offset)
instance type. */ instance type. */
tree tree
vtable_pointer_value_to_binfo (tree t) vtable_pointer_value_to_binfo (const_tree t)
{ {
tree vtable; tree vtable;
unsigned HOST_WIDE_INT offset; unsigned HOST_WIDE_INT offset;
......
...@@ -443,11 +443,10 @@ ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset, ...@@ -443,11 +443,10 @@ ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
base_type = TYPE_MAIN_VARIANT (base_type); base_type = TYPE_MAIN_VARIANT (base_type);
component_type = TYPE_MAIN_VARIANT (component_type); component_type = TYPE_MAIN_VARIANT (component_type);
gcc_assert (TREE_CODE (component_type) == RECORD_TYPE gcc_assert (contains_polymorphic_type_p (base_type)
&& TYPE_BINFO (component_type)); && contains_polymorphic_type_p (component_type));
if (!flag_devirtualize) if (!flag_devirtualize)
return; return;
gcc_assert (BINFO_VTABLE (TYPE_BINFO (component_type)));
jfunc->type = IPA_JF_KNOWN_TYPE; jfunc->type = IPA_JF_KNOWN_TYPE;
jfunc->value.known_type.offset = offset, jfunc->value.known_type.offset = offset,
jfunc->value.known_type.base_type = base_type; jfunc->value.known_type.base_type = base_type;
...@@ -534,12 +533,11 @@ ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset, ...@@ -534,12 +533,11 @@ ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset,
{ {
if (!flag_devirtualize) if (!flag_devirtualize)
type_preserved = false; type_preserved = false;
if (!type_preserved)
type = NULL_TREE;
if (type) if (type)
type = TYPE_MAIN_VARIANT (type); type = TYPE_MAIN_VARIANT (type);
gcc_assert (!type_preserved gcc_assert (!type_preserved || contains_polymorphic_type_p (type));
|| (TREE_CODE (type) == RECORD_TYPE
&& TYPE_BINFO (type)
&& BINFO_VTABLE (TYPE_BINFO (type))));
jfunc->type = IPA_JF_ANCESTOR; jfunc->type = IPA_JF_ANCESTOR;
jfunc->value.ancestor.formal_id = formal_id; jfunc->value.ancestor.formal_id = formal_id;
jfunc->value.ancestor.offset = offset; jfunc->value.ancestor.offset = offset;
...@@ -752,18 +750,12 @@ detect_type_change (tree arg, tree base, tree comp_type, gimple call, ...@@ -752,18 +750,12 @@ detect_type_change (tree arg, tree base, tree comp_type, gimple call,
gcc_checking_assert (DECL_P (arg) gcc_checking_assert (DECL_P (arg)
|| TREE_CODE (arg) == MEM_REF || TREE_CODE (arg) == MEM_REF
|| handled_component_p (arg)); || handled_component_p (arg));
/* Const calls cannot call virtual methods through VMT and so type changes do
not matter. */
if (!flag_devirtualize || !gimple_vuse (call)
/* Be sure expected_type is polymorphic. */
|| !comp_type
|| TREE_CODE (comp_type) != RECORD_TYPE
|| !TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))
|| !BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))))
return true;
comp_type = TYPE_MAIN_VARIANT (comp_type); comp_type = TYPE_MAIN_VARIANT (comp_type);
if (!flag_devirtualize)
return false;
/* C++ methods are not allowed to change THIS pointer unless they /* C++ methods are not allowed to change THIS pointer unless they
are constructors or destructors. */ are constructors or destructors. */
if (TREE_CODE (base) == MEM_REF if (TREE_CODE (base) == MEM_REF
...@@ -775,7 +767,20 @@ detect_type_change (tree arg, tree base, tree comp_type, gimple call, ...@@ -775,7 +767,20 @@ detect_type_change (tree arg, tree base, tree comp_type, gimple call,
&& !DECL_CXX_DESTRUCTOR_P (current_function_decl) && !DECL_CXX_DESTRUCTOR_P (current_function_decl)
&& (SSA_NAME_VAR (TREE_OPERAND (base, 0)) && (SSA_NAME_VAR (TREE_OPERAND (base, 0))
== DECL_ARGUMENTS (current_function_decl))) == DECL_ARGUMENTS (current_function_decl)))
return false; {
gcc_assert (comp_type);
return false;
}
/* Const calls cannot call virtual methods through VMT and so type changes do
not matter. */
if (!flag_devirtualize || !gimple_vuse (call)
/* Be sure expected_type is polymorphic. */
|| !comp_type
|| TREE_CODE (comp_type) != RECORD_TYPE
|| !TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))
|| !BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (comp_type))))
return true;
ao_ref_init (&ao, arg); ao_ref_init (&ao, arg);
ao.base = base; ao.base = base;
...@@ -1258,8 +1263,9 @@ compute_complex_assign_jump_func (struct func_body_info *fbi, ...@@ -1258,8 +1263,9 @@ compute_complex_assign_jump_func (struct func_body_info *fbi,
index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa)); index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa));
if (index >= 0 && param_type && POINTER_TYPE_P (param_type)) if (index >= 0 && param_type && POINTER_TYPE_P (param_type))
{ {
bool type_p = !detect_type_change (op1, base, TREE_TYPE (param_type), bool type_p = (contains_polymorphic_type_p (TREE_TYPE (param_type))
call, jfunc, offset); && !detect_type_change (op1, base, TREE_TYPE (param_type),
call, jfunc, offset));
if (type_p || jfunc->type == IPA_JF_UNKNOWN) if (type_p || jfunc->type == IPA_JF_UNKNOWN)
ipa_set_ancestor_jf (jfunc, offset, ipa_set_ancestor_jf (jfunc, offset,
type_p ? TREE_TYPE (param_type) : NULL, index, type_p ? TREE_TYPE (param_type) : NULL, index,
...@@ -1391,7 +1397,8 @@ compute_complex_ancestor_jump_func (struct func_body_info *fbi, ...@@ -1391,7 +1397,8 @@ compute_complex_ancestor_jump_func (struct func_body_info *fbi,
} }
bool type_p = false; bool type_p = false;
if (param_type && POINTER_TYPE_P (param_type)) if (param_type && POINTER_TYPE_P (param_type)
&& contains_polymorphic_type_p (TREE_TYPE (param_type)))
type_p = !detect_type_change (obj, expr, TREE_TYPE (param_type), type_p = !detect_type_change (obj, expr, TREE_TYPE (param_type),
call, jfunc, offset); call, jfunc, offset);
if (type_p || jfunc->type == IPA_JF_UNKNOWN) if (type_p || jfunc->type == IPA_JF_UNKNOWN)
...@@ -1415,12 +1422,10 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc, ...@@ -1415,12 +1422,10 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc,
if (!flag_devirtualize if (!flag_devirtualize
|| TREE_CODE (op) != ADDR_EXPR || TREE_CODE (op) != ADDR_EXPR
|| TREE_CODE (TREE_TYPE (TREE_TYPE (op))) != RECORD_TYPE || !contains_polymorphic_type_p (TREE_TYPE (TREE_TYPE (op)))
/* Be sure expected_type is polymorphic. */ /* Be sure expected_type is polymorphic. */
|| !expected_type || !expected_type
|| TREE_CODE (expected_type) != RECORD_TYPE || !contains_polymorphic_type_p (expected_type))
|| !TYPE_BINFO (TYPE_MAIN_VARIANT (expected_type))
|| !BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (expected_type))))
return; return;
op = TREE_OPERAND (op, 0); op = TREE_OPERAND (op, 0);
...@@ -1428,7 +1433,7 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc, ...@@ -1428,7 +1433,7 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc,
if (!DECL_P (base) if (!DECL_P (base)
|| max_size == -1 || max_size == -1
|| max_size != size || max_size != size
|| TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE || !contains_polymorphic_type_p (TREE_TYPE (base))
|| is_global_var (base)) || is_global_var (base))
return; return;
......
...@@ -83,15 +83,16 @@ void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT, ...@@ -83,15 +83,16 @@ 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 *n); struct cgraph_node *);
tree method_class_type (tree); tree method_class_type (const_tree);
tree get_polymorphic_call_info (tree, tree, tree *, tree get_polymorphic_call_info (tree, tree, tree *,
HOST_WIDE_INT *, HOST_WIDE_INT *,
ipa_polymorphic_call_context *); ipa_polymorphic_call_context *);
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);
tree vtable_pointer_value_to_binfo (tree t); tree vtable_pointer_value_to_binfo (const_tree);
bool vtable_pointer_value_to_vtable (tree, tree *, unsigned HOST_WIDE_INT *); bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *);
bool contains_polymorphic_type_p (const_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 FINALP is non-NULL, store true if the list is complette.
......
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