From 4db4241dd512cf274d07b301215c715abfd9559f Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Mon, 18 May 2015 15:25:22 +0800 Subject: Cherry-pick r212222 BUG=19872411 2014-07-01 Jan Hubicka * 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. Change-Id: If4b1a919f00fb1b23c6ebce84141c04120e0e2b6 --- gcc-4.9/gcc/ipa-devirt.c | 32 +++++++++++++++++++++++++--- gcc-4.9/gcc/ipa-prop.c | 55 ++++++++++++++++++++++++++---------------------- gcc-4.9/gcc/ipa-utils.h | 9 ++++---- 3 files changed, 64 insertions(+), 32 deletions(-) (limited to 'gcc-4.9') diff --git a/gcc-4.9/gcc/ipa-devirt.c b/gcc-4.9/gcc/ipa-devirt.c index 0671a8b78..43e904ce7 100644 --- a/gcc-4.9/gcc/ipa-devirt.c +++ b/gcc-4.9/gcc/ipa-devirt.c @@ -534,7 +534,7 @@ dump_type_inheritance_graph (FILE *f) Lookup this pointer and get its type. */ tree -method_class_type (tree t) +method_class_type (const_tree t) { tree first_parm_type = TREE_VALUE (TYPE_ARG_TYPES (t)); gcc_assert (TREE_CODE (t) == METHOD_TYPE); @@ -887,6 +887,31 @@ devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED) 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 is contained at CONTEXT->OFFSET. Walk the memory representation of CONTEXT->OUTER_TYPE and find the outermost class type that match @@ -1048,7 +1073,8 @@ subbinfo_with_vtable_at_offset (tree binfo, unsigned HOST_WIDE_INT offset, Return false if T does not look like virtual table reference. */ 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 obtain object's BINFO from the context of the virtual table. @@ -1094,7 +1120,7 @@ vtable_pointer_value_to_vtable (tree t, tree *v, unsigned HOST_WIDE_INT *offset) instance type. */ tree -vtable_pointer_value_to_binfo (tree t) +vtable_pointer_value_to_binfo (const_tree t) { tree vtable; unsigned HOST_WIDE_INT offset; diff --git a/gcc-4.9/gcc/ipa-prop.c b/gcc-4.9/gcc/ipa-prop.c index 2ccbbdbca..adfcb0354 100644 --- a/gcc-4.9/gcc/ipa-prop.c +++ b/gcc-4.9/gcc/ipa-prop.c @@ -394,11 +394,10 @@ static void ipa_set_jf_known_type (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset, tree base_type, tree component_type) { - gcc_assert (TREE_CODE (component_type) == RECORD_TYPE - && TYPE_BINFO (component_type)); + gcc_assert (contains_polymorphic_type_p (base_type) + && contains_polymorphic_type_p (component_type)); if (!flag_devirtualize) return; - gcc_assert (BINFO_VTABLE (TYPE_BINFO (component_type))); jfunc->type = IPA_JF_KNOWN_TYPE; jfunc->value.known_type.offset = offset, jfunc->value.known_type.base_type = base_type; @@ -485,10 +484,9 @@ ipa_set_ancestor_jf (struct ipa_jump_func *jfunc, HOST_WIDE_INT offset, { if (!flag_devirtualize) type_preserved = false; - gcc_assert (!type_preserved - || (TREE_CODE (type) == RECORD_TYPE - && TYPE_BINFO (type) - && BINFO_VTABLE (TYPE_BINFO (type)))); + if (!type_preserved) + type = NULL_TREE; + gcc_assert (!type_preserved || contains_polymorphic_type_p (type)); jfunc->type = IPA_JF_ANCESTOR; jfunc->value.ancestor.formal_id = formal_id; jfunc->value.ancestor.offset = offset; @@ -689,15 +687,9 @@ detect_type_change (tree arg, tree base, tree comp_type, gimple call, gcc_checking_assert (DECL_P (arg) || TREE_CODE (arg) == MEM_REF || 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 (comp_type) - || !BINFO_VTABLE (TYPE_BINFO (comp_type))) - return true; + + if (!flag_devirtualize) + return false; /* C++ methods are not allowed to change THIS pointer unless they are constructors or destructors. */ @@ -710,7 +702,20 @@ detect_type_change (tree arg, tree base, tree comp_type, gimple call, && !DECL_CXX_DESTRUCTOR_P (current_function_decl) && (SSA_NAME_VAR (TREE_OPERAND (base, 0)) == 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.base = base; @@ -1111,8 +1116,9 @@ compute_complex_assign_jump_func (struct ipa_node_params *info, index = ipa_get_param_decl_index (info, SSA_NAME_VAR (ssa)); if (index >= 0 && param_type && POINTER_TYPE_P (param_type)) { - bool type_p = !detect_type_change (op1, base, TREE_TYPE (param_type), - call, jfunc, offset); + bool type_p = (contains_polymorphic_type_p (TREE_TYPE (param_type)) + && !detect_type_change (op1, base, TREE_TYPE (param_type), + call, jfunc, offset)); if (type_p || jfunc->type == IPA_JF_UNKNOWN) ipa_set_ancestor_jf (jfunc, offset, type_p ? TREE_TYPE (param_type) : NULL, index, @@ -1244,7 +1250,8 @@ compute_complex_ancestor_jump_func (struct ipa_node_params *info, } 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), call, jfunc, offset); if (type_p || jfunc->type == IPA_JF_UNKNOWN) @@ -1267,12 +1274,10 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc, if (!flag_devirtualize || 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. */ || !expected_type - || TREE_CODE (expected_type) != RECORD_TYPE - || !TYPE_BINFO (expected_type) - || !BINFO_VTABLE (TYPE_BINFO (expected_type))) + || !contains_polymorphic_type_p (expected_type)) return; op = TREE_OPERAND (op, 0); @@ -1280,7 +1285,7 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc, if (!DECL_P (base) || max_size == -1 || max_size != size - || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE + || !contains_polymorphic_type_p (TREE_TYPE (base)) || is_global_var (base)) return; diff --git a/gcc-4.9/gcc/ipa-utils.h b/gcc-4.9/gcc/ipa-utils.h index 4d609096a..b1b0d1a8a 100644 --- a/gcc-4.9/gcc/ipa-utils.h +++ b/gcc-4.9/gcc/ipa-utils.h @@ -87,15 +87,16 @@ 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); + struct cgraph_node *); +tree method_class_type (const_tree); tree get_polymorphic_call_info (tree, tree, tree *, HOST_WIDE_INT *, ipa_polymorphic_call_context *); bool get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *, tree, tree, HOST_WIDE_INT); -tree vtable_pointer_value_to_binfo (tree t); -bool vtable_pointer_value_to_vtable (tree, tree *, unsigned HOST_WIDE_INT *); +tree vtable_pointer_value_to_binfo (const_tree); +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. If FINALP is non-NULL, store true if the list is complette. -- cgit v1.2.3