diff options
author | Feng Xue <fxue@os.amperecomputing.com> | 2019-11-14 03:19:15 +0000 |
---|---|---|
committer | Feng Xue <fxue@gcc.gnu.org> | 2019-11-14 03:19:15 +0000 |
commit | eb270950acbae6f70e3487a6e63a26c1294656b3 (patch) | |
tree | d64f761c523baf3052aaaff96fd28ca6a47d6aaf /gcc/ipa-cp.c | |
parent | 3e7cf2e6c0ee30b83aa158b7bd2b2eb9a686c1c3 (diff) | |
download | gcc-eb270950acbae6f70e3487a6e63a26c1294656b3.zip gcc-eb270950acbae6f70e3487a6e63a26c1294656b3.tar.gz gcc-eb270950acbae6f70e3487a6e63a26c1294656b3.tar.bz2 |
Support extended aggregate jump function in ipa-cp
2019-11-14 Feng Xue <fxue@os.amperecomputing.com>
PR ipa/91682
* ipa-prop.h (jump_func_type): New value IPA_JF_LOAD_AGG.
(ipa_load_agg_data, ipa_agg_value, ipa_agg_value_set): New structs.
(ipa_agg_jf_item): Add new field jftype and type, redefine field value.
(ipa_agg_jump_function): Remove member function equal_to.
(ipa_agg_jump_function_p): Remove typedef.
(ipa_copy_agg_values, ipa_release_agg_values): New functions.
* ipa-prop.c (ipa_print_node_jump_functions_for_edge): Dump
information for aggregate jump function.
(get_ssa_def_if_simple_copy): Add new parameter rhs_stmt to
record last definition statement.
(load_from_unmodified_param_or_agg): New function.
(ipa_known_agg_contents_list): Add new field type and value, remove
field constant.
(build_agg_jump_func_from_list): Rename parameter const_count to
value_count, build aggregate jump function from ipa_load_agg_data.
(analyze_agg_content_value): New function.
(extract_mem_content): Analyze memory store assignment to prepare
information for aggregate jump function generation.
(determine_known_aggregate_parts): Add new parameter fbi, remove
parameter aa_walk_budeget_p.
(update_jump_functions_after_inlining): Update aggregate jump function.
(ipa_find_agg_cst_for_param): Change type of parameter agg.
(try_make_edge_direct_simple_call): Add new parameter new_root.
(try_make_edge_direct_virtual_call): Add new parameter new_root and
new_root_info.
(update_indirect_edges_after_inlining): Pass new argument to
try_make_edge_direct_simple_call and try_make_edge_direct_virtual_call.
(ipa_write_jump_function): Write aggregate jump function to file.
(ipa_read_jump_function): Read aggregate jump function from file.
(ipa_agg_value::equal_to): Migrate from ipa_agg_jf_item::equal_to.
* ipa-cp.c (ipa_get_jf_arith_result): New function.
(ipa_agg_value_from_node): Likewise.
(ipa_agg_value_set_from_jfunc): Likewise.
(propagate_vals_across_arith_jfunc): Likewise.
(propagate_aggregate_lattice): Likewise.
(ipa_get_jf_pass_through_result): Call ipa_get_jf_arith_result.
(propagate_vals_across_pass_through): Call
propagate_vals_across_arith_jfunc.
(get_clone_agg_value): Move forward.
(propagate_aggs_across_jump_function): Handle value propagation for
aggregate jump function.
(agg_jmp_p_vec_for_t_vec): Remove.
(context_independent_aggregate_values): Replace vec<ipa_agg_jf_item>
with vec<ipa_agg_value>.
(copy_plats_to_inter, intersect_with_plats): Likewise.
(agg_replacements_to_vector, intersect_with_agg_replacements): Likewise.
(intersect_aggregate_with_edge): Likewise.
(find_aggregate_values_for_callers_subset): Likewise.
(cgraph_edge_brings_all_agg_vals_for_node): Likewise.
(estimate_local_effects): Replace vec<ipa_agg_jump_function> and
vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
(gather_context_independent_values): Likewise.
(perform_estimation_of_a_value, decide_whether_version_node): Likewise.
* ipa-fnsummary.c (evaluate_conditions_for_known_args): Replace
vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
(evaluate_properties_for_edge): Likewise.
(estimate_edge_devirt_benefit): Likewise.
(estimate_edge_size_and_time): Likewise.
(estimate_calls_size_and_time): Likewise.
(ipa_call_context::ipa_call_context): Likewise.
(estimate_ipcp_clone_size_and_time): Likewise.
* ipa-fnsummary.h (ipa_call_context): Replace
vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
* ipa-inline-analysis.c (do_estimate_edge_time): Replace
vec<ipa_agg_jump_function_p> with vec<ipa_agg_value_set>.
(do_estimate_edge_size): Likewise.
(do_estimate_edge_hints): Likewise.
2019-11-14 Feng Xue <fxue@os.amperecomputing.com>
PR ipa/91682
* gcc.dg/ipa/ipcp-agg-10.c: Change dg-scan string.
* gcc.dg/ipa/ipcp-agg-11.c: New test.
From-SVN: r278193
Diffstat (limited to 'gcc/ipa-cp.c')
-rw-r--r-- | gcc/ipa-cp.c | 498 |
1 files changed, 362 insertions, 136 deletions
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 36cac5f..f0d354b 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -1287,23 +1287,23 @@ initialize_node_lattices (struct cgraph_node *node) } } -/* Return the result of a (possibly arithmetic) pass through jump function - JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter - to which the result is passed. Return NULL_TREE if that cannot be - determined or be considered an interprocedural invariant. */ +/* Return the result of a (possibly arithmetic) operation on the constant + value INPUT. OPERAND is 2nd operand for binary operation. RES_TYPE is + the type of the parameter to which the result is passed. Return + NULL_TREE if that cannot be determined or be considered an + interprocedural invariant. */ static tree -ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, - tree res_type) +ipa_get_jf_arith_result (enum tree_code opcode, tree input, tree operand, + tree res_type) { tree res; - if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) + if (opcode == NOP_EXPR) return input; if (!is_gimple_ip_invariant (input)) return NULL_TREE; - tree_code opcode = ipa_get_jf_pass_through_operation (jfunc); if (!res_type) { if (TREE_CODE_CLASS (opcode) == tcc_comparison) @@ -1317,8 +1317,7 @@ ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, if (TREE_CODE_CLASS (opcode) == tcc_unary) res = fold_unary (opcode, res_type, input); else - res = fold_binary (opcode, res_type, input, - ipa_get_jf_pass_through_operand (jfunc)); + res = fold_binary (opcode, res_type, input, operand); if (res && !is_gimple_ip_invariant (res)) return NULL_TREE; @@ -1326,6 +1325,21 @@ ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, return res; } +/* Return the result of a (possibly arithmetic) pass through jump function + JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter + to which the result is passed. Return NULL_TREE if that cannot be + determined or be considered an interprocedural invariant. */ + +static tree +ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, + tree res_type) +{ + return ipa_get_jf_arith_result (ipa_get_jf_pass_through_operation (jfunc), + input, + ipa_get_jf_pass_through_operand (jfunc), + res_type); +} + /* Return the result of an ancestor jump function JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be determined. */ @@ -1459,6 +1473,146 @@ ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx, return ctx; } +/* See if NODE is a clone with a known aggregate value at a given OFFSET of a + parameter with the given INDEX. */ + +static tree +get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset, + int index) +{ + struct ipa_agg_replacement_value *aggval; + + aggval = ipa_get_agg_replacements_for_node (node); + while (aggval) + { + if (aggval->offset == offset + && aggval->index == index) + return aggval->value; + aggval = aggval->next; + } + return NULL_TREE; +} + +/* Determine whether ITEM, jump function for an aggregate part, evaluates to a + single known constant value and if so, return it. Otherwise return NULL. + NODE and INFO describes the caller node or the one it is inlined to, and + its related info. */ + +static tree +ipa_agg_value_from_node (class ipa_node_params *info, + struct cgraph_node *node, + struct ipa_agg_jf_item *item) +{ + tree value = NULL_TREE; + int src_idx; + + if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN) + return NULL_TREE; + + if (item->jftype == IPA_JF_CONST) + return item->value.constant; + + gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH + || item->jftype == IPA_JF_LOAD_AGG); + + src_idx = item->value.pass_through.formal_id; + + if (info->ipcp_orig_node) + { + if (item->jftype == IPA_JF_PASS_THROUGH) + value = info->known_csts[src_idx]; + else + value = get_clone_agg_value (node, item->value.load_agg.offset, + src_idx); + } + else if (info->lattices) + { + class ipcp_param_lattices *src_plats + = ipa_get_parm_lattices (info, src_idx); + + if (item->jftype == IPA_JF_PASS_THROUGH) + { + struct ipcp_lattice<tree> *lat = &src_plats->itself; + + if (!lat->is_single_const ()) + return NULL_TREE; + + value = lat->values->value; + } + else if (src_plats->aggs + && !src_plats->aggs_bottom + && !src_plats->aggs_contain_variable + && src_plats->aggs_by_ref == item->value.load_agg.by_ref) + { + struct ipcp_agg_lattice *aglat; + + for (aglat = src_plats->aggs; aglat; aglat = aglat->next) + { + if (aglat->offset > item->value.load_agg.offset) + break; + + if (aglat->offset == item->value.load_agg.offset) + { + if (aglat->is_single_const ()) + value = aglat->values->value; + break; + } + } + } + } + + if (!value) + return NULL_TREE; + + if (item->jftype == IPA_JF_LOAD_AGG) + { + tree load_type = item->value.load_agg.type; + tree value_type = TREE_TYPE (value); + + /* Ensure value type is compatible with load type. */ + if (!useless_type_conversion_p (load_type, value_type)) + return NULL_TREE; + } + + return ipa_get_jf_arith_result (item->value.pass_through.operation, + value, + item->value.pass_through.operand, + item->type); +} + +/* Determine whether AGG_JFUNC evaluates to a set of known constant value for + an aggregate and if so, return it. Otherwise return an empty set. NODE + and INFO describes the caller node or the one it is inlined to, and its + related info. */ + +struct ipa_agg_value_set +ipa_agg_value_set_from_jfunc (class ipa_node_params *info, cgraph_node *node, + struct ipa_agg_jump_function *agg_jfunc) +{ + struct ipa_agg_value_set agg; + struct ipa_agg_jf_item *item; + int i; + + agg.items = vNULL; + agg.by_ref = agg_jfunc->by_ref; + + FOR_EACH_VEC_SAFE_ELT (agg_jfunc->items, i, item) + { + tree value = ipa_agg_value_from_node (info, node, item); + + if (value) + { + struct ipa_agg_value value_item; + + value_item.offset = item->offset; + value_item.value = value; + + agg.items.safe_push (value_item); + } + } + return agg; +} + /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not bottom, not containing a variable component and without any known value at the same time. */ @@ -1638,16 +1792,25 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs, return true; } -/* Propagate values through a pass-through jump function JFUNC associated with - edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX - is the index of the source parameter. PARM_TYPE is the type of the - parameter to which the result is passed. */ +/* Propagate values through an arithmetic transformation described by a jump + function associated with edge CS, taking values from SRC_LAT and putting + them into DEST_LAT. OPND1_TYPE is expected type for the values in SRC_LAT. + OPND2 is a constant value if transformation is a binary operation. + SRC_OFFSET specifies offset in an aggregate if SRC_LAT describes lattice of + a part of the aggregate. SRC_IDX is the index of the source parameter. + RES_TYPE is the value type of result being propagated into. Return true if + DEST_LAT changed. */ static bool -propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, - ipcp_lattice<tree> *src_lat, - ipcp_lattice<tree> *dest_lat, int src_idx, - tree parm_type) +propagate_vals_across_arith_jfunc (cgraph_edge *cs, + enum tree_code opcode, + tree opnd1_type, + tree opnd2, + ipcp_lattice<tree> *src_lat, + ipcp_lattice<tree> *dest_lat, + HOST_WIDE_INT src_offset, + int src_idx, + tree res_type) { ipcp_value<tree> *src_val; bool ret = false; @@ -1657,17 +1820,22 @@ propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, number of them and we would just make lattices bottom. If this condition is ever relaxed we have to detect self-feeding recursive calls in cgraph_edge_brings_value_p in a smarter way. */ - if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) - && ipa_edge_within_scc (cs)) + if (opcode != NOP_EXPR && ipa_edge_within_scc (cs)) ret = dest_lat->set_contains_variable (); else for (src_val = src_lat->values; src_val; src_val = src_val->next) { - tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value, - parm_type); + tree opnd1 = src_val->value; + tree cstval = NULL_TREE; + + /* Skip source values that is incompatible with specified type. */ + if (!opnd1_type + || useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1))) + cstval = ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type); if (cstval) - ret |= dest_lat->add_value (cstval, cs, src_val, src_idx); + ret |= dest_lat->add_value (cstval, cs, src_val, src_idx, + src_offset); else ret |= dest_lat->set_contains_variable (); } @@ -1675,6 +1843,24 @@ propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, return ret; } +/* Propagate values through a pass-through jump function JFUNC associated with + edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX + is the index of the source parameter. PARM_TYPE is the type of the + parameter to which the result is passed. */ + +static bool +propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, + ipcp_lattice<tree> *src_lat, + ipcp_lattice<tree> *dest_lat, int src_idx, + tree parm_type) +{ + return propagate_vals_across_arith_jfunc (cs, + ipa_get_jf_pass_through_operation (jfunc), + NULL_TREE, + ipa_get_jf_pass_through_operand (jfunc), + src_lat, dest_lat, -1, src_idx, parm_type); +} + /* Propagate values through an ancestor jump function JFUNC associated with edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX is the index of the source parameter. */ @@ -1835,7 +2021,6 @@ propagate_context_across_jump_function (cgraph_edge *cs, added_sth = true; } } - } prop_fail: @@ -2218,6 +2403,85 @@ agg_pass_through_permissible_p (class ipcp_param_lattices *src_plats, || ipa_get_jf_pass_through_agg_preserved (jfunc)); } +/* Propagate values through ITEM, jump function for a part of an aggregate, + into corresponding aggregate lattice AGLAT. CS is the call graph edge + associated with the jump function. Return true if AGLAT changed in any + way. */ + +static bool +propagate_aggregate_lattice (struct cgraph_edge *cs, + struct ipa_agg_jf_item *item, + struct ipcp_agg_lattice *aglat) +{ + class ipa_node_params *caller_info; + class ipcp_param_lattices *src_plats; + struct ipcp_lattice<tree> *src_lat; + HOST_WIDE_INT src_offset; + int src_idx; + tree load_type; + bool ret; + + if (item->jftype == IPA_JF_CONST) + { + tree value = item->value.constant; + + gcc_checking_assert (is_gimple_ip_invariant (value)); + return aglat->add_value (value, cs, NULL, 0); + } + + gcc_checking_assert (item->jftype == IPA_JF_PASS_THROUGH + || item->jftype == IPA_JF_LOAD_AGG); + + caller_info = IPA_NODE_REF (cs->caller); + src_idx = item->value.pass_through.formal_id; + src_plats = ipa_get_parm_lattices (caller_info, src_idx); + + if (item->jftype == IPA_JF_PASS_THROUGH) + { + load_type = NULL_TREE; + src_lat = &src_plats->itself; + src_offset = -1; + } + else + { + HOST_WIDE_INT load_offset = item->value.load_agg.offset; + struct ipcp_agg_lattice *src_aglat; + + for (src_aglat = src_plats->aggs; src_aglat; src_aglat = src_aglat->next) + if (src_aglat->offset >= load_offset) + break; + + load_type = item->value.load_agg.type; + if (!src_aglat + || src_aglat->offset > load_offset + || src_aglat->size != tree_to_shwi (TYPE_SIZE (load_type)) + || src_plats->aggs_by_ref != item->value.load_agg.by_ref) + return aglat->set_contains_variable (); + + src_lat = src_aglat; + src_offset = load_offset; + } + + if (src_lat->bottom + || (!ipcp_versionable_function_p (cs->caller) + && !src_lat->is_single_const ())) + return aglat->set_contains_variable (); + + ret = propagate_vals_across_arith_jfunc (cs, + item->value.pass_through.operation, + load_type, + item->value.pass_through.operand, + src_lat, aglat, + src_offset, + src_idx, + item->type); + + if (src_lat->contains_variable) + ret |= aglat->set_contains_variable (); + + return ret; +} + /* Propagate scalar values across jump function JFUNC that is associated with edge CS and put the values into DEST_LAT. */ @@ -2285,15 +2549,14 @@ propagate_aggs_across_jump_function (struct cgraph_edge *cs, { HOST_WIDE_INT val_size; - if (item->offset < 0) + if (item->offset < 0 || item->jftype == IPA_JF_UNKNOWN) continue; - gcc_checking_assert (is_gimple_ip_invariant (item->value)); - val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value))); + val_size = tree_to_shwi (TYPE_SIZE (item->type)); if (merge_agg_lats_step (dest_plats, item->offset, val_size, &aglat, pre_existing, &ret)) { - ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0); + ret |= propagate_aggregate_lattice (cs, item, *aglat); aglat = &(*aglat)->next; } else if (dest_plats->aggs_bottom) @@ -2410,7 +2673,7 @@ static tree ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, vec<tree> known_csts, vec<ipa_polymorphic_call_context> known_contexts, - vec<ipa_agg_jump_function_p> known_aggs, + vec<ipa_agg_value_set> known_aggs, struct ipa_agg_replacement_value *agg_reps, bool *speculative) { @@ -2448,9 +2711,9 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, } if (!t) { - struct ipa_agg_jump_function *agg; + struct ipa_agg_value_set *agg; if (known_aggs.length () > (unsigned int) param_index) - agg = known_aggs[param_index]; + agg = &known_aggs[param_index]; else agg = NULL; bool from_global_constant; @@ -2504,8 +2767,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, if (!t && known_aggs.length () > (unsigned int) param_index && !ie->indirect_info->by_ref) { - struct ipa_agg_jump_function *agg; - agg = known_aggs[param_index]; + struct ipa_agg_value_set *agg = &known_aggs[param_index]; t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], ie->indirect_info->offset, true); } @@ -2627,7 +2889,7 @@ tree ipa_get_indirect_edge_target (struct cgraph_edge *ie, vec<tree> known_csts, vec<ipa_polymorphic_call_context> known_contexts, - vec<ipa_agg_jump_function_p> known_aggs, + vec<ipa_agg_value_set> known_aggs, bool *speculative) { return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, @@ -2641,7 +2903,7 @@ static int devirtualization_time_bonus (struct cgraph_node *node, vec<tree> known_csts, vec<ipa_polymorphic_call_context> known_contexts, - vec<ipa_agg_jump_function_p> known_aggs) + vec<ipa_agg_value_set> known_aggs) { struct cgraph_edge *ie; int res = 0; @@ -2776,25 +3038,25 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, /* Return all context independent values from aggregate lattices in PLATS in a vector. Return NULL if there are none. */ -static vec<ipa_agg_jf_item, va_gc> * +static vec<ipa_agg_value> context_independent_aggregate_values (class ipcp_param_lattices *plats) { - vec<ipa_agg_jf_item, va_gc> *res = NULL; + vec<ipa_agg_value> res = vNULL; if (plats->aggs_bottom || plats->aggs_contain_variable || plats->aggs_count == 0) - return NULL; + return vNULL; for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next) if (aglat->is_single_const ()) { - struct ipa_agg_jf_item item; + struct ipa_agg_value item; item.offset = aglat->offset; item.value = aglat->values->value; - vec_safe_push (res, item); + res.safe_push (item); } return res; } @@ -2810,7 +3072,7 @@ gather_context_independent_values (class ipa_node_params *info, vec<tree> *known_csts, vec<ipa_polymorphic_call_context> *known_contexts, - vec<ipa_agg_jump_function> *known_aggs, + vec<ipa_agg_value_set> *known_aggs, int *removable_params_cost) { int i, count = ipa_get_param_count (info); @@ -2860,40 +3122,20 @@ gather_context_independent_values (class ipa_node_params *info, if (known_aggs) { - vec<ipa_agg_jf_item, va_gc> *agg_items; - struct ipa_agg_jump_function *ajf; + vec<ipa_agg_value> agg_items; + struct ipa_agg_value_set *agg; agg_items = context_independent_aggregate_values (plats); - ajf = &(*known_aggs)[i]; - ajf->items = agg_items; - ajf->by_ref = plats->aggs_by_ref; - ret |= agg_items != NULL; + agg = &(*known_aggs)[i]; + agg->items = agg_items; + agg->by_ref = plats->aggs_by_ref; + ret |= !agg_items.is_empty (); } } return ret; } -/* The current interface in ipa-inline-analysis requires a pointer vector. - Create it. - - FIXME: That interface should be re-worked, this is slightly silly. Still, - I'd like to discuss how to change it first and this demonstrates the - issue. */ - -static vec<ipa_agg_jump_function_p> -agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs) -{ - vec<ipa_agg_jump_function_p> ret; - struct ipa_agg_jump_function *ajf; - int i; - - ret.create (known_aggs.length ()); - FOR_EACH_VEC_ELT (known_aggs, i, ajf) - ret.quick_push (ajf); - return ret; -} - /* Perform time and size measurement of NODE with the context given in KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of @@ -2903,7 +3145,7 @@ agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs) static void perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts, vec<ipa_polymorphic_call_context> known_contexts, - vec<ipa_agg_jump_function_p> known_aggs_ptrs, + vec<ipa_agg_value_set> known_aggs, int removable_params_cost, int est_move_cost, ipcp_value_base *val) { @@ -2912,7 +3154,7 @@ perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts, ipa_hints hints; estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, - known_aggs_ptrs, &size, &time, + known_aggs, &size, &time, &base_time, &hints); base_time -= time; if (base_time > 65535) @@ -2926,7 +3168,7 @@ perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts, else time_benefit = base_time.to_int () + devirtualization_time_bonus (node, known_csts, known_contexts, - known_aggs_ptrs) + known_aggs) + hint_time_bonus (hints) + removable_params_cost + est_move_cost; @@ -2952,8 +3194,7 @@ estimate_local_effects (struct cgraph_node *node) int i, count = ipa_get_param_count (info); vec<tree> known_csts; vec<ipa_polymorphic_call_context> known_contexts; - vec<ipa_agg_jump_function> known_aggs; - vec<ipa_agg_jump_function_p> known_aggs_ptrs; + vec<ipa_agg_value_set> known_aggs; bool always_const; int removable_params_cost; @@ -2966,9 +3207,8 @@ estimate_local_effects (struct cgraph_node *node) always_const = gather_context_independent_values (info, &known_csts, &known_contexts, &known_aggs, &removable_params_cost); - known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs); int devirt_bonus = devirtualization_time_bonus (node, known_csts, - known_contexts, known_aggs_ptrs); + known_contexts, known_aggs); if (always_const || devirt_bonus || (removable_params_cost && node->can_change_signature)) { @@ -2981,7 +3221,7 @@ estimate_local_effects (struct cgraph_node *node) node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false); estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, - known_aggs_ptrs, &size, &time, + known_aggs, &size, &time, &base_time, &hints); time -= devirt_bonus; time -= hint_time_bonus (hints); @@ -3044,7 +3284,7 @@ estimate_local_effects (struct cgraph_node *node) int emc = estimate_move_cost (TREE_TYPE (val->value), true); perform_estimation_of_a_value (node, known_csts, known_contexts, - known_aggs_ptrs, + known_aggs, removable_params_cost, emc, val); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -3079,7 +3319,7 @@ estimate_local_effects (struct cgraph_node *node) { known_contexts[i] = val->value; perform_estimation_of_a_value (node, known_csts, known_contexts, - known_aggs_ptrs, + known_aggs, removable_params_cost, 0, val); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -3098,13 +3338,13 @@ estimate_local_effects (struct cgraph_node *node) for (i = 0; i < count; i++) { class ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); - struct ipa_agg_jump_function *ajf; + struct ipa_agg_value_set *agg; struct ipcp_agg_lattice *aglat; if (plats->aggs_bottom || !plats->aggs) continue; - ajf = &known_aggs[i]; + agg = &known_aggs[i]; for (aglat = plats->aggs; aglat; aglat = aglat->next) { ipcp_value<tree> *val; @@ -3116,14 +3356,14 @@ estimate_local_effects (struct cgraph_node *node) for (val = aglat->values; val; val = val->next) { - struct ipa_agg_jf_item item; + struct ipa_agg_value item; item.offset = aglat->offset; item.value = val->value; - vec_safe_push (ajf->items, item); + agg->items.safe_push (item); perform_estimation_of_a_value (node, known_csts, known_contexts, - known_aggs_ptrs, + known_aggs, removable_params_cost, 0, val); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -3139,18 +3379,14 @@ estimate_local_effects (struct cgraph_node *node) val->local_time_benefit, val->local_size_cost); } - ajf->items->pop (); + agg->items.pop (); } } } - for (i = 0; i < count; i++) - vec_free (known_aggs[i].items); - known_csts.release (); known_contexts.release (); - known_aggs.release (); - known_aggs_ptrs.release (); + ipa_release_agg_values (known_aggs); } @@ -3532,26 +3768,6 @@ edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge, src_data->next_clone = dst_edge; } -/* See if NODE is a clone with a known aggregate value at a given OFFSET of a - parameter with the given INDEX. */ - -static tree -get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset, - int index) -{ - struct ipa_agg_replacement_value *aggval; - - aggval = ipa_get_agg_replacements_for_node (node); - while (aggval) - { - if (aggval->offset == offset - && aggval->index == index) - return aggval->value; - aggval = aggval->next; - } - return NULL_TREE; -} - /* Return true is NODE is DEST or its clone for all contexts. */ static bool @@ -4237,10 +4453,10 @@ find_more_contexts_for_caller_subset (cgraph_node *node, /* Go through PLATS and create a vector of values consisting of values and offsets (minus OFFSET) of lattices that contain only a single value. */ -static vec<ipa_agg_jf_item> +static vec<ipa_agg_value> copy_plats_to_inter (class ipcp_param_lattices *plats, HOST_WIDE_INT offset) { - vec<ipa_agg_jf_item> res = vNULL; + vec<ipa_agg_value> res = vNULL; if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) return vNULL; @@ -4248,7 +4464,7 @@ copy_plats_to_inter (class ipcp_param_lattices *plats, HOST_WIDE_INT offset) for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next) if (aglat->is_single_const ()) { - struct ipa_agg_jf_item ti; + struct ipa_agg_value ti; ti.offset = aglat->offset - offset; ti.value = aglat->values->value; res.safe_push (ti); @@ -4261,11 +4477,11 @@ copy_plats_to_inter (class ipcp_param_lattices *plats, HOST_WIDE_INT offset) static void intersect_with_plats (class ipcp_param_lattices *plats, - vec<ipa_agg_jf_item> *inter, + vec<ipa_agg_value> *inter, HOST_WIDE_INT offset) { struct ipcp_agg_lattice *aglat; - struct ipa_agg_jf_item *item; + struct ipa_agg_value *item; int k; if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) @@ -4303,18 +4519,18 @@ intersect_with_plats (class ipcp_param_lattices *plats, /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the vector result while subtracting OFFSET from the individual value offsets. */ -static vec<ipa_agg_jf_item> +static vec<ipa_agg_value> agg_replacements_to_vector (struct cgraph_node *node, int index, HOST_WIDE_INT offset) { struct ipa_agg_replacement_value *av; - vec<ipa_agg_jf_item> res = vNULL; + vec<ipa_agg_value> res = vNULL; for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next) if (av->index == index && (av->offset - offset) >= 0) { - struct ipa_agg_jf_item item; + struct ipa_agg_value item; gcc_checking_assert (av->value); item.offset = av->offset - offset; item.value = av->value; @@ -4330,11 +4546,11 @@ agg_replacements_to_vector (struct cgraph_node *node, int index, static void intersect_with_agg_replacements (struct cgraph_node *node, int index, - vec<ipa_agg_jf_item> *inter, + vec<ipa_agg_value> *inter, HOST_WIDE_INT offset) { struct ipa_agg_replacement_value *srcvals; - struct ipa_agg_jf_item *item; + struct ipa_agg_value *item; int i; srcvals = ipa_get_agg_replacements_for_node (node); @@ -4371,9 +4587,9 @@ intersect_with_agg_replacements (struct cgraph_node *node, int index, copy all incoming values to it. If we determine we ended up with no values whatsoever, return a released vector. */ -static vec<ipa_agg_jf_item> +static vec<ipa_agg_value> intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, - vec<ipa_agg_jf_item> inter) + vec<ipa_agg_value> inter) { struct ipa_jump_func *jfunc; jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index); @@ -4454,12 +4670,26 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, } else if (jfunc->agg.items) { - struct ipa_agg_jf_item *item; + class ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); + struct ipa_agg_value *item; int k; if (!inter.exists ()) for (unsigned i = 0; i < jfunc->agg.items->length (); i++) - inter.safe_push ((*jfunc->agg.items)[i]); + { + struct ipa_agg_jf_item *agg_item = &(*jfunc->agg.items)[i]; + tree value = ipa_agg_value_from_node (caller_info, cs->caller, + agg_item); + if (value) + { + struct ipa_agg_value agg_value; + + agg_value.offset = agg_item->offset; + agg_value.value = value; + + inter.safe_push (agg_value); + } + } else FOR_EACH_VEC_ELT (inter, k, item) { @@ -4477,9 +4707,10 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, break; if (ti->offset == item->offset) { - gcc_checking_assert (ti->value); - if (values_equal_for_ipcp_p (item->value, - ti->value)) + tree value = ipa_agg_value_from_node (caller_info, + cs->caller, ti); + if (value + && values_equal_for_ipcp_p (item->value, value)) found = true; break; } @@ -4492,7 +4723,7 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, else { inter.release (); - return vec<ipa_agg_jf_item>(); + return vNULL; } return inter; } @@ -4525,8 +4756,8 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node, for (i = 0; i < count; i++) { struct cgraph_edge *cs; - vec<ipa_agg_jf_item> inter = vNULL; - struct ipa_agg_jf_item *item; + vec<ipa_agg_value> inter = vNULL; + struct ipa_agg_value *item; class ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i); int j; @@ -4633,7 +4864,7 @@ cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, for (i = 0; i < count; i++) { - static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>(); + static vec<ipa_agg_value> values = vNULL; class ipcp_param_lattices *plats; bool interesting = false; for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) @@ -4656,7 +4887,7 @@ cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) if (aggval->index == i) { - struct ipa_agg_jf_item *item; + struct ipa_agg_value *item; int j; bool found = false; FOR_EACH_VEC_ELT (values, j, item) @@ -4894,7 +5125,6 @@ decide_whether_version_node (struct cgraph_node *node) int i, count = ipa_get_param_count (info); vec<tree> known_csts; vec<ipa_polymorphic_call_context> known_contexts; - vec<ipa_agg_jump_function> known_aggs = vNULL; bool ret = false; if (count == 0) @@ -4905,8 +5135,7 @@ decide_whether_version_node (struct cgraph_node *node) node->dump_name ()); gather_context_independent_values (info, &known_csts, &known_contexts, - info->do_clone_for_all_contexts ? &known_aggs - : NULL, NULL); + NULL, NULL); for (i = 0; i < count;i++) { @@ -4975,9 +5204,6 @@ decide_whether_version_node (struct cgraph_node *node) info = IPA_NODE_REF (node); info->do_clone_for_all_contexts = false; IPA_NODE_REF (clone)->is_all_contexts_clone = true; - for (i = 0; i < count; i++) - vec_free (known_aggs[i].items); - known_aggs.release (); ret = true; } else |