}
}
+/* If a parameter with original INDEX has survived intact, return its new
+ index. Otherwise return -1. In that case, if it has been split and there
+ is a new parameter representing a portion at unit OFFSET for which a value
+ of a TYPE can be substituted, store its new index into SPLIT_INDEX,
+ otherwise store -1 there. */
+int
+ipa_param_adjustments::get_updated_index_or_split (int index,
+ unsigned unit_offset,
+ tree type, int *split_index)
+{
+ unsigned adj_len = vec_safe_length (m_adj_params);
+ for (unsigned i = 0; i < adj_len ; i++)
+ {
+ ipa_adjusted_param *apm = &(*m_adj_params)[i];
+ if (apm->base_index != index)
+ continue;
+ if (apm->op == IPA_PARAM_OP_COPY)
+ return i;
+ if (apm->op == IPA_PARAM_OP_SPLIT
+ && apm->unit_offset == unit_offset)
+ {
+ if (useless_type_conversion_p (apm->type, type))
+ *split_index = i;
+ else
+ *split_index = -1;
+ return -1;
+ }
+ }
+
+ *split_index = -1;
+ return -1;
+}
+
/* Return the original index for the given new parameter index. Return a
negative number if not available. */
void get_surviving_params (vec<bool> *surviving_params);
/* Fill a vector with new indices of surviving original parameters. */
void get_updated_indices (vec<int> *new_indices);
+ /* If a parameter with original INDEX has survived intact, return its new
+ index. Otherwise return -1. In that case, if it has been split and there
+ is a new parameter representing a portion at UNIT_OFFSET for which a value
+ of a TYPE can be substituted, store its new index into SPLIT_INDEX,
+ otherwise store -1 there. */
+ int get_updated_index_or_split (int index, unsigned unit_offset, tree type,
+ int *split_index);
/* Return the original index for the given new parameter index. Return a
negative number if not available. */
int get_original_index (int newidx);
}
/* Adjust the aggregate replacements in AGGVAL to reflect parameters skipped in
- NODE. */
+ NODE but also if any parameter was IPA-SRAed into a scalar go ahead with
+ substitution of the default_definitions of that new param with the
+ appropriate constant.
-static void
-adjust_agg_replacement_values (struct cgraph_node *node,
- struct ipa_agg_replacement_value *aggval)
+ Return two bools. the first it true if at least one item in AGGVAL still
+ exists and function body walk should go ahead. The second is true if any
+ values were already substituted for scalarized parameters and update_cfg
+ shuld be run after replace_uses_by. */
+
+static std::pair<bool, bool>
+adjust_agg_replacement_values (cgraph_node *node,
+ ipa_agg_replacement_value *aggval,
+ const vec<ipa_param_descriptor, va_gc>
+ &descriptors)
{
struct ipa_agg_replacement_value *v;
clone_info *cinfo = clone_info::get (node);
-
if (!cinfo || !cinfo->param_adjustments)
- return;
+ return std::pair<bool, bool> (true, false);
- auto_vec<int, 16> new_indices;
- cinfo->param_adjustments->get_updated_indices (&new_indices);
+ bool anything_left = false;
+ bool done_replacement = false;
for (v = aggval; v; v = v->next)
{
gcc_checking_assert (v->index >= 0);
- if ((unsigned) v->index < new_indices.length ())
- v->index = new_indices[v->index];
- else
- /* This can happen if we know about a constant passed by reference by
- an argument which is never actually used for anything, let alone
- loading that constant. */
- v->index = -1;
+ unsigned unit_offset = v->offset / BITS_PER_UNIT;
+ tree cst_type = TREE_TYPE (v->value);
+ int split_idx;
+ int new_idx
+ = cinfo->param_adjustments->get_updated_index_or_split (v->index,
+ unit_offset,
+ cst_type,
+ &split_idx);
+ v->index = new_idx;
+ if (new_idx >= 0)
+ anything_left = true;
+ else if (split_idx >= 0)
+ {
+ tree parm = ipa_get_param (descriptors, split_idx);
+ tree ddef = ssa_default_def (cfun, parm);
+ if (ddef)
+ {
+ replace_uses_by (ddef, v->value);
+ done_replacement = true;
+ }
+ }
}
+ return std::pair<bool, bool> (anything_left, done_replacement);
}
/* Dominator walker driving the ipcp modification phase. */
param_count = count_formal_params (node->decl);
if (param_count == 0)
return 0;
- adjust_agg_replacement_values (node, aggval);
+ vec_safe_grow_cleared (descriptors, param_count, true);
+ ipa_populate_param_decls (node, *descriptors);
+ std::pair<bool, bool> rr
+ = adjust_agg_replacement_values (node, aggval, *descriptors);
+ int retval = rr.second ? TODO_cleanup_cfg : 0;
+ if (!rr.first)
+ {
+ vec_free (descriptors);
+ if (dump_file)
+ fprintf (dump_file, " All affected aggregate parameters were either "
+ "removed or converted into scalars, phase done.\n");
+ return retval;
+ }
if (dump_file)
ipa_dump_agg_replacement_values (dump_file, aggval);
fbi.param_count = param_count;
fbi.aa_walk_budget = opt_for_fn (node->decl, param_ipa_max_aa_steps);
- vec_safe_grow_cleared (descriptors, param_count, true);
- ipa_populate_param_decls (node, *descriptors);
calculate_dominance_info (CDI_DOMINATORS);
ipcp_modif_dom_walker walker (&fbi, descriptors, aggval, &something_changed);
walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
vec_free (descriptors);
if (!something_changed)
- return 0;
+ return retval;
if (cfg_changed)
delete_unreachable_blocks_update_callgraph (node, false);
- return TODO_update_ssa_only_virtuals;
+ return retval | TODO_update_ssa_only_virtuals;
}
return vec_safe_length (info->descriptors);
}
+/* Return the parameter declaration in DESCRIPTORS at index I and assert it is
+ indeed a PARM_DECL. */
+
+static inline tree
+ipa_get_param (const vec<ipa_param_descriptor, va_gc> &descriptors, int i)
+{
+ tree t = descriptors[i].decl_or_type;
+ gcc_checking_assert (TREE_CODE (t) == PARM_DECL);
+ return t;
+}
+
/* Return the declaration of Ith formal parameter of the function corresponding
to INFO. Note there is no setter function as this array is built just once
using ipa_initialize_node_params. This function should not be called in
ipa_get_param (class ipa_node_params *info, int i)
{
gcc_checking_assert (info->descriptors);
- tree t = (*info->descriptors)[i].decl_or_type;
- gcc_checking_assert (TREE_CODE (t) == PARM_DECL);
- return t;
+ return ipa_get_param (*info->descriptors, i);
}
/* Return the type of Ith formal parameter of the function corresponding