Hi, On Fri, Sep 16, 2011 at 04:29:44PM +0200, Jan Hubicka wrote: > > > > * ipa-prop.h (jump_func_type): Updated comments. > > (ipa_known_type_data): New type. > > (ipa_jump_func): Use it to describe known type jump functions. > > * ipa-prop.c (ipa_print_node_jump_functions_for_edge): Updated to > > reflect the new known type jump function contents. > > (compute_known_type_jump_func): Likewise. > > (combine_known_type_and_ancestor_jfs): Likewise. > > (try_make_edge_direct_virtual_call): Likewise. > > (ipa_write_jump_function): Likewise. > > (ipa_read_jump_function): Likewise. > > * ipa-cp.c (ipa_value_from_known_type_jfunc): New function. > > (ipa_value_from_jfunc): Use ipa_value_from_known_type_jfunc. > > (propagate_accross_jump_function): Likewise. > > OK. If we saved just one pointer to the actual type (i.e. not > BINFO), would it be any sanier? >
When C and C++ code is linked together, the prevailing representation of shared types might come from the C land and thus lack BINFOs. This then might then falsely trigger the assert I added to ipa_value_from_known_type_jfunc. Therefore I have committed a slightly different version with that assert replaced by a test. Thanks, Martin 2011-09-23 Martin Jambor <mjam...@suse.cz> * ipa-prop.h (jump_func_type): Updated comments. (ipa_known_type_data): New type. (ipa_jump_func): Use it to describe known type jump functions. * ipa-prop.c (ipa_print_node_jump_functions_for_edge): Updated to reflect the new known type jump function contents. (compute_known_type_jump_func): Likewise. (combine_known_type_and_ancestor_jfs): Likewise. (try_make_edge_direct_virtual_call): Likewise. (ipa_write_jump_function): Likewise. (ipa_read_jump_function): Likewise. * ipa-cp.c (ipa_value_from_known_type_jfunc): New function. (ipa_value_from_jfunc): Use ipa_value_from_known_type_jfunc. (propagate_accross_jump_function): Likewise. Index: src/gcc/ipa-cp.c =================================================================== --- src.orig/gcc/ipa-cp.c +++ src/gcc/ipa-cp.c @@ -674,6 +674,20 @@ ipa_get_jf_ancestor_result (struct ipa_j return NULL_TREE; } +/* Extract the acual BINFO being described by JFUNC which must be a known type + jump function. */ + +static tree +ipa_value_from_known_type_jfunc (struct ipa_jump_func *jfunc) +{ + tree base_binfo = TYPE_BINFO (jfunc->value.known_type.base_type); + if (!base_binfo) + return NULL_TREE; + return get_binfo_at_offset (base_binfo, + jfunc->value.known_type.offset, + jfunc->value.known_type.component_type); +} + /* Determine whether JFUNC evaluates to a known value (that is either a constant or a binfo) and if so, return it. Otherwise return NULL. INFO describes the caller node so that pass-through jump functions can be @@ -685,7 +699,7 @@ ipa_value_from_jfunc (struct ipa_node_pa if (jfunc->type == IPA_JF_CONST) return jfunc->value.constant; else if (jfunc->type == IPA_JF_KNOWN_TYPE) - return jfunc->value.base_binfo; + return ipa_value_from_known_type_jfunc (jfunc); else if (jfunc->type == IPA_JF_PASS_THROUGH || jfunc->type == IPA_JF_ANCESTOR) { @@ -991,7 +1005,11 @@ propagate_accross_jump_function (struct tree val; if (jfunc->type == IPA_JF_KNOWN_TYPE) - val = jfunc->value.base_binfo; + { + val = ipa_value_from_known_type_jfunc (jfunc); + if (!val) + return set_lattice_contains_variable (dest_lat); + } else val = jfunc->value.constant; return add_value_to_lattice (dest_lat, val, cs, NULL, 0); Index: src/gcc/ipa-prop.c =================================================================== --- src.orig/gcc/ipa-prop.c +++ src/gcc/ipa-prop.c @@ -164,10 +164,12 @@ ipa_print_node_jump_functions_for_edge ( fprintf (f, "UNKNOWN\n"); else if (type == IPA_JF_KNOWN_TYPE) { - tree binfo_type = TREE_TYPE (jump_func->value.base_binfo); - fprintf (f, "KNOWN TYPE, type in binfo is: "); - print_generic_expr (f, binfo_type, 0); - fprintf (f, " (%u)\n", TYPE_UID (binfo_type)); + fprintf (f, "KNOWN TYPE: base "); + print_generic_expr (f, jump_func->value.known_type.base_type, 0); + fprintf (f, ", offset "HOST_WIDE_INT_PRINT_DEC", component ", + jump_func->value.known_type.offset); + print_generic_expr (f, jump_func->value.known_type.component_type, 0); + fprintf (f, "\n"); } else if (type == IPA_JF_CONST) { @@ -638,7 +640,7 @@ compute_known_type_jump_func (tree op, s gimple call) { HOST_WIDE_INT offset, size, max_size; - tree base, binfo; + tree base; if (!flag_devirtualize || TREE_CODE (op) != ADDR_EXPR @@ -654,18 +656,14 @@ compute_known_type_jump_func (tree op, s || is_global_var (base)) return; - if (detect_type_change (op, base, call, jfunc, offset)) + if (detect_type_change (op, base, call, jfunc, offset) + || !TYPE_BINFO (TREE_TYPE (base))) return; - binfo = TYPE_BINFO (TREE_TYPE (base)); - if (!binfo) - return; - binfo = get_binfo_at_offset (binfo, offset, TREE_TYPE (op)); - if (binfo) - { - jfunc->type = IPA_JF_KNOWN_TYPE; - jfunc->value.base_binfo = binfo; - } + jfunc->type = IPA_JF_KNOWN_TYPE; + jfunc->value.known_type.base_type = TREE_TYPE (base); + jfunc->value.known_type.offset = offset; + jfunc->value.known_type.component_type = TREE_TYPE (op); } @@ -1504,18 +1502,16 @@ static void combine_known_type_and_ancestor_jfs (struct ipa_jump_func *src, struct ipa_jump_func *dst) { - tree new_binfo; + HOST_WIDE_INT combined_offset; + tree combined_type; - new_binfo = get_binfo_at_offset (src->value.base_binfo, - dst->value.ancestor.offset, - dst->value.ancestor.type); - if (new_binfo) - { - dst->type = IPA_JF_KNOWN_TYPE; - dst->value.base_binfo = new_binfo; - } - else - dst->type = IPA_JF_UNKNOWN; + combined_offset = src->value.known_type.offset + dst->value.ancestor.offset; + combined_type = dst->value.ancestor.type; + + dst->type = IPA_JF_KNOWN_TYPE; + dst->value.known_type.base_type = src->value.known_type.base_type; + dst->value.known_type.offset = combined_offset; + dst->value.known_type.component_type = combined_type; } /* Update the jump functions associated with call graph edge E when the call @@ -1650,22 +1646,19 @@ static struct cgraph_edge * try_make_edge_direct_virtual_call (struct cgraph_edge *ie, struct ipa_jump_func *jfunc) { - tree binfo, type, target; - HOST_WIDE_INT token; - - if (jfunc->type == IPA_JF_KNOWN_TYPE) - binfo = jfunc->value.base_binfo; - else - return NULL; + tree binfo, target; - if (!binfo) + if (jfunc->type != IPA_JF_KNOWN_TYPE) return NULL; - token = ie->indirect_info->otr_token; - type = ie->indirect_info->otr_type; - binfo = get_binfo_at_offset (binfo, ie->indirect_info->anc_offset, type); + binfo = TYPE_BINFO (jfunc->value.known_type.base_type); + gcc_checking_assert (binfo); + binfo = get_binfo_at_offset (binfo, jfunc->value.known_type.offset + + ie->indirect_info->anc_offset, + ie->indirect_info->otr_type); if (binfo) - target = gimple_get_virt_method_for_binfo (token, binfo); + target = gimple_get_virt_method_for_binfo (ie->indirect_info->otr_token, + binfo); else return NULL; @@ -2589,7 +2582,9 @@ ipa_write_jump_function (struct output_b case IPA_JF_UNKNOWN: break; case IPA_JF_KNOWN_TYPE: - stream_write_tree (ob, jump_func->value.base_binfo, true); + streamer_write_uhwi (ob, jump_func->value.known_type.offset); + stream_write_tree (ob, jump_func->value.known_type.base_type, true); + stream_write_tree (ob, jump_func->value.known_type.component_type, true); break; case IPA_JF_CONST: stream_write_tree (ob, jump_func->value.constant, true); @@ -2625,7 +2620,10 @@ ipa_read_jump_function (struct lto_input case IPA_JF_UNKNOWN: break; case IPA_JF_KNOWN_TYPE: - jump_func->value.base_binfo = stream_read_tree (ib, data_in); + jump_func->value.known_type.offset = streamer_read_uhwi (ib); + jump_func->value.known_type.base_type = stream_read_tree (ib, data_in); + jump_func->value.known_type.component_type = stream_read_tree (ib, + data_in); break; case IPA_JF_CONST: jump_func->value.constant = stream_read_tree (ib, data_in); Index: src/gcc/ipa-prop.h =================================================================== --- src.orig/gcc/ipa-prop.h +++ src/gcc/ipa-prop.h @@ -72,13 +72,24 @@ along with GCC; see the file COPYING3. enum jump_func_type { IPA_JF_UNKNOWN = 0, /* newly allocated and zeroed jump functions default */ - IPA_JF_KNOWN_TYPE, /* represented by field base_binfo */ + IPA_JF_KNOWN_TYPE, /* represented by field known_type */ IPA_JF_CONST, /* represented by field costant */ IPA_JF_CONST_MEMBER_PTR, /* represented by field member_cst */ IPA_JF_PASS_THROUGH, /* represented by field pass_through */ IPA_JF_ANCESTOR /* represented by field ancestor */ }; +/* Structure holding data required to describe a known type jump function. */ +struct GTY(()) ipa_known_type_data +{ + /* Offset of the component of the base_type being described. */ + HOST_WIDE_INT offset; + /* Type of the whole object. */ + tree base_type; + /* Type of the component of the object that is being described. */ + tree component_type; +}; + /* Structure holding data required to describe a pass-through jump function. */ struct GTY(()) ipa_pass_through_data @@ -127,7 +138,7 @@ typedef struct GTY (()) ipa_jump_func functions and member_cst holds constant c++ member functions. */ union jump_func_value { - tree GTY ((tag ("IPA_JF_KNOWN_TYPE"))) base_binfo; + struct ipa_known_type_data GTY ((tag ("IPA_JF_KNOWN_TYPE"))) known_type; tree GTY ((tag ("IPA_JF_CONST"))) constant; struct ipa_member_ptr_cst GTY ((tag ("IPA_JF_CONST_MEMBER_PTR"))) member_cst; struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH"))) pass_through;