aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-cp.c
diff options
context:
space:
mode:
authorFeng Xue <fxue@os.amperecomputing.com>2019-11-14 03:19:15 +0000
committerFeng Xue <fxue@gcc.gnu.org>2019-11-14 03:19:15 +0000
commiteb270950acbae6f70e3487a6e63a26c1294656b3 (patch)
treed64f761c523baf3052aaaff96fd28ca6a47d6aaf /gcc/ipa-cp.c
parent3e7cf2e6c0ee30b83aa158b7bd2b2eb9a686c1c3 (diff)
downloadgcc-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.c498
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