Commit c0cb5055 by Martin Jambor Committed by Martin Jambor

ipa-cp.c (ipcp_value_source): Converted to a template class.

2014-11-14  Martin Jambor  <mjambor@suse.cz>

	* ipa-cp.c (ipcp_value_source): Converted to a template class.  All
	users converted to the same specialization as the using class/function
	or specialization on tree.
	(ipcp_value): Likewise.
	(ipcp_lattice): Likewise.
	(ipcp_agg_lattice): Now derived from tree specialization of
	ipcp_lattice.
	(values_topo): Moved to new class value_topo_info.
	(ipa_lat_is_single_const): Turned into ipcp_lattice::is_single_const.
	Updated all callers.
	(print_lattice): Turned into ipcp_lattice::print.  Updated all
	callers.
	(value_topo_info): New class template.
	(ipa_topo_info): New field constants.  New constructor.
	(build_toporder_info): Do not clear stack_top, only checkign assert
	it.
	(set_lattice_to_bottom): Turned into ipcp_lattice::set_to_bottom.
	Updated all callers.
	(set_lattice_contains_variable): Turned into
	ipcp_lattice::set_contains_variable.  Updated all callers.
	(add_value_source): Turned into ipcp_value::add_source.  Updated all
	callers.
	(allocate_and_init_ipcp_value): New function.
	(add_value_to_lattice): Turned into ipcp_lattice::add_value.  Last
	parameter got default a value.  Updated all callers.
	(add_scalar_value_to_lattice): Removed, users converted to using
	ipcp_lattice::add_value with default value of the last parameter.
	(add_val_to_toposort): Turned to value_topo_info::add_val.  Updated
	all callers.
	(propagate_effects): Made method of value_topo_info.
	(cgraph_edge_brings_value_p): Now a template function.
	(get_info_about_necessary_edges): Likewise.
	(gather_edges_for_value): Likewise.
	(perhaps_add_new_callers): Likewise.
	(decide_about_value): Likewise.
	* ipa-prop.h (ipcp_lattice): Remove fowrward declaration.

From-SVN: r217586
parent b907149b
2014-11-14 Martin Jambor <mjambor@suse.cz>
* ipa-cp.c (ipcp_value_source): Converted to a template class. All
users converted to the same specialization as the using class/function
or specialization on tree.
(ipcp_value): Likewise.
(ipcp_lattice): Likewise.
(ipcp_agg_lattice): Now derived from tree specialization of
ipcp_lattice.
(values_topo): Moved to new class value_topo_info.
(ipa_lat_is_single_const): Turned into ipcp_lattice::is_single_const.
Updated all callers.
(print_lattice): Turned into ipcp_lattice::print. Updated all
callers.
(value_topo_info): New class template.
(ipa_topo_info): New field constants. New constructor.
(build_toporder_info): Do not clear stack_top, only checkign assert
it.
(set_lattice_to_bottom): Turned into ipcp_lattice::set_to_bottom.
Updated all callers.
(set_lattice_contains_variable): Turned into
ipcp_lattice::set_contains_variable. Updated all callers.
(add_value_source): Turned into ipcp_value::add_source. Updated all
callers.
(allocate_and_init_ipcp_value): New function.
(add_value_to_lattice): Turned into ipcp_lattice::add_value. Last
parameter got default a value. Updated all callers.
(add_scalar_value_to_lattice): Removed, users converted to using
ipcp_lattice::add_value with default value of the last parameter.
(add_val_to_toposort): Turned to value_topo_info::add_val. Updated
all callers.
(propagate_effects): Made method of value_topo_info.
(cgraph_edge_brings_value_p): Now a template function.
(get_info_about_necessary_edges): Likewise.
(gather_edges_for_value): Likewise.
(perhaps_add_new_callers): Likewise.
(decide_about_value): Likewise.
* ipa-prop.h (ipcp_lattice): Remove fowrward declaration.
2014-11-14 Jakub Jelinek <jakub@redhat.com> 2014-11-14 Jakub Jelinek <jakub@redhat.com>
* doc/install.texi (--with-diagnostics-color=): Document. * doc/install.texi (--with-diagnostics-color=): Document.
...@@ -134,61 +134,73 @@ along with GCC; see the file COPYING3. If not see ...@@ -134,61 +134,73 @@ along with GCC; see the file COPYING3. If not see
#include "ipa-inline.h" #include "ipa-inline.h"
#include "ipa-utils.h" #include "ipa-utils.h"
struct ipcp_value; template <typename valtype> class ipcp_value;
/* Describes a particular source for an IPA-CP value. */ /* Describes a particular source for an IPA-CP value. */
struct ipcp_value_source template <typename valtype>
class ipcp_value_source
{ {
public:
/* Aggregate offset of the source, negative if the source is scalar value of /* Aggregate offset of the source, negative if the source is scalar value of
the argument itself. */ the argument itself. */
HOST_WIDE_INT offset; HOST_WIDE_INT offset;
/* The incoming edge that brought the value. */ /* The incoming edge that brought the value. */
struct cgraph_edge *cs; cgraph_edge *cs;
/* If the jump function that resulted into his value was a pass-through or an /* If the jump function that resulted into his value was a pass-through or an
ancestor, this is the ipcp_value of the caller from which the described ancestor, this is the ipcp_value of the caller from which the described
value has been derived. Otherwise it is NULL. */ value has been derived. Otherwise it is NULL. */
struct ipcp_value *val; ipcp_value<valtype> *val;
/* Next pointer in a linked list of sources of a value. */ /* Next pointer in a linked list of sources of a value. */
struct ipcp_value_source *next; ipcp_value_source *next;
/* If the jump function that resulted into his value was a pass-through or an /* If the jump function that resulted into his value was a pass-through or an
ancestor, this is the index of the parameter of the caller the jump ancestor, this is the index of the parameter of the caller the jump
function references. */ function references. */
int index; int index;
}; };
/* Common ancestor for all ipcp_value instantiations. */
class ipcp_value_base
{
public:
/* Time benefit and size cost that specializing the function for this value
would bring about in this function alone. */
int local_time_benefit, local_size_cost;
/* Time benefit and size cost that specializing the function for this value
can bring about in it's callees (transitively). */
int prop_time_benefit, prop_size_cost;
};
/* Describes one particular value stored in struct ipcp_lattice. */ /* Describes one particular value stored in struct ipcp_lattice. */
struct ipcp_value template <typename valtype>
class ipcp_value : public ipcp_value_base
{ {
/* The actual value for the given parameter. This is either an IPA invariant public:
or a TREE_BINFO describing a type that can be used for /* The actual value for the given parameter. */
devirtualization. */ valtype value;
tree value;
/* The list of sources from which this value originates. */ /* The list of sources from which this value originates. */
struct ipcp_value_source *sources; ipcp_value_source <valtype> *sources;
/* Next pointers in a linked list of all values in a lattice. */ /* Next pointers in a linked list of all values in a lattice. */
struct ipcp_value *next; ipcp_value *next;
/* Next pointers in a linked list of values in a strongly connected component /* Next pointers in a linked list of values in a strongly connected component
of values. */ of values. */
struct ipcp_value *scc_next; ipcp_value *scc_next;
/* Next pointers in a linked list of SCCs of values sorted topologically /* Next pointers in a linked list of SCCs of values sorted topologically
according their sources. */ according their sources. */
struct ipcp_value *topo_next; ipcp_value *topo_next;
/* A specialized node created for this value, NULL if none has been (so far) /* A specialized node created for this value, NULL if none has been (so far)
created. */ created. */
struct cgraph_node *spec_node; cgraph_node *spec_node;
/* Depth first search number and low link for topological sorting of /* Depth first search number and low link for topological sorting of
values. */ values. */
int dfs, low_link; int dfs, low_link;
/* Time benefit and size cost that specializing the function for this value
would bring about in this function alone. */
int local_time_benefit, local_size_cost;
/* Time benefit and size cost that specializing the function for this value
can bring about in it's callees (transitively). */
int prop_time_benefit, prop_size_cost;
/* True if this valye is currently on the topo-sort stack. */ /* True if this valye is currently on the topo-sort stack. */
bool on_stack; bool on_stack;
void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx,
HOST_WIDE_INT offset);
}; };
/* Lattice describing potential values of a formal parameter of a function, or /* Lattice describing potential values of a formal parameter of a function, or
...@@ -197,12 +209,14 @@ struct ipcp_value ...@@ -197,12 +209,14 @@ struct ipcp_value
by a lattice with the bottom flag set. In that case, values and by a lattice with the bottom flag set. In that case, values and
contains_variable flag should be disregarded. */ contains_variable flag should be disregarded. */
struct ipcp_lattice template <typename valtype>
class ipcp_lattice
{ {
public:
/* The list of known values and types in this lattice. Note that values are /* The list of known values and types in this lattice. Note that values are
not deallocated if a lattice is set to bottom because there may be value not deallocated if a lattice is set to bottom because there may be value
sources referencing them. */ sources referencing them. */
struct ipcp_value *values; ipcp_value<valtype> *values;
/* Number of known values and types in this lattice. */ /* Number of known values and types in this lattice. */
int values_count; int values_count;
/* The lattice contains a variable component (in addition to values). */ /* The lattice contains a variable component (in addition to values). */
...@@ -210,12 +224,22 @@ struct ipcp_lattice ...@@ -210,12 +224,22 @@ struct ipcp_lattice
/* The value of the lattice is bottom (i.e. variable and unusable for any /* The value of the lattice is bottom (i.e. variable and unusable for any
propagation). */ propagation). */
bool bottom; bool bottom;
inline bool is_single_const ();
inline bool set_to_bottom ();
inline bool set_contains_variable ();
bool add_value (valtype newval, cgraph_edge *cs,
ipcp_value<valtype> *src_val = NULL,
int src_idx = 0, HOST_WIDE_INT offset = -1);
void print (FILE * f, bool dump_sources, bool dump_benefits);
}; };
/* Lattice with an offset to describe a part of an aggregate. */ /* Lattice of tree values with an offset to describe a part of an
aggregate. */
struct ipcp_agg_lattice : public ipcp_lattice class ipcp_agg_lattice : public ipcp_lattice<tree>
{ {
public:
/* Offset that is being described by this lattice. */ /* Offset that is being described by this lattice. */
HOST_WIDE_INT offset; HOST_WIDE_INT offset;
/* Size so that we don't have to re-compute it every time we traverse the /* Size so that we don't have to re-compute it every time we traverse the
...@@ -229,12 +253,13 @@ struct ipcp_agg_lattice : public ipcp_lattice ...@@ -229,12 +253,13 @@ struct ipcp_agg_lattice : public ipcp_lattice
aggregates that are passed in the parameter or by a reference in a parameter aggregates that are passed in the parameter or by a reference in a parameter
plus some other useful flags. */ plus some other useful flags. */
struct ipcp_param_lattices class ipcp_param_lattices
{ {
public:
/* Lattice describing the value of the parameter itself. */ /* Lattice describing the value of the parameter itself. */
struct ipcp_lattice itself; ipcp_lattice<tree> itself;
/* Lattices describing aggregate parts. */ /* Lattices describing aggregate parts. */
struct ipcp_agg_lattice *aggs; ipcp_agg_lattice *aggs;
/* Number of aggregate lattices */ /* Number of aggregate lattices */
int aggs_count; int aggs_count;
/* True if aggregate data were passed by reference (as opposed to by /* True if aggregate data were passed by reference (as opposed to by
...@@ -265,10 +290,6 @@ static gcov_type max_count; ...@@ -265,10 +290,6 @@ static gcov_type max_count;
static long overall_size, max_new_size; static long overall_size, max_new_size;
/* Head of the linked list of topologically sorted values. */
static struct ipcp_value *values_topo;
/* Return the param lattices structure corresponding to the Ith formal /* Return the param lattices structure corresponding to the Ith formal
parameter of the function described by INFO. */ parameter of the function described by INFO. */
static inline struct ipcp_param_lattices * static inline struct ipcp_param_lattices *
...@@ -282,7 +303,7 @@ ipa_get_parm_lattices (struct ipa_node_params *info, int i) ...@@ -282,7 +303,7 @@ ipa_get_parm_lattices (struct ipa_node_params *info, int i)
/* Return the lattice corresponding to the scalar value of the Ith formal /* Return the lattice corresponding to the scalar value of the Ith formal
parameter of the function described by INFO. */ parameter of the function described by INFO. */
static inline struct ipcp_lattice * static inline ipcp_lattice<tree> *
ipa_get_scalar_lat (struct ipa_node_params *info, int i) ipa_get_scalar_lat (struct ipa_node_params *info, int i)
{ {
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
...@@ -292,12 +313,11 @@ ipa_get_scalar_lat (struct ipa_node_params *info, int i) ...@@ -292,12 +313,11 @@ ipa_get_scalar_lat (struct ipa_node_params *info, int i)
/* Return whether LAT is a lattice with a single constant and without an /* Return whether LAT is a lattice with a single constant and without an
undefined value. */ undefined value. */
static inline bool template <typename valtype>
ipa_lat_is_single_const (struct ipcp_lattice *lat) inline bool
ipcp_lattice<valtype>::is_single_const ()
{ {
if (lat->bottom if (bottom || contains_variable || values_count != 1)
|| lat->contains_variable
|| lat->values_count != 1)
return false; return false;
else else
return true; return true;
...@@ -325,26 +345,26 @@ print_ipcp_constant_value (FILE * f, tree v) ...@@ -325,26 +345,26 @@ print_ipcp_constant_value (FILE * f, tree v)
/* Print a lattice LAT to F. */ /* Print a lattice LAT to F. */
static void template <typename valtype>
print_lattice (FILE * f, struct ipcp_lattice *lat, void
bool dump_sources, bool dump_benefits) ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits)
{ {
struct ipcp_value *val; ipcp_value<valtype> *val;
bool prev = false; bool prev = false;
if (lat->bottom) if (bottom)
{ {
fprintf (f, "BOTTOM\n"); fprintf (f, "BOTTOM\n");
return; return;
} }
if (!lat->values_count && !lat->contains_variable) if (!values_count && !contains_variable)
{ {
fprintf (f, "TOP\n"); fprintf (f, "TOP\n");
return; return;
} }
if (lat->contains_variable) if (contains_variable)
{ {
fprintf (f, "VARIABLE"); fprintf (f, "VARIABLE");
prev = true; prev = true;
...@@ -352,7 +372,7 @@ print_lattice (FILE * f, struct ipcp_lattice *lat, ...@@ -352,7 +372,7 @@ print_lattice (FILE * f, struct ipcp_lattice *lat,
fprintf (f, "\n"); fprintf (f, "\n");
} }
for (val = lat->values; val; val = val->next) for (val = values; val; val = val->next)
{ {
if (dump_benefits && prev) if (dump_benefits && prev)
fprintf (f, " "); fprintf (f, " ");
...@@ -365,7 +385,7 @@ print_lattice (FILE * f, struct ipcp_lattice *lat, ...@@ -365,7 +385,7 @@ print_lattice (FILE * f, struct ipcp_lattice *lat,
if (dump_sources) if (dump_sources)
{ {
struct ipcp_value_source *s; ipcp_value_source<valtype> *s;
fprintf (f, " [from:"); fprintf (f, " [from:");
for (s = val->sources; s; s = s->next) for (s = val->sources; s; s = s->next)
...@@ -406,7 +426,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) ...@@ -406,7 +426,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
struct ipcp_agg_lattice *aglat; struct ipcp_agg_lattice *aglat;
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
fprintf (f, " param [%d]: ", i); fprintf (f, " param [%d]: ", i);
print_lattice (f, &plats->itself, dump_sources, dump_benefits); plats->itself.print (f, dump_sources, dump_benefits);
if (plats->virt_call) if (plats->virt_call)
fprintf (f, " virt_call flag set\n"); fprintf (f, " virt_call flag set\n");
...@@ -422,7 +442,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) ...@@ -422,7 +442,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits)
{ {
fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ", fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ",
plats->aggs_by_ref ? "ref " : "", aglat->offset); plats->aggs_by_ref ? "ref " : "", aglat->offset);
print_lattice (f, aglat, dump_sources, dump_benefits); aglat->print (f, dump_sources, dump_benefits);
} }
} }
} }
...@@ -586,14 +606,43 @@ ipcp_cloning_candidate_p (struct cgraph_node *node) ...@@ -586,14 +606,43 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
return true; return true;
} }
template <typename valtype>
class value_topo_info
{
public:
/* Head of the linked list of topologically sorted values. */
ipcp_value<valtype> *values_topo;
/* Stack for creating SCCs, represented by a linked list too. */
ipcp_value<valtype> *stack;
/* Counter driving the algorithm in add_val_to_toposort. */
int dfs_counter;
value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0)
{}
void add_val (ipcp_value<valtype> *cur_val);
void propagate_effects ();
};
/* Arrays representing a topological ordering of call graph nodes and a stack /* Arrays representing a topological ordering of call graph nodes and a stack
of noes used during constant propagation. */ of nodes used during constant propagation and also data required to perform
topological sort of values and propagation of benefits in the determined
order. */
struct ipa_topo_info class ipa_topo_info
{ {
public:
/* Array with obtained topological order of cgraph nodes. */
struct cgraph_node **order; struct cgraph_node **order;
/* Stack of cgraph nodes used during propagation within SCC until all values
in the SCC stabilize. */
struct cgraph_node **stack; struct cgraph_node **stack;
int nnodes, stack_top; int nnodes, stack_top;
value_topo_info<tree> constants;
ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0),
constants ()
{}
}; };
/* Allocate the arrays in TOPO and topologically sort the nodes into order. */ /* Allocate the arrays in TOPO and topologically sort the nodes into order. */
...@@ -604,7 +653,7 @@ build_toporder_info (struct ipa_topo_info *topo) ...@@ -604,7 +653,7 @@ build_toporder_info (struct ipa_topo_info *topo)
topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
topo->stack_top = 0; gcc_checking_assert (topo->stack_top == 0);
topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL); topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL);
} }
...@@ -652,22 +701,24 @@ pop_node_from_stack (struct ipa_topo_info *topo) ...@@ -652,22 +701,24 @@ pop_node_from_stack (struct ipa_topo_info *topo)
/* Set lattice LAT to bottom and return true if it previously was not set as /* Set lattice LAT to bottom and return true if it previously was not set as
such. */ such. */
static inline bool template <typename valtype>
set_lattice_to_bottom (struct ipcp_lattice *lat) inline bool
ipcp_lattice<valtype>::set_to_bottom ()
{ {
bool ret = !lat->bottom; bool ret = !bottom;
lat->bottom = true; bottom = true;
return ret; return ret;
} }
/* Mark lattice as containing an unknown value and return true if it previously /* Mark lattice as containing an unknown value and return true if it previously
was not marked as such. */ was not marked as such. */
static inline bool template <typename valtype>
set_lattice_contains_variable (struct ipcp_lattice *lat) inline bool
ipcp_lattice<valtype>::set_contains_variable ()
{ {
bool ret = !lat->contains_variable; bool ret = !contains_variable;
lat->contains_variable = true; contains_variable = true;
return ret; return ret;
} }
...@@ -735,7 +786,7 @@ initialize_node_lattices (struct cgraph_node *node) ...@@ -735,7 +786,7 @@ initialize_node_lattices (struct cgraph_node *node)
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
if (disable) if (disable)
{ {
set_lattice_to_bottom (&plats->itself); plats->itself.set_to_bottom ();
set_agg_lats_to_bottom (plats); set_agg_lats_to_bottom (plats);
} }
else else
...@@ -864,7 +915,7 @@ ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc) ...@@ -864,7 +915,7 @@ ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
input = info->known_vals[idx]; input = info->known_vals[idx];
else else
{ {
struct ipcp_lattice *lat; ipcp_lattice<tree> *lat;
if (!info->lattices) if (!info->lattices)
{ {
...@@ -872,7 +923,7 @@ ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc) ...@@ -872,7 +923,7 @@ ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
return NULL_TREE; return NULL_TREE;
} }
lat = ipa_get_scalar_lat (info, idx); lat = ipa_get_scalar_lat (info, idx);
if (!ipa_lat_is_single_const (lat)) if (!lat->is_single_const ())
return NULL_TREE; return NULL_TREE;
input = lat->values->value; input = lat->values->value;
} }
...@@ -906,7 +957,7 @@ ipcp_verify_propagated_values (void) ...@@ -906,7 +957,7 @@ ipcp_verify_propagated_values (void)
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
{ {
struct ipcp_lattice *lat = ipa_get_scalar_lat (info, i); ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i);
if (!lat->bottom if (!lat->bottom
&& !lat->contains_variable && !lat->contains_variable
...@@ -949,48 +1000,65 @@ values_equal_for_ipcp_p (tree x, tree y) ...@@ -949,48 +1000,65 @@ values_equal_for_ipcp_p (tree x, tree y)
return operand_equal_p (x, y, 0); return operand_equal_p (x, y, 0);
} }
/* Add a new value source to VAL, marking that a value comes from edge CS and /* Add a new value source to the value represented by THIS, marking that a
(if the underlying jump function is a pass-through or an ancestor one) from value comes from edge CS and (if the underlying jump function is a
a caller value SRC_VAL of a caller parameter described by SRC_INDEX. OFFSET pass-through or an ancestor one) from a caller value SRC_VAL of a caller
is negative if the source was the scalar value of the parameter itself or parameter described by SRC_INDEX. OFFSET is negative if the source was the
the offset within an aggregate. */ scalar value of the parameter itself or the offset within an aggregate. */
static void template <typename valtype>
add_value_source (struct ipcp_value *val, struct cgraph_edge *cs, void
struct ipcp_value *src_val, int src_idx, HOST_WIDE_INT offset) ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val,
int src_idx, HOST_WIDE_INT offset)
{ {
struct ipcp_value_source *src; ipcp_value_source<valtype> *src;
src = (struct ipcp_value_source *) pool_alloc (ipcp_sources_pool); src = new (pool_alloc (ipcp_sources_pool)) ipcp_value_source<valtype>;
src->offset = offset; src->offset = offset;
src->cs = cs; src->cs = cs;
src->val = src_val; src->val = src_val;
src->index = src_idx; src->index = src_idx;
src->next = val->sources; src->next = sources;
val->sources = src; sources = src;
} }
/* Try to add NEWVAL to LAT, potentially creating a new struct ipcp_value for /* Allocate a new ipcp_value holding a tree constant, initialize its value to
it. CS, SRC_VAL SRC_INDEX and OFFSET are meant for add_value_source and SOURCE and clear all other fields. */
have the same meaning. */
static bool static ipcp_value<tree> *
add_value_to_lattice (struct ipcp_lattice *lat, tree newval, allocate_and_init_ipcp_value (tree source)
struct cgraph_edge *cs, struct ipcp_value *src_val,
int src_idx, HOST_WIDE_INT offset)
{ {
struct ipcp_value *val; ipcp_value<tree> *val;
if (lat->bottom) val = new (pool_alloc (ipcp_values_pool)) ipcp_value<tree>;
memset (val, 0, sizeof (*val));
val->value = source;
return val;
}
/* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
meaning. OFFSET -1 means the source is scalar and not a part of an
aggregate. */
template <typename valtype>
bool
ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
ipcp_value<valtype> *src_val,
int src_idx, HOST_WIDE_INT offset)
{
ipcp_value<valtype> *val;
if (bottom)
return false; return false;
for (val = lat->values; val; val = val->next) for (val = values; val; val = val->next)
if (values_equal_for_ipcp_p (val->value, newval)) if (values_equal_for_ipcp_p (val->value, newval))
{ {
if (ipa_edge_within_scc (cs)) if (ipa_edge_within_scc (cs))
{ {
struct ipcp_value_source *s; ipcp_value_source<valtype> *s;
for (s = val->sources; s ; s = s->next) for (s = val->sources; s ; s = s->next)
if (s->cs == cs) if (s->cs == cs)
break; break;
...@@ -998,63 +1066,48 @@ add_value_to_lattice (struct ipcp_lattice *lat, tree newval, ...@@ -998,63 +1066,48 @@ add_value_to_lattice (struct ipcp_lattice *lat, tree newval,
return false; return false;
} }
add_value_source (val, cs, src_val, src_idx, offset); val->add_source (cs, src_val, src_idx, offset);
return false; return false;
} }
if (lat->values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE)) if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE))
{ {
/* We can only free sources, not the values themselves, because sources /* We can only free sources, not the values themselves, because sources
of other values in this this SCC might point to them. */ of other values in this this SCC might point to them. */
for (val = lat->values; val; val = val->next) for (val = values; val; val = val->next)
{ {
while (val->sources) while (val->sources)
{ {
struct ipcp_value_source *src = val->sources; ipcp_value_source<valtype> *src = val->sources;
val->sources = src->next; val->sources = src->next;
pool_free (ipcp_sources_pool, src); pool_free (ipcp_sources_pool, src);
} }
} }
lat->values = NULL; values = NULL;
return set_lattice_to_bottom (lat); return set_to_bottom ();
} }
lat->values_count++; values_count++;
val = (struct ipcp_value *) pool_alloc (ipcp_values_pool); val = allocate_and_init_ipcp_value (newval);
memset (val, 0, sizeof (*val)); val->add_source (cs, src_val, src_idx, offset);
val->next = values;
add_value_source (val, cs, src_val, src_idx, offset); values = val;
val->value = newval;
val->next = lat->values;
lat->values = val;
return true; return true;
} }
/* Like above but passes a special value of offset to distinguish that the
origin is the scalar value of the parameter rather than a part of an
aggregate. */
static inline bool
add_scalar_value_to_lattice (struct ipcp_lattice *lat, tree newval,
struct cgraph_edge *cs,
struct ipcp_value *src_val, int src_idx)
{
return add_value_to_lattice (lat, newval, cs, src_val, src_idx, -1);
}
/* Propagate values through a pass-through jump function JFUNC associated with /* 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 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX
is the index of the source parameter. */ is the index of the source parameter. */
static bool static bool
propagate_vals_accross_pass_through (struct cgraph_edge *cs, propagate_vals_accross_pass_through (cgraph_edge *cs,
struct ipa_jump_func *jfunc, ipa_jump_func *jfunc,
struct ipcp_lattice *src_lat, ipcp_lattice<tree> *src_lat,
struct ipcp_lattice *dest_lat, ipcp_lattice<tree> *dest_lat,
int src_idx) int src_idx)
{ {
struct ipcp_value *src_val; ipcp_value<tree> *src_val;
bool ret = false; bool ret = false;
/* Do not create new values when propagating within an SCC because if there /* Do not create new values when propagating within an SCC because if there
...@@ -1062,17 +1115,16 @@ propagate_vals_accross_pass_through (struct cgraph_edge *cs, ...@@ -1062,17 +1115,16 @@ propagate_vals_accross_pass_through (struct cgraph_edge *cs,
number of them and we would just make lattices bottom. */ number of them and we would just make lattices bottom. */
if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR)
&& ipa_edge_within_scc (cs)) && ipa_edge_within_scc (cs))
ret = set_lattice_contains_variable (dest_lat); ret = dest_lat->set_contains_variable ();
else else
for (src_val = src_lat->values; src_val; src_val = src_val->next) 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); tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value);
if (cstval) if (cstval)
ret |= add_scalar_value_to_lattice (dest_lat, cstval, cs, src_val, ret |= dest_lat->add_value (cstval, cs, src_val, src_idx);
src_idx);
else else
ret |= set_lattice_contains_variable (dest_lat); ret |= dest_lat->set_contains_variable ();
} }
return ret; return ret;
...@@ -1085,24 +1137,24 @@ propagate_vals_accross_pass_through (struct cgraph_edge *cs, ...@@ -1085,24 +1137,24 @@ propagate_vals_accross_pass_through (struct cgraph_edge *cs,
static bool static bool
propagate_vals_accross_ancestor (struct cgraph_edge *cs, propagate_vals_accross_ancestor (struct cgraph_edge *cs,
struct ipa_jump_func *jfunc, struct ipa_jump_func *jfunc,
struct ipcp_lattice *src_lat, ipcp_lattice<tree> *src_lat,
struct ipcp_lattice *dest_lat, ipcp_lattice<tree> *dest_lat,
int src_idx) int src_idx)
{ {
struct ipcp_value *src_val; ipcp_value<tree> *src_val;
bool ret = false; bool ret = false;
if (ipa_edge_within_scc (cs)) if (ipa_edge_within_scc (cs))
return set_lattice_contains_variable (dest_lat); return dest_lat->set_contains_variable ();
for (src_val = src_lat->values; src_val; src_val = src_val->next) for (src_val = src_lat->values; src_val; src_val = src_val->next)
{ {
tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value); tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value);
if (t) if (t)
ret |= add_scalar_value_to_lattice (dest_lat, t, cs, src_val, src_idx); ret |= dest_lat->add_value (t, cs, src_val, src_idx);
else else
ret |= set_lattice_contains_variable (dest_lat); ret |= dest_lat->set_contains_variable ();
} }
return ret; return ret;
...@@ -1114,7 +1166,7 @@ propagate_vals_accross_ancestor (struct cgraph_edge *cs, ...@@ -1114,7 +1166,7 @@ propagate_vals_accross_ancestor (struct cgraph_edge *cs,
static bool static bool
propagate_scalar_accross_jump_function (struct cgraph_edge *cs, propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
struct ipa_jump_func *jfunc, struct ipa_jump_func *jfunc,
struct ipcp_lattice *dest_lat) ipcp_lattice<tree> *dest_lat)
{ {
if (dest_lat->bottom) if (dest_lat->bottom)
return false; return false;
...@@ -1128,17 +1180,17 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs, ...@@ -1128,17 +1180,17 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
{ {
val = ipa_binfo_from_known_type_jfunc (jfunc); val = ipa_binfo_from_known_type_jfunc (jfunc);
if (!val) if (!val)
return set_lattice_contains_variable (dest_lat); return dest_lat->set_contains_variable ();
} }
else else
val = ipa_get_jf_constant (jfunc); val = ipa_get_jf_constant (jfunc);
return add_scalar_value_to_lattice (dest_lat, val, cs, NULL, 0); return dest_lat->add_value (val, cs, NULL, 0);
} }
else if (jfunc->type == IPA_JF_PASS_THROUGH else if (jfunc->type == IPA_JF_PASS_THROUGH
|| jfunc->type == IPA_JF_ANCESTOR) || jfunc->type == IPA_JF_ANCESTOR)
{ {
struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
struct ipcp_lattice *src_lat; ipcp_lattice<tree> *src_lat;
int src_idx; int src_idx;
bool ret; bool ret;
...@@ -1149,13 +1201,13 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs, ...@@ -1149,13 +1201,13 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
src_lat = ipa_get_scalar_lat (caller_info, src_idx); src_lat = ipa_get_scalar_lat (caller_info, src_idx);
if (src_lat->bottom) if (src_lat->bottom)
return set_lattice_contains_variable (dest_lat); return dest_lat->set_contains_variable ();
/* If we would need to clone the caller and cannot, do not propagate. */ /* If we would need to clone the caller and cannot, do not propagate. */
if (!ipcp_versionable_function_p (cs->caller) if (!ipcp_versionable_function_p (cs->caller)
&& (src_lat->contains_variable && (src_lat->contains_variable
|| (src_lat->values_count > 1))) || (src_lat->values_count > 1)))
return set_lattice_contains_variable (dest_lat); return dest_lat->set_contains_variable ();
if (jfunc->type == IPA_JF_PASS_THROUGH) if (jfunc->type == IPA_JF_PASS_THROUGH)
ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat, ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat,
...@@ -1165,14 +1217,14 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs, ...@@ -1165,14 +1217,14 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs,
src_idx); src_idx);
if (src_lat->contains_variable) if (src_lat->contains_variable)
ret |= set_lattice_contains_variable (dest_lat); ret |= dest_lat->set_contains_variable ();
return ret; return ret;
} }
/* TODO: We currently do not handle member method pointers in IPA-CP (we only /* TODO: We currently do not handle member method pointers in IPA-CP (we only
use it for indirect inlining), we should propagate them too. */ use it for indirect inlining), we should propagate them too. */
return set_lattice_contains_variable (dest_lat); return dest_lat->set_contains_variable ();
} }
/* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches
...@@ -1222,7 +1274,7 @@ merge_agg_lats_step (struct ipcp_param_lattices *dest_plats, ...@@ -1222,7 +1274,7 @@ merge_agg_lats_step (struct ipcp_param_lattices *dest_plats,
set_agg_lats_to_bottom (dest_plats); set_agg_lats_to_bottom (dest_plats);
return false; return false;
} }
*change |= set_lattice_contains_variable (**aglat); *change |= (**aglat)->set_contains_variable ();
*aglat = &(**aglat)->next; *aglat = &(**aglat)->next;
} }
...@@ -1273,7 +1325,7 @@ set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat) ...@@ -1273,7 +1325,7 @@ set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat)
bool ret = false; bool ret = false;
while (aglat) while (aglat)
{ {
ret |= set_lattice_contains_variable (aglat); ret |= aglat->set_contains_variable ();
aglat = aglat->next; aglat = aglat->next;
} }
return ret; return ret;
...@@ -1318,16 +1370,16 @@ merge_aggregate_lattices (struct cgraph_edge *cs, ...@@ -1318,16 +1370,16 @@ merge_aggregate_lattices (struct cgraph_edge *cs,
dst_aglat = &(*dst_aglat)->next; dst_aglat = &(*dst_aglat)->next;
if (src_aglat->bottom) if (src_aglat->bottom)
{ {
ret |= set_lattice_contains_variable (new_al); ret |= new_al->set_contains_variable ();
continue; continue;
} }
if (src_aglat->contains_variable) if (src_aglat->contains_variable)
ret |= set_lattice_contains_variable (new_al); ret |= new_al->set_contains_variable ();
for (struct ipcp_value *val = src_aglat->values; for (ipcp_value<tree> *val = src_aglat->values;
val; val;
val = val->next) val = val->next)
ret |= add_value_to_lattice (new_al, val->value, cs, val, src_idx, ret |= new_al->add_value (val->value, cs, val, src_idx,
src_aglat->offset); src_aglat->offset);
} }
else if (dest_plats->aggs_bottom) else if (dest_plats->aggs_bottom)
return true; return true;
...@@ -1424,7 +1476,7 @@ propagate_aggs_accross_jump_function (struct cgraph_edge *cs, ...@@ -1424,7 +1476,7 @@ propagate_aggs_accross_jump_function (struct cgraph_edge *cs,
if (merge_agg_lats_step (dest_plats, item->offset, val_size, if (merge_agg_lats_step (dest_plats, item->offset, val_size,
&aglat, pre_existing, &ret)) &aglat, pre_existing, &ret))
{ {
ret |= add_value_to_lattice (*aglat, item->value, cs, NULL, 0, 0); ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0);
aglat = &(*aglat)->next; aglat = &(*aglat)->next;
} }
else if (dest_plats->aggs_bottom) else if (dest_plats->aggs_bottom)
...@@ -1828,7 +1880,7 @@ context_independent_aggregate_values (struct ipcp_param_lattices *plats) ...@@ -1828,7 +1880,7 @@ context_independent_aggregate_values (struct ipcp_param_lattices *plats)
for (struct ipcp_agg_lattice *aglat = plats->aggs; for (struct ipcp_agg_lattice *aglat = plats->aggs;
aglat; aglat;
aglat = aglat->next) aglat = aglat->next)
if (ipa_lat_is_single_const (aglat)) if (aglat->is_single_const ())
{ {
struct ipa_agg_jf_item item; struct ipa_agg_jf_item item;
item.offset = aglat->offset; item.offset = aglat->offset;
...@@ -1869,11 +1921,11 @@ gather_context_independent_values (struct ipa_node_params *info, ...@@ -1869,11 +1921,11 @@ gather_context_independent_values (struct ipa_node_params *info,
for (i = 0; i < count ; i++) for (i = 0; i < count ; i++)
{ {
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
struct ipcp_lattice *lat = &plats->itself; ipcp_lattice<tree> *lat = &plats->itself;
if (ipa_lat_is_single_const (lat)) if (lat->is_single_const ())
{ {
struct ipcp_value *val = lat->values; ipcp_value<tree> *val = lat->values;
if (TREE_CODE (val->value) != TREE_BINFO) if (TREE_CODE (val->value) != TREE_BINFO)
{ {
(*known_csts)[i] = val->value; (*known_csts)[i] = val->value;
...@@ -1932,6 +1984,43 @@ agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs) ...@@ -1932,6 +1984,43 @@ agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs)
return ret; return ret;
} }
/* Perform time and size measurement of NODE with the context given in
KNOWN_CSTS, KNOWN_BINFOS and KNOWN_AGGS, calculate the benefit and cost
given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of
all context-independent removable parameters and EST_MOVE_COST of estimated
movement of the considered parameter and store it into VAL. */
static void
perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts,
vec<tree> known_binfos,
vec<ipa_agg_jump_function_p> known_aggs_ptrs,
int base_time, int removable_params_cost,
int est_move_cost, ipcp_value_base *val)
{
int time, size, time_benefit;
inline_hints hints;
estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos,
known_aggs_ptrs, &size, &time,
&hints);
time_benefit = base_time - time
+ devirtualization_time_bonus (node, known_csts, known_binfos,
known_aggs_ptrs)
+ hint_time_bonus (hints)
+ removable_params_cost + est_move_cost;
gcc_checking_assert (size >=0);
/* The inliner-heuristics based estimates may think that in certain
contexts some functions do not have any size at all but we want
all specializations to have at least a tiny cost, not least not to
divide by zero. */
if (size == 0)
size = 1;
val->local_time_benefit = time_benefit;
val->local_size_cost = size;
}
/* Iterate over known values of parameters of NODE and estimate the local /* Iterate over known values of parameters of NODE and estimate the local
effects in terms of time and size they have. */ effects in terms of time and size they have. */
...@@ -2013,8 +2102,8 @@ estimate_local_effects (struct cgraph_node *node) ...@@ -2013,8 +2102,8 @@ estimate_local_effects (struct cgraph_node *node)
for (i = 0; i < count ; i++) for (i = 0; i < count ; i++)
{ {
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
struct ipcp_lattice *lat = &plats->itself; ipcp_lattice<tree> *lat = &plats->itself;
struct ipcp_value *val; ipcp_value<tree> *val;
int emc; int emc;
if (lat->bottom if (lat->bottom
...@@ -2025,9 +2114,6 @@ estimate_local_effects (struct cgraph_node *node) ...@@ -2025,9 +2114,6 @@ estimate_local_effects (struct cgraph_node *node)
for (val = lat->values; val; val = val->next) for (val = lat->values; val; val = val->next)
{ {
int time, size, time_benefit;
inline_hints hints;
if (TREE_CODE (val->value) != TREE_BINFO) if (TREE_CODE (val->value) != TREE_BINFO)
{ {
known_csts[i] = val->value; known_csts[i] = val->value;
...@@ -2043,22 +2129,9 @@ estimate_local_effects (struct cgraph_node *node) ...@@ -2043,22 +2129,9 @@ estimate_local_effects (struct cgraph_node *node)
else else
continue; continue;
estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos, perform_estimation_of_a_value (node, known_csts, known_binfos,
known_aggs_ptrs, &size, &time, known_aggs_ptrs, base_time,
&hints); removable_params_cost, emc, val);
time_benefit = base_time - time
+ devirtualization_time_bonus (node, known_csts, known_binfos,
known_aggs_ptrs)
+ hint_time_bonus (hints)
+ removable_params_cost + emc;
gcc_checking_assert (size >=0);
/* The inliner-heuristics based estimates may think that in certain
contexts some functions do not have any size at all but we want
all specializations to have at least a tiny cost, not least not to
divide by zero. */
if (size == 0)
size = 1;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -2067,11 +2140,8 @@ estimate_local_effects (struct cgraph_node *node) ...@@ -2067,11 +2140,8 @@ estimate_local_effects (struct cgraph_node *node)
fprintf (dump_file, " for "); fprintf (dump_file, " for ");
ipa_dump_param (dump_file, info, i); ipa_dump_param (dump_file, info, i);
fprintf (dump_file, ": time_benefit: %i, size: %i\n", fprintf (dump_file, ": time_benefit: %i, size: %i\n",
time_benefit, size); val->local_time_benefit, val->local_size_cost);
} }
val->local_time_benefit = time_benefit;
val->local_size_cost = size;
} }
known_binfos[i] = NULL_TREE; known_binfos[i] = NULL_TREE;
known_csts[i] = NULL_TREE; known_csts[i] = NULL_TREE;
...@@ -2089,33 +2159,24 @@ estimate_local_effects (struct cgraph_node *node) ...@@ -2089,33 +2159,24 @@ estimate_local_effects (struct cgraph_node *node)
ajf = &known_aggs[i]; ajf = &known_aggs[i];
for (aglat = plats->aggs; aglat; aglat = aglat->next) for (aglat = plats->aggs; aglat; aglat = aglat->next)
{ {
struct ipcp_value *val; ipcp_value<tree> *val;
if (aglat->bottom || !aglat->values if (aglat->bottom || !aglat->values
/* If the following is true, the one value is in known_aggs. */ /* If the following is true, the one value is in known_aggs. */
|| (!plats->aggs_contain_variable || (!plats->aggs_contain_variable
&& ipa_lat_is_single_const (aglat))) && aglat->is_single_const ()))
continue; continue;
for (val = aglat->values; val; val = val->next) for (val = aglat->values; val; val = val->next)
{ {
int time, size, time_benefit;
struct ipa_agg_jf_item item; struct ipa_agg_jf_item item;
inline_hints hints;
item.offset = aglat->offset; item.offset = aglat->offset;
item.value = val->value; item.value = val->value;
vec_safe_push (ajf->items, item); vec_safe_push (ajf->items, item);
estimate_ipcp_clone_size_and_time (node, known_csts, known_binfos, perform_estimation_of_a_value (node, known_csts, known_binfos,
known_aggs_ptrs, &size, &time, known_aggs_ptrs, base_time,
&hints); removable_params_cost, 0, val);
time_benefit = base_time - time
+ devirtualization_time_bonus (node, known_csts, known_binfos,
known_aggs_ptrs)
+ hint_time_bonus (hints);
gcc_checking_assert (size >=0);
if (size == 0)
size = 1;
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -2124,13 +2185,12 @@ estimate_local_effects (struct cgraph_node *node) ...@@ -2124,13 +2185,12 @@ estimate_local_effects (struct cgraph_node *node)
fprintf (dump_file, " for "); fprintf (dump_file, " for ");
ipa_dump_param (dump_file, info, i); ipa_dump_param (dump_file, info, i);
fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC
"]: time_benefit: %i, size: %i\n", "]: time_benefit: %i, size: %i\n",
plats->aggs_by_ref ? "ref " : "", plats->aggs_by_ref ? "ref " : "",
aglat->offset, time_benefit, size); aglat->offset,
val->local_time_benefit, val->local_size_cost);
} }
val->local_time_benefit = time_benefit;
val->local_size_cost = size;
ajf->items->pop (); ajf->items->pop ();
} }
} }
...@@ -2149,12 +2209,11 @@ estimate_local_effects (struct cgraph_node *node) ...@@ -2149,12 +2209,11 @@ estimate_local_effects (struct cgraph_node *node)
/* Add value CUR_VAL and all yet-unsorted values it is dependent on to the /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the
topological sort of values. */ topological sort of values. */
static void template <typename valtype>
add_val_to_toposort (struct ipcp_value *cur_val) void
value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val)
{ {
static int dfs_counter = 0; ipcp_value_source<valtype> *src;
static struct ipcp_value *stack;
struct ipcp_value_source *src;
if (cur_val->dfs) if (cur_val->dfs)
return; return;
...@@ -2172,7 +2231,7 @@ add_val_to_toposort (struct ipcp_value *cur_val) ...@@ -2172,7 +2231,7 @@ add_val_to_toposort (struct ipcp_value *cur_val)
{ {
if (src->val->dfs == 0) if (src->val->dfs == 0)
{ {
add_val_to_toposort (src->val); add_val (src->val);
if (src->val->low_link < cur_val->low_link) if (src->val->low_link < cur_val->low_link)
cur_val->low_link = src->val->low_link; cur_val->low_link = src->val->low_link;
} }
...@@ -2183,7 +2242,7 @@ add_val_to_toposort (struct ipcp_value *cur_val) ...@@ -2183,7 +2242,7 @@ add_val_to_toposort (struct ipcp_value *cur_val)
if (cur_val->dfs == cur_val->low_link) if (cur_val->dfs == cur_val->low_link)
{ {
struct ipcp_value *v, *scc_list = NULL; ipcp_value<valtype> *v, *scc_list = NULL;
do do
{ {
...@@ -2205,7 +2264,7 @@ add_val_to_toposort (struct ipcp_value *cur_val) ...@@ -2205,7 +2264,7 @@ add_val_to_toposort (struct ipcp_value *cur_val)
they are not there yet. */ they are not there yet. */
static void static void
add_all_node_vals_to_toposort (struct cgraph_node *node) add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo)
{ {
struct ipa_node_params *info = IPA_NODE_REF (node); struct ipa_node_params *info = IPA_NODE_REF (node);
int i, count = ipa_get_param_count (info); int i, count = ipa_get_param_count (info);
...@@ -2213,19 +2272,19 @@ add_all_node_vals_to_toposort (struct cgraph_node *node) ...@@ -2213,19 +2272,19 @@ add_all_node_vals_to_toposort (struct cgraph_node *node)
for (i = 0; i < count ; i++) for (i = 0; i < count ; i++)
{ {
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
struct ipcp_lattice *lat = &plats->itself; ipcp_lattice<tree> *lat = &plats->itself;
struct ipcp_agg_lattice *aglat; struct ipcp_agg_lattice *aglat;
struct ipcp_value *val; ipcp_value<tree> *val;
if (!lat->bottom) if (!lat->bottom)
for (val = lat->values; val; val = val->next) for (val = lat->values; val; val = val->next)
add_val_to_toposort (val); topo->constants.add_val (val);
if (!plats->aggs_bottom) if (!plats->aggs_bottom)
for (aglat = plats->aggs; aglat; aglat = aglat->next) for (aglat = plats->aggs; aglat; aglat = aglat->next)
if (!aglat->bottom) if (!aglat->bottom)
for (val = aglat->values; val; val = val->next) for (val = aglat->values; val; val = val->next)
add_val_to_toposort (val); topo->constants.add_val (val);
} }
} }
...@@ -2271,7 +2330,7 @@ propagate_constants_topo (struct ipa_topo_info *topo) ...@@ -2271,7 +2330,7 @@ propagate_constants_topo (struct ipa_topo_info *topo)
struct cgraph_edge *cs; struct cgraph_edge *cs;
estimate_local_effects (v); estimate_local_effects (v);
add_all_node_vals_to_toposort (v); add_all_node_vals_to_toposort (v, topo);
for (cs = v->callees; cs; cs = cs->next_callee) for (cs = v->callees; cs; cs = cs->next_callee)
if (!ipa_edge_within_scc (cs)) if (!ipa_edge_within_scc (cs))
propagate_constants_accross_call (cs); propagate_constants_accross_call (cs);
...@@ -2297,15 +2356,16 @@ safe_add (int a, int b) ...@@ -2297,15 +2356,16 @@ safe_add (int a, int b)
/* Propagate the estimated effects of individual values along the topological /* Propagate the estimated effects of individual values along the topological
from the dependent values to those they depend on. */ from the dependent values to those they depend on. */
static void template <typename valtype>
propagate_effects (void) void
value_topo_info<valtype>::propagate_effects ()
{ {
struct ipcp_value *base; ipcp_value<valtype> *base;
for (base = values_topo; base; base = base->topo_next) for (base = values_topo; base; base = base->topo_next)
{ {
struct ipcp_value_source *src; ipcp_value_source<valtype> *src;
struct ipcp_value *val; ipcp_value<valtype> *val;
int time = 0, size = 0; int time = 0, size = 0;
for (val = base; val; val = val->scc_next) for (val = base; val; val = val->scc_next)
...@@ -2374,7 +2434,7 @@ ipcp_propagate_stage (struct ipa_topo_info *topo) ...@@ -2374,7 +2434,7 @@ ipcp_propagate_stage (struct ipa_topo_info *topo)
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
ipcp_verify_propagated_values (); ipcp_verify_propagated_values ();
#endif #endif
propagate_effects (); topo->constants.propagate_effects ();
if (dump_file) if (dump_file)
{ {
...@@ -2513,7 +2573,7 @@ get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset, ...@@ -2513,7 +2573,7 @@ get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset,
static bool static bool
cgraph_edge_brings_value_p (struct cgraph_edge *cs, cgraph_edge_brings_value_p (struct cgraph_edge *cs,
struct ipcp_value_source *src) ipcp_value_source<tree> *src)
{ {
struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
cgraph_node *real_dest = cs->callee->function_symbol (); cgraph_node *real_dest = cs->callee->function_symbol ();
...@@ -2541,7 +2601,7 @@ cgraph_edge_brings_value_p (struct cgraph_edge *cs, ...@@ -2541,7 +2601,7 @@ cgraph_edge_brings_value_p (struct cgraph_edge *cs,
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info,
src->index); src->index);
if (src->offset == -1) if (src->offset == -1)
return (ipa_lat_is_single_const (&plats->itself) return (plats->itself.is_single_const ()
&& values_equal_for_ipcp_p (src->val->value, && values_equal_for_ipcp_p (src->val->value,
plats->itself.values->value)); plats->itself.values->value));
else else
...@@ -2550,7 +2610,7 @@ cgraph_edge_brings_value_p (struct cgraph_edge *cs, ...@@ -2550,7 +2610,7 @@ cgraph_edge_brings_value_p (struct cgraph_edge *cs,
return false; return false;
for (aglat = plats->aggs; aglat; aglat = aglat->next) for (aglat = plats->aggs; aglat; aglat = aglat->next)
if (aglat->offset == src->offset) if (aglat->offset == src->offset)
return (ipa_lat_is_single_const (aglat) return (aglat->is_single_const ()
&& values_equal_for_ipcp_p (src->val->value, && values_equal_for_ipcp_p (src->val->value,
aglat->values->value)); aglat->values->value));
} }
...@@ -2570,11 +2630,12 @@ get_next_cgraph_edge_clone (struct cgraph_edge *cs) ...@@ -2570,11 +2630,12 @@ get_next_cgraph_edge_clone (struct cgraph_edge *cs)
edge frequency and their number into *FREQUENCY and *CALLER_COUNT edge frequency and their number into *FREQUENCY and *CALLER_COUNT
respectively. */ respectively. */
template <typename valtype>
static bool static bool
get_info_about_necessary_edges (struct ipcp_value *val, int *freq_sum, get_info_about_necessary_edges (ipcp_value<valtype> *val, int *freq_sum,
gcov_type *count_sum, int *caller_count) gcov_type *count_sum, int *caller_count)
{ {
struct ipcp_value_source *src; ipcp_value_source<valtype> *src;
int freq = 0, count = 0; int freq = 0, count = 0;
gcov_type cnt = 0; gcov_type cnt = 0;
bool hot = false; bool hot = false;
...@@ -2604,10 +2665,11 @@ get_info_about_necessary_edges (struct ipcp_value *val, int *freq_sum, ...@@ -2604,10 +2665,11 @@ get_info_about_necessary_edges (struct ipcp_value *val, int *freq_sum,
/* Return a vector of incoming edges that do bring value VAL. It is assumed /* Return a vector of incoming edges that do bring value VAL. It is assumed
their number is known and equal to CALLER_COUNT. */ their number is known and equal to CALLER_COUNT. */
template <typename valtype>
static vec<cgraph_edge *> static vec<cgraph_edge *>
gather_edges_for_value (struct ipcp_value *val, int caller_count) gather_edges_for_value (ipcp_value<valtype> *val, int caller_count)
{ {
struct ipcp_value_source *src; ipcp_value_source<valtype> *src;
vec<cgraph_edge *> ret; vec<cgraph_edge *> ret;
ret.create (caller_count); ret.create (caller_count);
...@@ -2932,7 +2994,7 @@ copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset) ...@@ -2932,7 +2994,7 @@ copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset)
return vNULL; return vNULL;
for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next) for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next)
if (ipa_lat_is_single_const (aglat)) if (aglat->is_single_const ())
{ {
struct ipa_agg_jf_item ti; struct ipa_agg_jf_item ti;
ti.offset = aglat->offset - offset; ti.offset = aglat->offset - offset;
...@@ -3385,10 +3447,11 @@ cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, ...@@ -3385,10 +3447,11 @@ cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
all other criteria such that they can be redirected the the special node. all other criteria such that they can be redirected the the special node.
This function can therefore redirect the final edge in a SCC. */ This function can therefore redirect the final edge in a SCC. */
template <typename valtype>
static void static void
perhaps_add_new_callers (struct cgraph_node *node, struct ipcp_value *val) perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val)
{ {
struct ipcp_value_source *src; ipcp_value_source<valtype> *src;
gcov_type redirected_sum = 0; gcov_type redirected_sum = 0;
for (src = val->sources; src; src = src->next) for (src = val->sources; src; src = src->next)
...@@ -3464,9 +3527,10 @@ ipcp_val_in_agg_replacements_p (struct ipa_agg_replacement_value *aggvals, ...@@ -3464,9 +3527,10 @@ ipcp_val_in_agg_replacements_p (struct ipa_agg_replacement_value *aggvals,
otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS, otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS,
KNOWN_BINFOS and KNOWN_AGGS describe the other already known values. */ KNOWN_BINFOS and KNOWN_AGGS describe the other already known values. */
template <typename valtype>
static bool static bool
decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset,
struct ipcp_value *val, vec<tree> known_csts, ipcp_value<valtype> *val, vec<tree> known_csts,
vec<tree> known_binfos) vec<tree> known_binfos)
{ {
struct ipa_agg_replacement_value *aggvals; struct ipa_agg_replacement_value *aggvals;
...@@ -3562,8 +3626,8 @@ decide_whether_version_node (struct cgraph_node *node) ...@@ -3562,8 +3626,8 @@ decide_whether_version_node (struct cgraph_node *node)
for (i = 0; i < count ;i++) for (i = 0; i < count ;i++)
{ {
struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i);
struct ipcp_lattice *lat = &plats->itself; ipcp_lattice<tree> *lat = &plats->itself;
struct ipcp_value *val; ipcp_value<tree> *val;
if (!lat->bottom if (!lat->bottom
&& !known_csts[i] && !known_csts[i]
...@@ -3575,13 +3639,13 @@ decide_whether_version_node (struct cgraph_node *node) ...@@ -3575,13 +3639,13 @@ decide_whether_version_node (struct cgraph_node *node)
if (!plats->aggs_bottom) if (!plats->aggs_bottom)
{ {
struct ipcp_agg_lattice *aglat; struct ipcp_agg_lattice *aglat;
struct ipcp_value *val; ipcp_value<tree> *val;
for (aglat = plats->aggs; aglat; aglat = aglat->next) for (aglat = plats->aggs; aglat; aglat = aglat->next)
if (!aglat->bottom && aglat->values if (!aglat->bottom && aglat->values
/* If the following is false, the one value is in /* If the following is false, the one value is in
known_aggs. */ known_aggs. */
&& (plats->aggs_contain_variable && (plats->aggs_contain_variable
|| !ipa_lat_is_single_const (aglat))) || !aglat->is_single_const ()))
for (val = aglat->values; val; val = val->next) for (val = aglat->values; val; val = val->next)
ret |= decide_about_value (node, i, aglat->offset, val, ret |= decide_about_value (node, i, aglat->offset, val,
known_csts, known_binfos); known_csts, known_binfos);
...@@ -3740,9 +3804,9 @@ ipcp_driver (void) ...@@ -3740,9 +3804,9 @@ ipcp_driver (void)
symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL); symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL);
ipcp_values_pool = create_alloc_pool ("IPA-CP values", ipcp_values_pool = create_alloc_pool ("IPA-CP values",
sizeof (struct ipcp_value), 32); sizeof (ipcp_value<tree>), 32);
ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources", ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources",
sizeof (struct ipcp_value_source), 64); sizeof (ipcp_value_source<tree>), 64);
ipcp_agg_lattice_pool = create_alloc_pool ("IPA_CP aggregate lattices", ipcp_agg_lattice_pool = create_alloc_pool ("IPA_CP aggregate lattices",
sizeof (struct ipcp_agg_lattice), sizeof (struct ipcp_agg_lattice),
32); 32);
...@@ -3871,5 +3935,4 @@ ipa_cp_c_finalize (void) ...@@ -3871,5 +3935,4 @@ ipa_cp_c_finalize (void)
max_count = 0; max_count = 0;
overall_size = 0; overall_size = 0;
max_new_size = 0; max_new_size = 0;
values_topo = NULL;
} }
...@@ -348,8 +348,6 @@ struct ipa_param_descriptor ...@@ -348,8 +348,6 @@ struct ipa_param_descriptor
unsigned used : 1; unsigned used : 1;
}; };
struct ipcp_lattice;
/* ipa_node_params stores information related to formal parameters of functions /* ipa_node_params stores information related to formal parameters of functions
and some other information for interprocedural passes that operate on and some other information for interprocedural passes that operate on
parameters (such as ipa-cp). */ parameters (such as ipa-cp). */
......
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