Commit 31519c38 by Aldy Hernandez Committed by Jakub Jelinek

ipa.c (symtab_remove_unreachable_nodes): Fix up comment typos.

	* ipa.c (symtab_remove_unreachable_nodes): Fix up comment typos.
	* ipa-prop.c (get_vector_of_formal_parm_types): Renamed to ...
	(ipa_get_vector_of_formal_parm_types): ... this.  No longer static.
	(ipa_modify_formal_parameters): Adjust caller.  Remove
	synth_parm_prefix argument.  Use operator enum instead of bit fields.
	Add assert for properly handling vector of references.  Handle
	creating brand new parameters.
	(ipa_modify_call_arguments): Use operator enum instead of bit
	fields.
	(ipa_combine_adjustments): Same.  Assert that IPA_PARM_OP_NEW is not
	used.
	(ipa_modify_expr, get_ssa_base_param, ipa_get_adjustment_candidate):
	New functions.
	(ipa_dump_param_adjustments): Rename reduction to new_decl.
	Use operator enum instead of bit fields.
	* ipa-prop.h (enum ipa_parm_op): New.
	(struct ipa_parm_adjustment): New field op.  Rename reduction
	to new_decl, new_arg_prefix to arg_prefix and remove remove_param
	and copy_param.
	(ipa_modify_formal_parameters): Remove last argument.
	(ipa_get_vector_of_formal_parm_types, ipa_modify_expr,
	ipa_get_adjustment_candidate): New prototypes.
	* tree-sra.c (turn_representatives_into_adjustments): Use operator
	enum.  Set arg_prefix.
	(get_adjustment_for_base): Use operator enum.
	(sra_ipa_modify_expr): Rename to ipa_modify_expr and move to
	ipa-prop.c.
	(sra_ipa_modify_assign): Rename sra_ipa_modify_expr to
	ipa_modify_expr.
	(ipa_sra_modify_function_body): Same.  No longer static.
	(sra_ipa_reset_debug_stmts): Use operator enum.
	(modify_function): Do not pass prefix argument.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>

From-SVN: r205284
parent 0a508bb6
2013-11-22 Aldy Hernandez <aldyh@redhat.com>
Jakub Jelinek <jakub@redhat.com>
* ipa.c (symtab_remove_unreachable_nodes): Fix up comment typos.
* ipa-prop.c (get_vector_of_formal_parm_types): Renamed to ...
(ipa_get_vector_of_formal_parm_types): ... this. No longer static.
(ipa_modify_formal_parameters): Adjust caller. Remove
synth_parm_prefix argument. Use operator enum instead of bit fields.
Add assert for properly handling vector of references. Handle
creating brand new parameters.
(ipa_modify_call_arguments): Use operator enum instead of bit
fields.
(ipa_combine_adjustments): Same. Assert that IPA_PARM_OP_NEW is not
used.
(ipa_modify_expr, get_ssa_base_param, ipa_get_adjustment_candidate):
New functions.
(ipa_dump_param_adjustments): Rename reduction to new_decl.
Use operator enum instead of bit fields.
* ipa-prop.h (enum ipa_parm_op): New.
(struct ipa_parm_adjustment): New field op. Rename reduction
to new_decl, new_arg_prefix to arg_prefix and remove remove_param
and copy_param.
(ipa_modify_formal_parameters): Remove last argument.
(ipa_get_vector_of_formal_parm_types, ipa_modify_expr,
ipa_get_adjustment_candidate): New prototypes.
* tree-sra.c (turn_representatives_into_adjustments): Use operator
enum. Set arg_prefix.
(get_adjustment_for_base): Use operator enum.
(sra_ipa_modify_expr): Rename to ipa_modify_expr and move to
ipa-prop.c.
(sra_ipa_modify_assign): Rename sra_ipa_modify_expr to
ipa_modify_expr.
(ipa_sra_modify_function_body): Same. No longer static.
(sra_ipa_reset_debug_stmts): Use operator enum.
(modify_function): Do not pass prefix argument.
2013-11-22 Jakub Jelinek <jakub@redhat.com> 2013-11-22 Jakub Jelinek <jakub@redhat.com>
* ubsan.c (ubsan_source_location): Don't crash on * ubsan.c (ubsan_source_location): Don't crash on
...@@ -3361,8 +3361,8 @@ ipa_get_vector_of_formal_parms (tree fndecl) ...@@ -3361,8 +3361,8 @@ ipa_get_vector_of_formal_parms (tree fndecl)
/* Return a heap allocated vector containing types of formal parameters of /* Return a heap allocated vector containing types of formal parameters of
function type FNTYPE. */ function type FNTYPE. */
static inline vec<tree> vec<tree>
get_vector_of_formal_parm_types (tree fntype) ipa_get_vector_of_formal_parm_types (tree fntype)
{ {
vec<tree> types; vec<tree> types;
int count = 0; int count = 0;
...@@ -3384,32 +3384,22 @@ get_vector_of_formal_parm_types (tree fntype) ...@@ -3384,32 +3384,22 @@ get_vector_of_formal_parm_types (tree fntype)
base_index field. */ base_index field. */
void void
ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments)
const char *synth_parm_prefix)
{ {
vec<tree> oparms, otypes; vec<tree> oparms = ipa_get_vector_of_formal_parms (fndecl);
tree orig_type, new_type = NULL; tree orig_type = TREE_TYPE (fndecl);
tree old_arg_types, t, new_arg_types = NULL; tree old_arg_types = TYPE_ARG_TYPES (orig_type);
tree parm, *link = &DECL_ARGUMENTS (fndecl);
int i, len = adjustments.length ();
tree new_reversed = NULL;
bool care_for_types, last_parm_void;
if (!synth_parm_prefix)
synth_parm_prefix = "SYNTH";
oparms = ipa_get_vector_of_formal_parms (fndecl);
orig_type = TREE_TYPE (fndecl);
old_arg_types = TYPE_ARG_TYPES (orig_type);
/* The following test is an ugly hack, some functions simply don't have any /* The following test is an ugly hack, some functions simply don't have any
arguments in their type. This is probably a bug but well... */ arguments in their type. This is probably a bug but well... */
care_for_types = (old_arg_types != NULL_TREE); bool care_for_types = (old_arg_types != NULL_TREE);
bool last_parm_void;
vec<tree> otypes;
if (care_for_types) if (care_for_types)
{ {
last_parm_void = (TREE_VALUE (tree_last (old_arg_types)) last_parm_void = (TREE_VALUE (tree_last (old_arg_types))
== void_type_node); == void_type_node);
otypes = get_vector_of_formal_parm_types (orig_type); otypes = ipa_get_vector_of_formal_parm_types (orig_type);
if (last_parm_void) if (last_parm_void)
gcc_assert (oparms.length () + 1 == otypes.length ()); gcc_assert (oparms.length () + 1 == otypes.length ());
else else
...@@ -3421,16 +3411,23 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, ...@@ -3421,16 +3411,23 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments,
otypes.create (0); otypes.create (0);
} }
for (i = 0; i < len; i++) int len = adjustments.length ();
tree *link = &DECL_ARGUMENTS (fndecl);
tree new_arg_types = NULL;
for (int i = 0; i < len; i++)
{ {
struct ipa_parm_adjustment *adj; struct ipa_parm_adjustment *adj;
gcc_assert (link); gcc_assert (link);
adj = &adjustments[i]; adj = &adjustments[i];
parm = oparms[adj->base_index]; tree parm;
if (adj->op == IPA_PARM_OP_NEW)
parm = NULL;
else
parm = oparms[adj->base_index];
adj->base = parm; adj->base = parm;
if (adj->copy_param) if (adj->op == IPA_PARM_OP_COPY)
{ {
if (care_for_types) if (care_for_types)
new_arg_types = tree_cons (NULL_TREE, otypes[adj->base_index], new_arg_types = tree_cons (NULL_TREE, otypes[adj->base_index],
...@@ -3438,7 +3435,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, ...@@ -3438,7 +3435,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments,
*link = parm; *link = parm;
link = &DECL_CHAIN (parm); link = &DECL_CHAIN (parm);
} }
else if (!adj->remove_param) else if (adj->op != IPA_PARM_OP_REMOVE)
{ {
tree new_parm; tree new_parm;
tree ptype; tree ptype;
...@@ -3453,8 +3450,8 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, ...@@ -3453,8 +3450,8 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments,
new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE,
ptype); ptype);
DECL_NAME (new_parm) = create_tmp_var_name (synth_parm_prefix); const char *prefix = adj->arg_prefix ? adj->arg_prefix : "SYNTH";
DECL_NAME (new_parm) = create_tmp_var_name (prefix);
DECL_ARTIFICIAL (new_parm) = 1; DECL_ARTIFICIAL (new_parm) = 1;
DECL_ARG_TYPE (new_parm) = ptype; DECL_ARG_TYPE (new_parm) = ptype;
DECL_CONTEXT (new_parm) = fndecl; DECL_CONTEXT (new_parm) = fndecl;
...@@ -3462,17 +3459,20 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, ...@@ -3462,17 +3459,20 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments,
DECL_IGNORED_P (new_parm) = 1; DECL_IGNORED_P (new_parm) = 1;
layout_decl (new_parm, 0); layout_decl (new_parm, 0);
adj->base = parm; if (adj->op == IPA_PARM_OP_NEW)
adj->reduction = new_parm; adj->base = NULL;
else
adj->base = parm;
adj->new_decl = new_parm;
*link = new_parm; *link = new_parm;
link = &DECL_CHAIN (new_parm); link = &DECL_CHAIN (new_parm);
} }
} }
*link = NULL_TREE; *link = NULL_TREE;
tree new_reversed = NULL;
if (care_for_types) if (care_for_types)
{ {
new_reversed = nreverse (new_arg_types); new_reversed = nreverse (new_arg_types);
...@@ -3490,8 +3490,9 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, ...@@ -3490,8 +3490,9 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments,
Exception is METHOD_TYPEs must have THIS argument. Exception is METHOD_TYPEs must have THIS argument.
When we are asked to remove it, we need to build new FUNCTION_TYPE When we are asked to remove it, we need to build new FUNCTION_TYPE
instead. */ instead. */
tree new_type = NULL;
if (TREE_CODE (orig_type) != METHOD_TYPE if (TREE_CODE (orig_type) != METHOD_TYPE
|| (adjustments[0].copy_param || (adjustments[0].op == IPA_PARM_OP_COPY
&& adjustments[0].base_index == 0)) && adjustments[0].base_index == 0))
{ {
new_type = build_distinct_type_copy (orig_type); new_type = build_distinct_type_copy (orig_type);
...@@ -3515,7 +3516,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, ...@@ -3515,7 +3516,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments,
/* This is a new type, not a copy of an old type. Need to reassociate /* This is a new type, not a copy of an old type. Need to reassociate
variants. We can handle everything except the main variant lazily. */ variants. We can handle everything except the main variant lazily. */
t = TYPE_MAIN_VARIANT (orig_type); tree t = TYPE_MAIN_VARIANT (orig_type);
if (orig_type != t) if (orig_type != t)
{ {
TYPE_MAIN_VARIANT (new_type) = t; TYPE_MAIN_VARIANT (new_type) = t;
...@@ -3564,13 +3565,13 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, ...@@ -3564,13 +3565,13 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
adj = &adjustments[i]; adj = &adjustments[i];
if (adj->copy_param) if (adj->op == IPA_PARM_OP_COPY)
{ {
tree arg = gimple_call_arg (stmt, adj->base_index); tree arg = gimple_call_arg (stmt, adj->base_index);
vargs.quick_push (arg); vargs.quick_push (arg);
} }
else if (!adj->remove_param) else if (adj->op != IPA_PARM_OP_REMOVE)
{ {
tree expr, base, off; tree expr, base, off;
location_t loc; location_t loc;
...@@ -3689,7 +3690,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, ...@@ -3689,7 +3690,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
NULL, true, GSI_SAME_STMT); NULL, true, GSI_SAME_STMT);
vargs.quick_push (expr); vargs.quick_push (expr);
} }
if (!adj->copy_param && MAY_HAVE_DEBUG_STMTS) if (adj->op != IPA_PARM_OP_COPY && MAY_HAVE_DEBUG_STMTS)
{ {
unsigned int ix; unsigned int ix;
tree ddecl = NULL_TREE, origin = DECL_ORIGIN (adj->base), arg; tree ddecl = NULL_TREE, origin = DECL_ORIGIN (adj->base), arg;
...@@ -3764,6 +3765,124 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, ...@@ -3764,6 +3765,124 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_DOMINATORS);
} }
/* If the expression *EXPR should be replaced by a reduction of a parameter, do
so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
specifies whether the function should care about type incompatibility the
current and new expressions. If it is false, the function will leave
incompatibility issues to the caller. Return true iff the expression
was modified. */
bool
ipa_modify_expr (tree *expr, bool convert,
ipa_parm_adjustment_vec adjustments)
{
struct ipa_parm_adjustment *cand
= ipa_get_adjustment_candidate (&expr, &convert, adjustments, false);
if (!cand)
return false;
tree src;
if (cand->by_ref)
src = build_simple_mem_ref (cand->new_decl);
else
src = cand->new_decl;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "About to replace expr ");
print_generic_expr (dump_file, *expr, 0);
fprintf (dump_file, " with ");
print_generic_expr (dump_file, src, 0);
fprintf (dump_file, "\n");
}
if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
{
tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
*expr = vce;
}
else
*expr = src;
return true;
}
/* If T is an SSA_NAME, return NULL if it is not a default def or
return its base variable if it is. If IGNORE_DEFAULT_DEF is true,
the base variable is always returned, regardless if it is a default
def. Return T if it is not an SSA_NAME. */
static tree
get_ssa_base_param (tree t, bool ignore_default_def)
{
if (TREE_CODE (t) == SSA_NAME)
{
if (ignore_default_def || SSA_NAME_IS_DEFAULT_DEF (t))
return SSA_NAME_VAR (t);
else
return NULL_TREE;
}
return t;
}
/* Given an expression, return an adjustment entry specifying the
transformation to be done on EXPR. If no suitable adjustment entry
was found, returns NULL.
If IGNORE_DEFAULT_DEF is set, consider SSA_NAMEs which are not a
default def, otherwise bail on them.
If CONVERT is non-NULL, this function will set *CONVERT if the
expression provided is a component reference. ADJUSTMENTS is the
adjustments vector. */
ipa_parm_adjustment *
ipa_get_adjustment_candidate (tree **expr, bool *convert,
ipa_parm_adjustment_vec adjustments,
bool ignore_default_def)
{
if (TREE_CODE (**expr) == BIT_FIELD_REF
|| TREE_CODE (**expr) == IMAGPART_EXPR
|| TREE_CODE (**expr) == REALPART_EXPR)
{
*expr = &TREE_OPERAND (**expr, 0);
if (convert)
*convert = true;
}
HOST_WIDE_INT offset, size, max_size;
tree base = get_ref_base_and_extent (**expr, &offset, &size, &max_size);
if (!base || size == -1 || max_size == -1)
return NULL;
if (TREE_CODE (base) == MEM_REF)
{
offset += mem_ref_offset (base).low * BITS_PER_UNIT;
base = TREE_OPERAND (base, 0);
}
base = get_ssa_base_param (base, ignore_default_def);
if (!base || TREE_CODE (base) != PARM_DECL)
return NULL;
struct ipa_parm_adjustment *cand = NULL;
unsigned int len = adjustments.length ();
for (unsigned i = 0; i < len; i++)
{
struct ipa_parm_adjustment *adj = &adjustments[i];
if (adj->base == base
&& (adj->offset == offset || adj->op == IPA_PARM_OP_REMOVE))
{
cand = adj;
break;
}
}
if (!cand || cand->op == IPA_PARM_OP_COPY || cand->op == IPA_PARM_OP_REMOVE)
return NULL;
return cand;
}
/* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */ /* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */
static bool static bool
...@@ -3809,10 +3928,14 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner, ...@@ -3809,10 +3928,14 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner,
struct ipa_parm_adjustment *n; struct ipa_parm_adjustment *n;
n = &inner[i]; n = &inner[i];
if (n->remove_param) if (n->op == IPA_PARM_OP_REMOVE)
removals++; removals++;
else else
tmp.quick_push (*n); {
/* FIXME: Handling of new arguments are not implemented yet. */
gcc_assert (n->op != IPA_PARM_OP_NEW);
tmp.quick_push (*n);
}
} }
adjustments.create (outlen + removals); adjustments.create (outlen + removals);
...@@ -3823,27 +3946,32 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner, ...@@ -3823,27 +3946,32 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner,
struct ipa_parm_adjustment *in = &tmp[out->base_index]; struct ipa_parm_adjustment *in = &tmp[out->base_index];
memset (&r, 0, sizeof (r)); memset (&r, 0, sizeof (r));
gcc_assert (!in->remove_param); gcc_assert (in->op != IPA_PARM_OP_REMOVE);
if (out->remove_param) if (out->op == IPA_PARM_OP_REMOVE)
{ {
if (!index_in_adjustments_multiple_times_p (in->base_index, tmp)) if (!index_in_adjustments_multiple_times_p (in->base_index, tmp))
{ {
r.remove_param = true; r.op = IPA_PARM_OP_REMOVE;
adjustments.quick_push (r); adjustments.quick_push (r);
} }
continue; continue;
} }
else
{
/* FIXME: Handling of new arguments are not implemented yet. */
gcc_assert (out->op != IPA_PARM_OP_NEW);
}
r.base_index = in->base_index; r.base_index = in->base_index;
r.type = out->type; r.type = out->type;
/* FIXME: Create nonlocal value too. */ /* FIXME: Create nonlocal value too. */
if (in->copy_param && out->copy_param) if (in->op == IPA_PARM_OP_COPY && out->op == IPA_PARM_OP_COPY)
r.copy_param = true; r.op = IPA_PARM_OP_COPY;
else if (in->copy_param) else if (in->op == IPA_PARM_OP_COPY)
r.offset = out->offset; r.offset = out->offset;
else if (out->copy_param) else if (out->op == IPA_PARM_OP_COPY)
r.offset = in->offset; r.offset = in->offset;
else else
r.offset = in->offset + out->offset; r.offset = in->offset + out->offset;
...@@ -3854,7 +3982,7 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner, ...@@ -3854,7 +3982,7 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner,
{ {
struct ipa_parm_adjustment *n = &inner[i]; struct ipa_parm_adjustment *n = &inner[i];
if (n->remove_param) if (n->op == IPA_PARM_OP_REMOVE)
adjustments.quick_push (*n); adjustments.quick_push (*n);
} }
...@@ -3891,10 +4019,10 @@ ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments, ...@@ -3891,10 +4019,10 @@ ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments,
fprintf (file, ", base: "); fprintf (file, ", base: ");
print_generic_expr (file, adj->base, 0); print_generic_expr (file, adj->base, 0);
} }
if (adj->reduction) if (adj->new_decl)
{ {
fprintf (file, ", reduction: "); fprintf (file, ", new_decl: ");
print_generic_expr (file, adj->reduction, 0); print_generic_expr (file, adj->new_decl, 0);
} }
if (adj->new_ssa_base) if (adj->new_ssa_base)
{ {
...@@ -3902,9 +4030,9 @@ ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments, ...@@ -3902,9 +4030,9 @@ ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments,
print_generic_expr (file, adj->new_ssa_base, 0); print_generic_expr (file, adj->new_ssa_base, 0);
} }
if (adj->copy_param) if (adj->op == IPA_PARM_OP_COPY)
fprintf (file, ", copy_param"); fprintf (file, ", copy_param");
else if (adj->remove_param) else if (adj->op == IPA_PARM_OP_REMOVE)
fprintf (file, ", remove_param"); fprintf (file, ", remove_param");
else else
fprintf (file, ", offset %li", (long) adj->offset); fprintf (file, ", offset %li", (long) adj->offset);
......
...@@ -609,6 +609,27 @@ extern alloc_pool ipcp_values_pool; ...@@ -609,6 +609,27 @@ extern alloc_pool ipcp_values_pool;
extern alloc_pool ipcp_sources_pool; extern alloc_pool ipcp_sources_pool;
extern alloc_pool ipcp_agg_lattice_pool; extern alloc_pool ipcp_agg_lattice_pool;
/* Operation to be performed for the parameter in ipa_parm_adjustment
below. */
enum ipa_parm_op {
IPA_PARM_OP_NONE,
/* This describes a brand new parameter.
The field `type' should be set to the new type, `arg_prefix'
should be set to the string prefix for the new DECL_NAME, and
`new_decl' will ultimately hold the newly created argument. */
IPA_PARM_OP_NEW,
/* This new parameter is an unmodified parameter at index base_index. */
IPA_PARM_OP_COPY,
/* This adjustment describes a parameter that is about to be removed
completely. Most users will probably need to book keep those so that they
don't leave behinfd any non default def ssa names belonging to them. */
IPA_PARM_OP_REMOVE
};
/* Structure to describe transformations of formal parameters and actual /* Structure to describe transformations of formal parameters and actual
arguments. Each instance describes one new parameter and they are meant to arguments. Each instance describes one new parameter and they are meant to
be stored in a vector. Additionally, most users will probably want to store be stored in a vector. Additionally, most users will probably want to store
...@@ -632,10 +653,11 @@ struct ipa_parm_adjustment ...@@ -632,10 +653,11 @@ struct ipa_parm_adjustment
arguments. */ arguments. */
tree alias_ptr_type; tree alias_ptr_type;
/* The new declaration when creating/replacing a parameter. Created by /* The new declaration when creating/replacing a parameter. Created
ipa_modify_formal_parameters, useful for functions modifying the body by ipa_modify_formal_parameters, useful for functions modifying
accordingly. */ the body accordingly. For brand new arguments, this is the newly
tree reduction; created argument. */
tree new_decl;
/* New declaration of a substitute variable that we may use to replace all /* New declaration of a substitute variable that we may use to replace all
non-default-def ssa names when a parm decl is going away. */ non-default-def ssa names when a parm decl is going away. */
...@@ -645,22 +667,19 @@ struct ipa_parm_adjustment ...@@ -645,22 +667,19 @@ struct ipa_parm_adjustment
is NULL), this is going to be its nonlocalized vars value. */ is NULL), this is going to be its nonlocalized vars value. */
tree nonlocal_value; tree nonlocal_value;
/* This holds the prefix to be used for the new DECL_NAME. */
const char *arg_prefix;
/* Offset into the original parameter (for the cases when the new parameter /* Offset into the original parameter (for the cases when the new parameter
is a component of an original one). */ is a component of an original one). */
HOST_WIDE_INT offset; HOST_WIDE_INT offset;
/* Zero based index of the original parameter this one is based on. (ATM /* Zero based index of the original parameter this one is based on. */
there is no way to insert a new parameter out of the blue because there is
no need but if it arises the code can be easily exteded to do so.) */
int base_index; int base_index;
/* This new parameter is an unmodified parameter at index base_index. */ /* Whether this parameter is a new parameter, a copy of an old one,
unsigned copy_param : 1; or one about to be removed. */
enum ipa_parm_op op;
/* This adjustment describes a parameter that is about to be removed
completely. Most users will probably need to book keep those so that they
don't leave behinfd any non default def ssa names belonging to them. */
unsigned remove_param : 1;
/* The parameter is to be passed by reference. */ /* The parameter is to be passed by reference. */
unsigned by_ref : 1; unsigned by_ref : 1;
...@@ -671,8 +690,8 @@ typedef struct ipa_parm_adjustment ipa_parm_adjustment_t; ...@@ -671,8 +690,8 @@ typedef struct ipa_parm_adjustment ipa_parm_adjustment_t;
typedef vec<ipa_parm_adjustment_t> ipa_parm_adjustment_vec; typedef vec<ipa_parm_adjustment_t> ipa_parm_adjustment_vec;
vec<tree> ipa_get_vector_of_formal_parms (tree fndecl); vec<tree> ipa_get_vector_of_formal_parms (tree fndecl);
void ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec, vec<tree> ipa_get_vector_of_formal_parm_types (tree fntype);
const char *); void ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec);
void ipa_modify_call_arguments (struct cgraph_edge *, gimple, void ipa_modify_call_arguments (struct cgraph_edge *, gimple,
ipa_parm_adjustment_vec); ipa_parm_adjustment_vec);
ipa_parm_adjustment_vec ipa_combine_adjustments (ipa_parm_adjustment_vec, ipa_parm_adjustment_vec ipa_combine_adjustments (ipa_parm_adjustment_vec,
...@@ -690,6 +709,10 @@ tree ipa_value_from_jfunc (struct ipa_node_params *info, ...@@ -690,6 +709,10 @@ tree ipa_value_from_jfunc (struct ipa_node_params *info,
struct ipa_jump_func *jfunc); struct ipa_jump_func *jfunc);
unsigned int ipcp_transform_function (struct cgraph_node *node); unsigned int ipcp_transform_function (struct cgraph_node *node);
void ipa_dump_param (FILE *, struct ipa_node_params *info, int i); void ipa_dump_param (FILE *, struct ipa_node_params *info, int i);
bool ipa_modify_expr (tree *, bool, ipa_parm_adjustment_vec);
ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *,
ipa_parm_adjustment_vec,
bool);
/* From tree-sra.c: */ /* From tree-sra.c: */
......
...@@ -246,7 +246,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, ...@@ -246,7 +246,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
hope calls to them will be devirtualized. hope calls to them will be devirtualized.
Again we remove them after inlining. In late optimization some Again we remove them after inlining. In late optimization some
devirtualization may happen, but it is not importnat since we won't inline devirtualization may happen, but it is not important since we won't inline
the call. In theory early opts and IPA should work out all important cases. the call. In theory early opts and IPA should work out all important cases.
- virtual clones needs bodies of their origins for later materialization; - virtual clones needs bodies of their origins for later materialization;
...@@ -274,7 +274,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, ...@@ -274,7 +274,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
by reachable symbols or origins of clones). The queue is represented by reachable symbols or origins of clones). The queue is represented
as linked list by AUX pointer terminated by 1. as linked list by AUX pointer terminated by 1.
A the end we keep all reachable symbols. For symbols in boundary we always At the end we keep all reachable symbols. For symbols in boundary we always
turn definition into a declaration, but we may keep function body around turn definition into a declaration, but we may keep function body around
based on body_needed_for_clonning based on body_needed_for_clonning
......
...@@ -4281,9 +4281,10 @@ turn_representatives_into_adjustments (vec<access_p> representatives, ...@@ -4281,9 +4281,10 @@ turn_representatives_into_adjustments (vec<access_p> representatives,
adj.base_index = get_param_index (parm, parms); adj.base_index = get_param_index (parm, parms);
adj.base = parm; adj.base = parm;
if (!repr) if (!repr)
adj.copy_param = 1; adj.op = IPA_PARM_OP_COPY;
else else
adj.remove_param = 1; adj.op = IPA_PARM_OP_REMOVE;
adj.arg_prefix = "ISRA";
adjustments.quick_push (adj); adjustments.quick_push (adj);
} }
else else
...@@ -4303,6 +4304,7 @@ turn_representatives_into_adjustments (vec<access_p> representatives, ...@@ -4303,6 +4304,7 @@ turn_representatives_into_adjustments (vec<access_p> representatives,
adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base)) adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
&& (repr->grp_maybe_modified && (repr->grp_maybe_modified
|| repr->grp_not_necessarilly_dereferenced)); || repr->grp_not_necessarilly_dereferenced));
adj.arg_prefix = "ISRA";
adjustments.quick_push (adj); adjustments.quick_push (adj);
} }
} }
...@@ -4433,7 +4435,7 @@ get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base) ...@@ -4433,7 +4435,7 @@ get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base)
struct ipa_parm_adjustment *adj; struct ipa_parm_adjustment *adj;
adj = &adjustments[i]; adj = &adjustments[i];
if (!adj->copy_param && adj->base == base) if (adj->op != IPA_PARM_OP_COPY && adj->base == base)
return adj; return adj;
} }
...@@ -4497,84 +4499,6 @@ replace_removed_params_ssa_names (gimple stmt, ...@@ -4497,84 +4499,6 @@ replace_removed_params_ssa_names (gimple stmt,
return true; return true;
} }
/* If the expression *EXPR should be replaced by a reduction of a parameter, do
so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT
specifies whether the function should care about type incompatibility the
current and new expressions. If it is false, the function will leave
incompatibility issues to the caller. Return true iff the expression
was modified. */
static bool
sra_ipa_modify_expr (tree *expr, bool convert,
ipa_parm_adjustment_vec adjustments)
{
int i, len;
struct ipa_parm_adjustment *adj, *cand = NULL;
HOST_WIDE_INT offset, size, max_size;
tree base, src;
len = adjustments.length ();
if (TREE_CODE (*expr) == BIT_FIELD_REF
|| TREE_CODE (*expr) == IMAGPART_EXPR
|| TREE_CODE (*expr) == REALPART_EXPR)
{
expr = &TREE_OPERAND (*expr, 0);
convert = true;
}
base = get_ref_base_and_extent (*expr, &offset, &size, &max_size);
if (!base || size == -1 || max_size == -1)
return false;
if (TREE_CODE (base) == MEM_REF)
{
offset += mem_ref_offset (base).low * BITS_PER_UNIT;
base = TREE_OPERAND (base, 0);
}
base = get_ssa_base_param (base);
if (!base || TREE_CODE (base) != PARM_DECL)
return false;
for (i = 0; i < len; i++)
{
adj = &adjustments[i];
if (adj->base == base
&& (adj->offset == offset || adj->remove_param))
{
cand = adj;
break;
}
}
if (!cand || cand->copy_param || cand->remove_param)
return false;
if (cand->by_ref)
src = build_simple_mem_ref (cand->reduction);
else
src = cand->reduction;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "About to replace expr ");
print_generic_expr (dump_file, *expr, 0);
fprintf (dump_file, " with ");
print_generic_expr (dump_file, src, 0);
fprintf (dump_file, "\n");
}
if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type))
{
tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src);
*expr = vce;
}
else
*expr = src;
return true;
}
/* If the statement pointed to by STMT_PTR contains any expressions that need /* If the statement pointed to by STMT_PTR contains any expressions that need
to replaced with a different one as noted by ADJUSTMENTS, do so. Handle any to replaced with a different one as noted by ADJUSTMENTS, do so. Handle any
potential type incompatibilities (GSI is used to accommodate conversion potential type incompatibilities (GSI is used to accommodate conversion
...@@ -4595,8 +4519,8 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, ...@@ -4595,8 +4519,8 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
rhs_p = gimple_assign_rhs1_ptr (stmt); rhs_p = gimple_assign_rhs1_ptr (stmt);
lhs_p = gimple_assign_lhs_ptr (stmt); lhs_p = gimple_assign_lhs_ptr (stmt);
any = sra_ipa_modify_expr (rhs_p, false, adjustments); any = ipa_modify_expr (rhs_p, false, adjustments);
any |= sra_ipa_modify_expr (lhs_p, false, adjustments); any |= ipa_modify_expr (lhs_p, false, adjustments);
if (any) if (any)
{ {
tree new_rhs = NULL_TREE; tree new_rhs = NULL_TREE;
...@@ -4642,7 +4566,7 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, ...@@ -4642,7 +4566,7 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi,
/* Traverse the function body and all modifications as described in /* Traverse the function body and all modifications as described in
ADJUSTMENTS. Return true iff the CFG has been changed. */ ADJUSTMENTS. Return true iff the CFG has been changed. */
static bool bool
ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
{ {
bool cfg_changed = false; bool cfg_changed = false;
...@@ -4668,7 +4592,7 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) ...@@ -4668,7 +4592,7 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
case GIMPLE_RETURN: case GIMPLE_RETURN:
t = gimple_return_retval_ptr (stmt); t = gimple_return_retval_ptr (stmt);
if (*t != NULL_TREE) if (*t != NULL_TREE)
modified |= sra_ipa_modify_expr (t, true, adjustments); modified |= ipa_modify_expr (t, true, adjustments);
break; break;
case GIMPLE_ASSIGN: case GIMPLE_ASSIGN:
...@@ -4681,13 +4605,13 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) ...@@ -4681,13 +4605,13 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
for (i = 0; i < gimple_call_num_args (stmt); i++) for (i = 0; i < gimple_call_num_args (stmt); i++)
{ {
t = gimple_call_arg_ptr (stmt, i); t = gimple_call_arg_ptr (stmt, i);
modified |= sra_ipa_modify_expr (t, true, adjustments); modified |= ipa_modify_expr (t, true, adjustments);
} }
if (gimple_call_lhs (stmt)) if (gimple_call_lhs (stmt))
{ {
t = gimple_call_lhs_ptr (stmt); t = gimple_call_lhs_ptr (stmt);
modified |= sra_ipa_modify_expr (t, false, adjustments); modified |= ipa_modify_expr (t, false, adjustments);
modified |= replace_removed_params_ssa_names (stmt, modified |= replace_removed_params_ssa_names (stmt,
adjustments); adjustments);
} }
...@@ -4697,12 +4621,12 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) ...@@ -4697,12 +4621,12 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments)
for (i = 0; i < gimple_asm_ninputs (stmt); i++) for (i = 0; i < gimple_asm_ninputs (stmt); i++)
{ {
t = &TREE_VALUE (gimple_asm_input_op (stmt, i)); t = &TREE_VALUE (gimple_asm_input_op (stmt, i));
modified |= sra_ipa_modify_expr (t, true, adjustments); modified |= ipa_modify_expr (t, true, adjustments);
} }
for (i = 0; i < gimple_asm_noutputs (stmt); i++) for (i = 0; i < gimple_asm_noutputs (stmt); i++)
{ {
t = &TREE_VALUE (gimple_asm_output_op (stmt, i)); t = &TREE_VALUE (gimple_asm_output_op (stmt, i));
modified |= sra_ipa_modify_expr (t, false, adjustments); modified |= ipa_modify_expr (t, false, adjustments);
} }
break; break;
...@@ -4748,7 +4672,7 @@ sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments) ...@@ -4748,7 +4672,7 @@ sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments)
use_operand_p use_p; use_operand_p use_p;
adj = &adjustments[i]; adj = &adjustments[i];
if (adj->copy_param || !is_gimple_reg (adj->base)) if (adj->op == IPA_PARM_OP_COPY || !is_gimple_reg (adj->base))
continue; continue;
name = ssa_default_def (cfun, adj->base); name = ssa_default_def (cfun, adj->base);
vexpr = NULL; vexpr = NULL;
...@@ -4931,7 +4855,7 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments) ...@@ -4931,7 +4855,7 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
redirect_callers.release (); redirect_callers.release ();
push_cfun (DECL_STRUCT_FUNCTION (new_node->decl)); push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA"); ipa_modify_formal_parameters (current_function_decl, adjustments);
cfg_changed = ipa_sra_modify_function_body (adjustments); cfg_changed = ipa_sra_modify_function_body (adjustments);
sra_ipa_reset_debug_stmts (adjustments); sra_ipa_reset_debug_stmts (adjustments);
convert_callers (new_node, node->decl, adjustments); convert_callers (new_node, node->decl, adjustments);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment