From: Martin Jambor Date: Fri, 14 Nov 2014 19:58:18 +0000 (+0100) Subject: ipa-cp.c (ipcp_value_source): Converted to a template class. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c0cb50559966b5215b3b2901fed2d672f6594b5f;p=gcc.git ipa-cp.c (ipcp_value_source): Converted to a template class. 2014-11-14 Martin Jambor * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 96e67e0e05c..421a8bcc33d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,42 @@ +2014-11-14 Martin Jambor + + * 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 * doc/install.texi (--with-diagnostics-color=): Document. diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 47f9f5cea09..e0acfaa82b0 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -134,61 +134,73 @@ along with GCC; see the file COPYING3. If not see #include "ipa-inline.h" #include "ipa-utils.h" -struct ipcp_value; +template class ipcp_value; /* Describes a particular source for an IPA-CP value. */ -struct ipcp_value_source +template +class ipcp_value_source { +public: /* Aggregate offset of the source, negative if the source is scalar value of the argument itself. */ HOST_WIDE_INT offset; /* 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 ancestor, this is the ipcp_value of the caller from which the described value has been derived. Otherwise it is NULL. */ - struct ipcp_value *val; + ipcp_value *val; /* 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 ancestor, this is the index of the parameter of the caller the jump function references. */ 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. */ -struct ipcp_value +template +class ipcp_value : public ipcp_value_base { - /* The actual value for the given parameter. This is either an IPA invariant - or a TREE_BINFO describing a type that can be used for - devirtualization. */ - tree value; +public: + /* The actual value for the given parameter. */ + valtype value; /* The list of sources from which this value originates. */ - struct ipcp_value_source *sources; + ipcp_value_source *sources; /* 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 of values. */ - struct ipcp_value *scc_next; + ipcp_value *scc_next; /* Next pointers in a linked list of SCCs of values sorted topologically 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) created. */ - struct cgraph_node *spec_node; + cgraph_node *spec_node; /* Depth first search number and low link for topological sorting of values. */ 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. */ 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 @@ -197,12 +209,14 @@ struct ipcp_value by a lattice with the bottom flag set. In that case, values and contains_variable flag should be disregarded. */ -struct ipcp_lattice +template +class ipcp_lattice { +public: /* 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 sources referencing them. */ - struct ipcp_value *values; + ipcp_value *values; /* Number of known values and types in this lattice. */ int values_count; /* The lattice contains a variable component (in addition to values). */ @@ -210,12 +224,22 @@ struct ipcp_lattice /* The value of the lattice is bottom (i.e. variable and unusable for any propagation). */ 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 *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 { +public: /* Offset that is being described by this lattice. */ HOST_WIDE_INT offset; /* 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 aggregates that are passed in the parameter or by a reference in a parameter plus some other useful flags. */ -struct ipcp_param_lattices +class ipcp_param_lattices { +public: /* Lattice describing the value of the parameter itself. */ - struct ipcp_lattice itself; + ipcp_lattice itself; /* Lattices describing aggregate parts. */ - struct ipcp_agg_lattice *aggs; + ipcp_agg_lattice *aggs; /* Number of aggregate lattices */ int aggs_count; /* True if aggregate data were passed by reference (as opposed to by @@ -265,10 +290,6 @@ static gcov_type max_count; 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 parameter of the function described by INFO. */ static inline struct ipcp_param_lattices * @@ -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 parameter of the function described by INFO. */ -static inline struct ipcp_lattice * +static inline ipcp_lattice * ipa_get_scalar_lat (struct ipa_node_params *info, int 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) /* Return whether LAT is a lattice with a single constant and without an undefined value. */ -static inline bool -ipa_lat_is_single_const (struct ipcp_lattice *lat) +template +inline bool +ipcp_lattice::is_single_const () { - if (lat->bottom - || lat->contains_variable - || lat->values_count != 1) + if (bottom || contains_variable || values_count != 1) return false; else return true; @@ -325,26 +345,26 @@ print_ipcp_constant_value (FILE * f, tree v) /* Print a lattice LAT to F. */ -static void -print_lattice (FILE * f, struct ipcp_lattice *lat, - bool dump_sources, bool dump_benefits) +template +void +ipcp_lattice::print (FILE * f, bool dump_sources, bool dump_benefits) { - struct ipcp_value *val; + ipcp_value *val; bool prev = false; - if (lat->bottom) + if (bottom) { fprintf (f, "BOTTOM\n"); return; } - if (!lat->values_count && !lat->contains_variable) + if (!values_count && !contains_variable) { fprintf (f, "TOP\n"); return; } - if (lat->contains_variable) + if (contains_variable) { fprintf (f, "VARIABLE"); prev = true; @@ -352,7 +372,7 @@ print_lattice (FILE * f, struct ipcp_lattice *lat, fprintf (f, "\n"); } - for (val = lat->values; val; val = val->next) + for (val = values; val; val = val->next) { if (dump_benefits && prev) fprintf (f, " "); @@ -365,7 +385,7 @@ print_lattice (FILE * f, struct ipcp_lattice *lat, if (dump_sources) { - struct ipcp_value_source *s; + ipcp_value_source *s; fprintf (f, " [from:"); for (s = val->sources; s; s = s->next) @@ -406,7 +426,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) struct ipcp_agg_lattice *aglat; struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, 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) fprintf (f, " virt_call flag set\n"); @@ -422,7 +442,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) { fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ", 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) return true; } +template +class value_topo_info +{ +public: + /* Head of the linked list of topologically sorted values. */ + ipcp_value *values_topo; + /* Stack for creating SCCs, represented by a linked list too. */ + ipcp_value *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 *cur_val); + void propagate_effects (); +}; + /* 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; + /* Stack of cgraph nodes used during propagation within SCC until all values + in the SCC stabilize. */ struct cgraph_node **stack; int nnodes, stack_top; + + value_topo_info 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. */ @@ -604,7 +653,7 @@ build_toporder_info (struct ipa_topo_info *topo) topo->order = 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); } @@ -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 such. */ -static inline bool -set_lattice_to_bottom (struct ipcp_lattice *lat) +template +inline bool +ipcp_lattice::set_to_bottom () { - bool ret = !lat->bottom; - lat->bottom = true; + bool ret = !bottom; + bottom = true; return ret; } /* Mark lattice as containing an unknown value and return true if it previously was not marked as such. */ -static inline bool -set_lattice_contains_variable (struct ipcp_lattice *lat) +template +inline bool +ipcp_lattice::set_contains_variable () { - bool ret = !lat->contains_variable; - lat->contains_variable = true; + bool ret = !contains_variable; + contains_variable = true; return ret; } @@ -735,7 +786,7 @@ initialize_node_lattices (struct cgraph_node *node) struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); if (disable) { - set_lattice_to_bottom (&plats->itself); + plats->itself.set_to_bottom (); set_agg_lats_to_bottom (plats); } else @@ -864,7 +915,7 @@ ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc) input = info->known_vals[idx]; else { - struct ipcp_lattice *lat; + ipcp_lattice *lat; if (!info->lattices) { @@ -872,7 +923,7 @@ ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc) return NULL_TREE; } lat = ipa_get_scalar_lat (info, idx); - if (!ipa_lat_is_single_const (lat)) + if (!lat->is_single_const ()) return NULL_TREE; input = lat->values->value; } @@ -906,7 +957,7 @@ ipcp_verify_propagated_values (void) for (i = 0; i < count; i++) { - struct ipcp_lattice *lat = ipa_get_scalar_lat (info, i); + ipcp_lattice *lat = ipa_get_scalar_lat (info, i); if (!lat->bottom && !lat->contains_variable @@ -949,48 +1000,65 @@ values_equal_for_ipcp_p (tree x, tree y) return operand_equal_p (x, y, 0); } -/* Add a new value source to VAL, marking that a value comes from edge CS and - (if the underlying jump function is a pass-through or an ancestor one) from - a caller value SRC_VAL of a caller parameter described by SRC_INDEX. OFFSET - is negative if the source was the scalar value of the parameter itself or - the offset within an aggregate. */ +/* Add a new value source to the value represented by THIS, marking that a + value comes from edge CS and (if the underlying jump function is a + pass-through or an ancestor one) from a caller value SRC_VAL of a caller + parameter described by SRC_INDEX. OFFSET is negative if the source was the + scalar value of the parameter itself or the offset within an aggregate. */ -static void -add_value_source (struct ipcp_value *val, struct cgraph_edge *cs, - struct ipcp_value *src_val, int src_idx, HOST_WIDE_INT offset) +template +void +ipcp_value::add_source (cgraph_edge *cs, ipcp_value *src_val, + int src_idx, HOST_WIDE_INT offset) { - struct ipcp_value_source *src; + ipcp_value_source *src; - src = (struct ipcp_value_source *) pool_alloc (ipcp_sources_pool); + src = new (pool_alloc (ipcp_sources_pool)) ipcp_value_source; src->offset = offset; src->cs = cs; src->val = src_val; src->index = src_idx; - src->next = val->sources; - val->sources = src; + src->next = sources; + sources = src; } -/* Try to add NEWVAL to LAT, potentially creating a new struct ipcp_value for - it. CS, SRC_VAL SRC_INDEX and OFFSET are meant for add_value_source and - have the same meaning. */ +/* Allocate a new ipcp_value holding a tree constant, initialize its value to + SOURCE and clear all other fields. */ -static bool -add_value_to_lattice (struct ipcp_lattice *lat, tree newval, - struct cgraph_edge *cs, struct ipcp_value *src_val, - int src_idx, HOST_WIDE_INT offset) +static ipcp_value * +allocate_and_init_ipcp_value (tree source) { - struct ipcp_value *val; + ipcp_value *val; - if (lat->bottom) + val = new (pool_alloc (ipcp_values_pool)) ipcp_value; + 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 +bool +ipcp_lattice::add_value (valtype newval, cgraph_edge *cs, + ipcp_value *src_val, + int src_idx, HOST_WIDE_INT offset) +{ + ipcp_value *val; + + if (bottom) 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 (ipa_edge_within_scc (cs)) { - struct ipcp_value_source *s; + ipcp_value_source *s; for (s = val->sources; s ; s = s->next) if (s->cs == cs) break; @@ -998,63 +1066,48 @@ add_value_to_lattice (struct ipcp_lattice *lat, tree newval, return false; } - add_value_source (val, cs, src_val, src_idx, offset); + val->add_source (cs, src_val, src_idx, offset); 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 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) { - struct ipcp_value_source *src = val->sources; + ipcp_value_source *src = val->sources; val->sources = src->next; pool_free (ipcp_sources_pool, src); } } - lat->values = NULL; - return set_lattice_to_bottom (lat); + values = NULL; + return set_to_bottom (); } - lat->values_count++; - val = (struct ipcp_value *) pool_alloc (ipcp_values_pool); - memset (val, 0, sizeof (*val)); - - add_value_source (val, cs, src_val, src_idx, offset); - val->value = newval; - val->next = lat->values; - lat->values = val; + values_count++; + val = allocate_and_init_ipcp_value (newval); + val->add_source (cs, src_val, src_idx, offset); + val->next = values; + values = val; 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 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX is the index of the source parameter. */ static bool -propagate_vals_accross_pass_through (struct cgraph_edge *cs, - struct ipa_jump_func *jfunc, - struct ipcp_lattice *src_lat, - struct ipcp_lattice *dest_lat, +propagate_vals_accross_pass_through (cgraph_edge *cs, + ipa_jump_func *jfunc, + ipcp_lattice *src_lat, + ipcp_lattice *dest_lat, int src_idx) { - struct ipcp_value *src_val; + ipcp_value *src_val; bool ret = false; /* 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, number of them and we would just make lattices bottom. */ if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) && ipa_edge_within_scc (cs)) - ret = set_lattice_contains_variable (dest_lat); + ret = dest_lat->set_contains_variable (); else for (src_val = src_lat->values; src_val; src_val = src_val->next) { tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value); if (cstval) - ret |= add_scalar_value_to_lattice (dest_lat, cstval, cs, src_val, - src_idx); + ret |= dest_lat->add_value (cstval, cs, src_val, src_idx); else - ret |= set_lattice_contains_variable (dest_lat); + ret |= dest_lat->set_contains_variable (); } return ret; @@ -1085,24 +1137,24 @@ propagate_vals_accross_pass_through (struct cgraph_edge *cs, static bool propagate_vals_accross_ancestor (struct cgraph_edge *cs, struct ipa_jump_func *jfunc, - struct ipcp_lattice *src_lat, - struct ipcp_lattice *dest_lat, + ipcp_lattice *src_lat, + ipcp_lattice *dest_lat, int src_idx) { - struct ipcp_value *src_val; + ipcp_value *src_val; bool ret = false; 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) { tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value); 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 - ret |= set_lattice_contains_variable (dest_lat); + ret |= dest_lat->set_contains_variable (); } return ret; @@ -1114,7 +1166,7 @@ propagate_vals_accross_ancestor (struct cgraph_edge *cs, static bool propagate_scalar_accross_jump_function (struct cgraph_edge *cs, struct ipa_jump_func *jfunc, - struct ipcp_lattice *dest_lat) + ipcp_lattice *dest_lat) { if (dest_lat->bottom) return false; @@ -1128,17 +1180,17 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs, { val = ipa_binfo_from_known_type_jfunc (jfunc); if (!val) - return set_lattice_contains_variable (dest_lat); + return dest_lat->set_contains_variable (); } else 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 || jfunc->type == IPA_JF_ANCESTOR) { struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); - struct ipcp_lattice *src_lat; + ipcp_lattice *src_lat; int src_idx; bool ret; @@ -1149,13 +1201,13 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs, src_lat = ipa_get_scalar_lat (caller_info, src_idx); 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 (!ipcp_versionable_function_p (cs->caller) && (src_lat->contains_variable || (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) ret = propagate_vals_accross_pass_through (cs, jfunc, src_lat, @@ -1165,14 +1217,14 @@ propagate_scalar_accross_jump_function (struct cgraph_edge *cs, src_idx); if (src_lat->contains_variable) - ret |= set_lattice_contains_variable (dest_lat); + ret |= dest_lat->set_contains_variable (); return ret; } /* TODO: We currently do not handle member method pointers in IPA-CP (we only 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 @@ -1222,7 +1274,7 @@ merge_agg_lats_step (struct ipcp_param_lattices *dest_plats, set_agg_lats_to_bottom (dest_plats); return false; } - *change |= set_lattice_contains_variable (**aglat); + *change |= (**aglat)->set_contains_variable (); *aglat = &(**aglat)->next; } @@ -1273,7 +1325,7 @@ set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat) bool ret = false; while (aglat) { - ret |= set_lattice_contains_variable (aglat); + ret |= aglat->set_contains_variable (); aglat = aglat->next; } return ret; @@ -1318,16 +1370,16 @@ merge_aggregate_lattices (struct cgraph_edge *cs, dst_aglat = &(*dst_aglat)->next; if (src_aglat->bottom) { - ret |= set_lattice_contains_variable (new_al); + ret |= new_al->set_contains_variable (); continue; } if (src_aglat->contains_variable) - ret |= set_lattice_contains_variable (new_al); - for (struct ipcp_value *val = src_aglat->values; + ret |= new_al->set_contains_variable (); + for (ipcp_value *val = src_aglat->values; val; val = val->next) - ret |= add_value_to_lattice (new_al, val->value, cs, val, src_idx, - src_aglat->offset); + ret |= new_al->add_value (val->value, cs, val, src_idx, + src_aglat->offset); } else if (dest_plats->aggs_bottom) return true; @@ -1424,7 +1476,7 @@ propagate_aggs_accross_jump_function (struct cgraph_edge *cs, if (merge_agg_lats_step (dest_plats, item->offset, val_size, &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; } else if (dest_plats->aggs_bottom) @@ -1828,7 +1880,7 @@ context_independent_aggregate_values (struct ipcp_param_lattices *plats) 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 item; item.offset = aglat->offset; @@ -1869,11 +1921,11 @@ gather_context_independent_values (struct ipa_node_params *info, for (i = 0; i < count ; i++) { struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); - struct ipcp_lattice *lat = &plats->itself; + ipcp_lattice *lat = &plats->itself; - if (ipa_lat_is_single_const (lat)) + if (lat->is_single_const ()) { - struct ipcp_value *val = lat->values; + ipcp_value *val = lat->values; if (TREE_CODE (val->value) != TREE_BINFO) { (*known_csts)[i] = val->value; @@ -1932,6 +1984,43 @@ agg_jmp_p_vec_for_t_vec (vec known_aggs) 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 known_csts, + vec known_binfos, + vec 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 effects in terms of time and size they have. */ @@ -2013,8 +2102,8 @@ estimate_local_effects (struct cgraph_node *node) for (i = 0; i < count ; i++) { struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); - struct ipcp_lattice *lat = &plats->itself; - struct ipcp_value *val; + ipcp_lattice *lat = &plats->itself; + ipcp_value *val; int emc; if (lat->bottom @@ -2025,9 +2114,6 @@ estimate_local_effects (struct cgraph_node *node) for (val = lat->values; val; val = val->next) { - int time, size, time_benefit; - inline_hints hints; - if (TREE_CODE (val->value) != TREE_BINFO) { known_csts[i] = val->value; @@ -2043,22 +2129,9 @@ estimate_local_effects (struct cgraph_node *node) else continue; - 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 + 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; + perform_estimation_of_a_value (node, known_csts, known_binfos, + known_aggs_ptrs, base_time, + removable_params_cost, emc, val); if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -2067,11 +2140,8 @@ estimate_local_effects (struct cgraph_node *node) fprintf (dump_file, " for "); ipa_dump_param (dump_file, info, i); 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_csts[i] = NULL_TREE; @@ -2089,33 +2159,24 @@ estimate_local_effects (struct cgraph_node *node) ajf = &known_aggs[i]; for (aglat = plats->aggs; aglat; aglat = aglat->next) { - struct ipcp_value *val; + ipcp_value *val; if (aglat->bottom || !aglat->values /* If the following is true, the one value is in known_aggs. */ || (!plats->aggs_contain_variable - && ipa_lat_is_single_const (aglat))) + && aglat->is_single_const ())) continue; for (val = aglat->values; val; val = val->next) { - int time, size, time_benefit; struct ipa_agg_jf_item item; - inline_hints hints; item.offset = aglat->offset; item.value = val->value; vec_safe_push (ajf->items, item); - 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); - gcc_checking_assert (size >=0); - if (size == 0) - size = 1; + perform_estimation_of_a_value (node, known_csts, known_binfos, + known_aggs_ptrs, base_time, + removable_params_cost, 0, val); if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -2124,13 +2185,12 @@ estimate_local_effects (struct cgraph_node *node) fprintf (dump_file, " for "); ipa_dump_param (dump_file, info, i); fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC - "]: time_benefit: %i, size: %i\n", - plats->aggs_by_ref ? "ref " : "", - aglat->offset, time_benefit, size); + "]: time_benefit: %i, size: %i\n", + plats->aggs_by_ref ? "ref " : "", + aglat->offset, + val->local_time_benefit, val->local_size_cost); } - val->local_time_benefit = time_benefit; - val->local_size_cost = size; ajf->items->pop (); } } @@ -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 topological sort of values. */ -static void -add_val_to_toposort (struct ipcp_value *cur_val) +template +void +value_topo_info::add_val (ipcp_value *cur_val) { - static int dfs_counter = 0; - static struct ipcp_value *stack; - struct ipcp_value_source *src; + ipcp_value_source *src; if (cur_val->dfs) return; @@ -2172,7 +2231,7 @@ add_val_to_toposort (struct ipcp_value *cur_val) { if (src->val->dfs == 0) { - add_val_to_toposort (src->val); + add_val (src->val); if (src->val->low_link < cur_val->low_link) cur_val->low_link = src->val->low_link; } @@ -2183,7 +2242,7 @@ add_val_to_toposort (struct ipcp_value *cur_val) if (cur_val->dfs == cur_val->low_link) { - struct ipcp_value *v, *scc_list = NULL; + ipcp_value *v, *scc_list = NULL; do { @@ -2205,7 +2264,7 @@ add_val_to_toposort (struct ipcp_value *cur_val) they are not there yet. */ 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); int i, count = ipa_get_param_count (info); @@ -2213,19 +2272,19 @@ add_all_node_vals_to_toposort (struct cgraph_node *node) for (i = 0; i < count ; i++) { struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); - struct ipcp_lattice *lat = &plats->itself; + ipcp_lattice *lat = &plats->itself; struct ipcp_agg_lattice *aglat; - struct ipcp_value *val; + ipcp_value *val; if (!lat->bottom) for (val = lat->values; val; val = val->next) - add_val_to_toposort (val); + topo->constants.add_val (val); if (!plats->aggs_bottom) for (aglat = plats->aggs; aglat; aglat = aglat->next) if (!aglat->bottom) 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) struct cgraph_edge *cs; 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) if (!ipa_edge_within_scc (cs)) propagate_constants_accross_call (cs); @@ -2297,15 +2356,16 @@ safe_add (int a, int b) /* Propagate the estimated effects of individual values along the topological from the dependent values to those they depend on. */ -static void -propagate_effects (void) +template +void +value_topo_info::propagate_effects () { - struct ipcp_value *base; + ipcp_value *base; for (base = values_topo; base; base = base->topo_next) { - struct ipcp_value_source *src; - struct ipcp_value *val; + ipcp_value_source *src; + ipcp_value *val; int time = 0, size = 0; for (val = base; val; val = val->scc_next) @@ -2374,7 +2434,7 @@ ipcp_propagate_stage (struct ipa_topo_info *topo) #ifdef ENABLE_CHECKING ipcp_verify_propagated_values (); #endif - propagate_effects (); + topo->constants.propagate_effects (); if (dump_file) { @@ -2513,7 +2573,7 @@ get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset, static bool cgraph_edge_brings_value_p (struct cgraph_edge *cs, - struct ipcp_value_source *src) + ipcp_value_source *src) { struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); cgraph_node *real_dest = cs->callee->function_symbol (); @@ -2541,7 +2601,7 @@ cgraph_edge_brings_value_p (struct cgraph_edge *cs, struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, src->index); 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, plats->itself.values->value)); else @@ -2550,7 +2610,7 @@ cgraph_edge_brings_value_p (struct cgraph_edge *cs, return false; for (aglat = plats->aggs; aglat; aglat = aglat->next) 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, aglat->values->value)); } @@ -2570,11 +2630,12 @@ get_next_cgraph_edge_clone (struct cgraph_edge *cs) edge frequency and their number into *FREQUENCY and *CALLER_COUNT respectively. */ +template static bool -get_info_about_necessary_edges (struct ipcp_value *val, int *freq_sum, +get_info_about_necessary_edges (ipcp_value *val, int *freq_sum, gcov_type *count_sum, int *caller_count) { - struct ipcp_value_source *src; + ipcp_value_source *src; int freq = 0, count = 0; gcov_type cnt = 0; bool hot = false; @@ -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 their number is known and equal to CALLER_COUNT. */ +template static vec -gather_edges_for_value (struct ipcp_value *val, int caller_count) +gather_edges_for_value (ipcp_value *val, int caller_count) { - struct ipcp_value_source *src; + ipcp_value_source *src; vec ret; ret.create (caller_count); @@ -2932,7 +2994,7 @@ copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset) return vNULL; 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; ti.offset = aglat->offset - offset; @@ -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. This function can therefore redirect the final edge in a SCC. */ +template static void -perhaps_add_new_callers (struct cgraph_node *node, struct ipcp_value *val) +perhaps_add_new_callers (cgraph_node *node, ipcp_value *val) { - struct ipcp_value_source *src; + ipcp_value_source *src; gcov_type redirected_sum = 0; for (src = val->sources; src; src = src->next) @@ -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, KNOWN_BINFOS and KNOWN_AGGS describe the other already known values. */ +template static bool decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, - struct ipcp_value *val, vec known_csts, + ipcp_value *val, vec known_csts, vec known_binfos) { struct ipa_agg_replacement_value *aggvals; @@ -3562,8 +3626,8 @@ decide_whether_version_node (struct cgraph_node *node) for (i = 0; i < count ;i++) { struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); - struct ipcp_lattice *lat = &plats->itself; - struct ipcp_value *val; + ipcp_lattice *lat = &plats->itself; + ipcp_value *val; if (!lat->bottom && !known_csts[i] @@ -3575,13 +3639,13 @@ decide_whether_version_node (struct cgraph_node *node) if (!plats->aggs_bottom) { struct ipcp_agg_lattice *aglat; - struct ipcp_value *val; + ipcp_value *val; for (aglat = plats->aggs; aglat; aglat = aglat->next) if (!aglat->bottom && aglat->values /* If the following is false, the one value is in known_aggs. */ && (plats->aggs_contain_variable - || !ipa_lat_is_single_const (aglat))) + || !aglat->is_single_const ())) for (val = aglat->values; val; val = val->next) ret |= decide_about_value (node, i, aglat->offset, val, known_csts, known_binfos); @@ -3740,9 +3804,9 @@ ipcp_driver (void) symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL); ipcp_values_pool = create_alloc_pool ("IPA-CP values", - sizeof (struct ipcp_value), 32); + sizeof (ipcp_value), 32); ipcp_sources_pool = create_alloc_pool ("IPA-CP value sources", - sizeof (struct ipcp_value_source), 64); + sizeof (ipcp_value_source), 64); ipcp_agg_lattice_pool = create_alloc_pool ("IPA_CP aggregate lattices", sizeof (struct ipcp_agg_lattice), 32); @@ -3871,5 +3935,4 @@ ipa_cp_c_finalize (void) max_count = 0; overall_size = 0; max_new_size = 0; - values_topo = NULL; } diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 165fc1a7f45..fdf48117734 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -348,8 +348,6 @@ struct ipa_param_descriptor unsigned used : 1; }; -struct ipcp_lattice; - /* ipa_node_params stores information related to formal parameters of functions and some other information for interprocedural passes that operate on parameters (such as ipa-cp). */