#include "cfgexpand.h"
#include "gimplify.h"
-/* Holders of ipa cgraph hooks: */
-static struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
-static struct cgraph_edge_hook_list *edge_removal_hook_holder;
-static void inline_edge_removal_hook (struct cgraph_edge *, void *);
-static void inline_edge_duplication_hook (struct cgraph_edge *,
- struct cgraph_edge *, void *);
-
-/* VECtor holding inline summaries.
- In GGC memory because conditions might point to constant trees. */
+/* Summaries. */
function_summary <inline_summary *> *inline_summaries;
-vec<inline_edge_summary_t> inline_edge_summary_vec;
+call_summary <ipa_call_summary *> *ipa_call_summaries;
/* Cached node/edge growths. */
vec<edge_growth_cache_entry> edge_growth_cache;
e->make_direct (target);
else
e->redirect_callee (target);
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
e->inline_failed = CIF_UNREACHABLE;
e->frequency = 0;
e->count = 0;
&& (!e->speculative || e->callee))
e = redirect_to_unreachable (e);
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
if (predicate && *predicate != true)
{
if (!es->predicate)
{
struct ipa_node_params *parms_info;
struct ipa_edge_args *args = IPA_EDGE_REF (e);
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
int i, count = ipa_get_cs_argument_count (args);
if (e->caller->global.inlined_to)
static void
inline_summary_alloc (void)
{
- if (!edge_removal_hook_holder)
- edge_removal_hook_holder =
- symtab->add_edge_removal_hook (&inline_edge_removal_hook, NULL);
- if (!edge_duplication_hook_holder)
- edge_duplication_hook_holder =
- symtab->add_edge_duplication_hook (&inline_edge_duplication_hook, NULL);
-
if (!inline_summaries)
- inline_summaries = (inline_summary_t*) inline_summary_t::create_ggc (symtab);
-
- if (inline_edge_summary_vec.length () <= (unsigned) symtab->edges_max_uid)
- inline_edge_summary_vec.safe_grow_cleared (symtab->edges_max_uid + 1);
+ inline_summaries = inline_summary_t::create_ggc (symtab);
+ if (!ipa_call_summaries)
+ ipa_call_summaries = new ipa_call_summary_t (symtab, false);
}
/* We are called multiple time for given function; clear
data from previous run so they are not cumulated. */
static void
-reset_inline_edge_summary (struct cgraph_edge *e)
+reset_ipa_call_summary (struct cgraph_edge *e)
{
- if (e->uid < (int) inline_edge_summary_vec.length ())
- {
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
- es->call_stmt_size = es->call_stmt_time = 0;
- if (es->predicate)
- edge_predicate_pool.remove (es->predicate);
- es->predicate = NULL;
- es->param.release ();
- }
+ es->call_stmt_size = es->call_stmt_time = 0;
+ if (es->predicate)
+ edge_predicate_pool.remove (es->predicate);
+ es->predicate = NULL;
+ es->param.release ();
}
/* We are called multiple time for given function; clear
vec_free (info->conds);
vec_free (info->entry);
for (e = node->callees; e; e = e->next_callee)
- reset_inline_edge_summary (e);
+ reset_ipa_call_summary (e);
for (e = node->indirect_calls; e; e = e->next_callee)
- reset_inline_edge_summary (e);
+ reset_ipa_call_summary (e);
info->fp_expressions = false;
}
for (edge = dst->callees; edge; edge = next)
{
predicate new_predicate;
- struct inline_edge_summary *es = inline_edge_summary (edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
next = edge->next_callee;
if (!edge->inline_failed)
for (edge = dst->indirect_calls; edge; edge = next)
{
predicate new_predicate;
- struct inline_edge_summary *es = inline_edge_summary (edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
next = edge->next_callee;
gcc_checking_assert (edge->inline_failed);
/* Hook that is called by cgraph.c when a node is duplicated. */
-static void
-inline_edge_duplication_hook (struct cgraph_edge *src,
- struct cgraph_edge *dst,
- ATTRIBUTE_UNUSED void *data)
+void
+ipa_call_summary_t::duplicate (struct cgraph_edge *src,
+ struct cgraph_edge *dst,
+ struct ipa_call_summary *srcinfo,
+ struct ipa_call_summary *info)
{
- struct inline_edge_summary *info;
- struct inline_edge_summary *srcinfo;
- inline_summary_alloc ();
- info = inline_edge_summary (dst);
- srcinfo = inline_edge_summary (src);
- memcpy (info, srcinfo, sizeof (struct inline_edge_summary));
+ *info = *srcinfo;
info->predicate = NULL;
edge_set_predicate (dst, srcinfo->predicate);
info->param = srcinfo->param.copy ();
/* Keep edge cache consistent across edge removal. */
-static void
-inline_edge_removal_hook (struct cgraph_edge *edge,
- void *data ATTRIBUTE_UNUSED)
+void
+ipa_call_summary_t::remove (struct cgraph_edge *edge,
+ struct ipa_call_summary *)
{
if (edge_growth_cache.exists ())
reset_edge_growth_cache (edge);
- reset_inline_edge_summary (edge);
+ reset_ipa_call_summary (edge);
}
Indent by INDENT. */
static void
-dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node,
- struct inline_summary *info)
+dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node,
+ struct inline_summary *info)
{
struct cgraph_edge *edge;
for (edge = node->callees; edge; edge = edge->next_callee)
{
- struct inline_edge_summary *es = inline_edge_summary (edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
struct cgraph_node *callee = edge->callee->ultimate_alias_target ();
int i;
(int) inline_summaries->get (callee)->stack_frame_offset,
(int) inline_summaries->get (callee)->estimated_self_stack_size,
(int) inline_summaries->get (callee)->estimated_stack_size);
- dump_inline_edge_summary (f, indent + 2, callee, info);
+ dump_ipa_call_summary (f, indent + 2, callee, info);
}
}
for (edge = node->indirect_calls; edge; edge = edge->next_callee)
{
- struct inline_edge_summary *es = inline_edge_summary (edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
fprintf (f, "%*sindirect call loop depth:%2i freq:%4i size:%2i"
" time: %2i",
indent, "",
s->array_index->dump (f, s->conds);
}
fprintf (f, " calls:\n");
- dump_inline_edge_summary (f, 4, node, s);
+ dump_ipa_call_summary (f, 4, node, s);
fprintf (f, "\n");
}
}
&& !gimple_call_internal_p (stmt))
{
struct cgraph_edge *edge = node->get_edge (stmt);
- struct inline_edge_summary *es = inline_edge_summary (edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
/* Special case: results of BUILT_IN_CONSTANT_P will be always
resolved as constant. We however don't want to optimize
if (node->thunk.thunk_p)
{
- struct inline_edge_summary *es = inline_edge_summary (node->callees);
+ struct ipa_call_summary *es = ipa_call_summaries->get (node->callees);
predicate t = true;
node->local.can_change_signature = false;
vec<ipa_agg_jump_function_p> known_aggs,
inline_hints *hints)
{
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
int call_size = es->call_stmt_size;
int call_time = es->call_stmt_time;
int cur_size;
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
{
- if (inline_edge_summary_vec.length () <= (unsigned) e->uid)
- continue;
-
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
/* Do not care about zero sized builtins. */
if (e->inline_failed && !es->call_stmt_size)
}
for (e = node->indirect_calls; e; e = e->next_callee)
{
- if (inline_edge_summary_vec.length () <= (unsigned) e->uid)
- continue;
-
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
if (!es->predicate
|| es->predicate->evaluate (possible_truths))
estimate_edge_size_and_time (e, size,
{
if (!e->inline_failed)
inline_update_callee_summaries (e->callee, depth);
- inline_edge_summary (e)->loop_depth += depth;
+ ipa_call_summaries->get (e)->loop_depth += depth;
}
for (e = node->indirect_calls; e; e = e->next_callee)
- inline_edge_summary (e)->loop_depth += depth;
+ ipa_call_summaries->get (e)->loop_depth += depth;
}
/* Update change_prob of EDGE after INLINED_EDGE has been inlined.
{
int i;
struct ipa_edge_args *args = IPA_EDGE_REF (edge);
- struct inline_edge_summary *es = inline_edge_summary (edge);
- struct inline_edge_summary *inlined_es
- = inline_edge_summary (inlined_edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
+ struct ipa_call_summary *inlined_es
+ = ipa_call_summaries->get (inlined_edge);
for (i = 0; i < ipa_get_cs_argument_count (args); i++)
{
struct cgraph_edge *e, *next;
for (e = node->callees; e; e = next)
{
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
predicate p;
next = e->next_callee;
}
for (e = node->indirect_calls; e; e = next)
{
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
predicate p;
next = e->next_callee;
int i;
predicate toplev_predicate;
predicate true_p = true;
- struct inline_edge_summary *es = inline_edge_summary (edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
if (es->predicate)
toplev_predicate = *es->predicate;
operand_map, offset_map, clause, &toplev_predicate);
inline_update_callee_summaries (edge->callee,
- inline_edge_summary (edge)->loop_depth);
+ ipa_call_summaries->get (edge)->loop_depth);
/* We do not maintain predicates of inlined edges, free it. */
edge_set_predicate (edge, &true_p);
vec<tree> known_vals;
vec<ipa_polymorphic_call_context> known_contexts;
vec<ipa_agg_jump_function_p> known_aggs;
- struct inline_edge_summary *es = inline_edge_summary (edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
int min_size;
callee = edge->callee->ultimate_alias_target ();
estimate_size_after_inlining (struct cgraph_node *node,
struct cgraph_edge *edge)
{
- struct inline_edge_summary *es = inline_edge_summary (edge);
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
if (!es->predicate || *es->predicate != false)
{
int size = inline_summaries->get (node)->size + estimate_edge_growth (edge);
/* Write inline summary for edge E to OB. */
static void
-read_inline_edge_summary (struct lto_input_block *ib, struct cgraph_edge *e)
+read_ipa_call_summary (struct lto_input_block *ib, struct cgraph_edge *e)
{
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
predicate p;
int length, i;
p.stream_in (&ib);
set_hint_predicate (&info->array_index, p);
for (e = node->callees; e; e = e->next_callee)
- read_inline_edge_summary (&ib, e);
+ read_ipa_call_summary (&ib, e);
for (e = node->indirect_calls; e; e = e->next_callee)
- read_inline_edge_summary (&ib, e);
+ read_ipa_call_summary (&ib, e);
}
lto_free_section_data (file_data, LTO_section_inline_summary, NULL, data,
/* Write inline summary for edge E to OB. */
static void
-write_inline_edge_summary (struct output_block *ob, struct cgraph_edge *e)
+write_ipa_call_summary (struct output_block *ob, struct cgraph_edge *e)
{
- struct inline_edge_summary *es = inline_edge_summary (e);
+ struct ipa_call_summary *es = ipa_call_summaries->get (e);
int i;
streamer_write_uhwi (ob, es->call_stmt_size);
else
streamer_write_uhwi (ob, 0);
for (edge = cnode->callees; edge; edge = edge->next_callee)
- write_inline_edge_summary (ob, edge);
+ write_ipa_call_summary (ob, edge);
for (edge = cnode->indirect_calls; edge; edge = edge->next_callee)
- write_inline_edge_summary (ob, edge);
+ write_ipa_call_summary (ob, edge);
}
}
streamer_write_char_stream (ob->main_stream, 0);
inline_free_summary (void)
{
struct cgraph_node *node;
- if (edge_removal_hook_holder)
- symtab->remove_edge_removal_hook (edge_removal_hook_holder);
- edge_removal_hook_holder = NULL;
- if (edge_duplication_hook_holder)
- symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
- edge_duplication_hook_holder = NULL;
- if (!inline_edge_summary_vec.exists ())
+ if (!ipa_call_summaries)
return;
FOR_EACH_DEFINED_FUNCTION (node)
if (!node->alias)
reset_inline_summary (node, inline_summaries->get (node));
inline_summaries->release ();
inline_summaries = NULL;
- inline_edge_summary_vec.release ();
+ ipa_call_summaries->release ();
+ delete ipa_call_summaries;
+ ipa_call_summaries = NULL;
edge_predicate_pool.release ();
}
> opt_for_fn (caller->decl, optimize)))
{
if (estimate_edge_time (e)
- >= 20 + inline_edge_summary (e)->call_stmt_time)
+ >= 20 + ipa_call_summaries->get (e)->call_stmt_time)
{
e->inline_failed = CIF_OPTIMIZATION_MISMATCH;
inlinable = false;
/* This calculation should match one in ipa-inline-analysis.c
(estimate_edge_size_and_time). */
time -= (sreal) edge->frequency
- * inline_edge_summary (edge)->call_stmt_time / CGRAPH_FREQ_BASE;
+ * ipa_call_summaries->get (edge)->call_stmt_time / CGRAPH_FREQ_BASE;
time += caller_time;
if (time <= 0)
time = ((sreal) 1) >> 8;
else if ((!DECL_DECLARED_INLINE_P (callee->decl)
&& (!e->count || !e->maybe_hot_p ()))
&& inline_summaries->get (callee)->min_size
- - inline_edge_summary (e)->call_stmt_size
- > MAX (MAX_INLINE_INSNS_SINGLE, MAX_INLINE_INSNS_AUTO))
+ - ipa_call_summaries->get (e)->call_stmt_size
+ > (unsigned)MAX (MAX_INLINE_INSNS_SINGLE, MAX_INLINE_INSNS_AUTO))
{
e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
want_inline = false;
}
else if ((DECL_DECLARED_INLINE_P (callee->decl) || e->count)
&& inline_summaries->get (callee)->min_size
- - inline_edge_summary (e)->call_stmt_size
- > 16 * MAX_INLINE_INSNS_SINGLE)
+ - ipa_call_summaries->get (e)->call_stmt_size
+ > (unsigned)16 * MAX_INLINE_INSNS_SINGLE)
{
e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT
of functions fully inlined in program. */
else
{
- int nest = MIN (inline_edge_summary (edge)->loop_depth, 8);
+ int nest = MIN (ipa_call_summaries->get (edge)->loop_depth, 8);
badness = growth;
/* Decrease badness if call is nested. */
statements that don't have inline parameters computed. */
for (edge = node->callees; edge; edge = edge->next_callee)
{
- if (inline_edge_summary_vec.length () > (unsigned) edge->uid)
- {
- struct inline_edge_summary *es = inline_edge_summary (edge);
- es->call_stmt_size
- = estimate_num_insns (edge->call_stmt, &eni_size_weights);
- es->call_stmt_time
- = estimate_num_insns (edge->call_stmt, &eni_time_weights);
- }
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
+ es->call_stmt_size
+ = estimate_num_insns (edge->call_stmt, &eni_size_weights);
+ es->call_stmt_time
+ = estimate_num_insns (edge->call_stmt, &eni_time_weights);
}
inline_update_overall_summary (node);
inlined = false;
for (edge = node->callees; edge; edge = edge->next_callee)
{
/* We have no summary for new bound store calls yet. */
- if (inline_edge_summary_vec.length () > (unsigned)edge->uid)
- {
- struct inline_edge_summary *es = inline_edge_summary (edge);
- es->call_stmt_size
- = estimate_num_insns (edge->call_stmt, &eni_size_weights);
- es->call_stmt_time
- = estimate_num_insns (edge->call_stmt, &eni_time_weights);
- }
+ struct ipa_call_summary *es = ipa_call_summaries->get (edge);
+ es->call_stmt_size
+ = estimate_num_insns (edge->call_stmt, &eni_size_weights);
+ es->call_stmt_time
+ = estimate_num_insns (edge->call_stmt, &eni_time_weights);
+
if (edge->callee->decl
&& !gimple_check_call_matching_types (
edge->call_stmt, edge->callee->decl, false))