+2019-11-04 Jan Hubicka <jh@suse.cz>
+
+ * cgraphclones.c (cgraph_node::create_version_clone): Do not
+ duplicate summaries.
+ * ipa-fnsummary.c (ipa_fn_summary_alloc): Allocate size summary
+ first.
+ (ipa_fn_summary_t::duplicate): Use get instead of get_create to
+ access call summaries.
+ (dump_ipa_call_summary): Be ready for missing edge summaries.
+ (analyze_function_body): Use get instead of get_create to access
+ edge summary.
+ (estimate_calls_size_and_time): Do not access summaries of
+ inlined edges; sanity check they are missing.
+ (ipa_call_context::estimate_size_and_time): Use get instead
+ of get_create to access node summary.
+ (inline_update_callee_summaries): Do not update depth of
+ inlined edge.
+ (ipa_merge_fn_summary_after_inlining): Remove inline edge from
+ growth caches.
+ (ipa_merge_fn_summary_after_inlining): Use get instead
+ of get_create.
+ * ipa-fnsummary.h (ipa_remove_from_growth_caches): Declare.
+ * ipa-inline-analyssi.c (edge_growth_cache): Turn to
+ fast summary.
+ (initialize_growth_caches): Update.
+ (do_estimate_edge_time): Remove redundant copy of context.
+ (ipa_remove_from_growth_caches): New function.
+ * ipa-inline.c (flatten_function): Update overall summary
+ only when optimizing.
+ (inline_to_all_callers): Update overall summary of function
+ inlined to.
+ * ipa-inline.h (edge_growth_cache): Turn to fast summary.
+ * symbol-summary.h (call_summary_base): Set m_initialize_when_cloning
+ to false.
+
2019-11-04 Richard Biener <rguenther@suse.de>
* system.h: Include malloc.h if INCLUDE_MALLOC_H and HAVE_MALLINFO.
ipa_fn_summary_alloc (void)
{
gcc_checking_assert (!ipa_fn_summaries);
- ipa_fn_summaries = ipa_fn_summary_t::create_ggc (symtab);
ipa_size_summaries = new fast_function_summary <ipa_size_summary *, va_heap>
(symtab);
+ ipa_fn_summaries = ipa_fn_summary_t::create_ggc (symtab);
ipa_call_summaries = new ipa_call_summary_t (symtab);
}
for (edge = dst->callees; edge; edge = next)
{
predicate new_predicate;
- class ipa_call_summary *es = ipa_call_summaries->get_create (edge);
+ class 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;
- class ipa_call_summary *es = ipa_call_summaries->get_create (edge);
+ class ipa_call_summary *es = ipa_call_summaries->get (edge);
next = edge->next_callee;
gcc_checking_assert (edge->inline_failed);
int i;
fprintf (f,
- "%*s%s/%i %s\n%*s loop depth:%2i freq:%4.2f size:%2i time: %2i",
+ "%*s%s/%i %s\n%*s freq:%4.2f",
indent, "", callee->name (), callee->order,
!edge->inline_failed
? "inlined" : cgraph_inline_failed_string (edge-> inline_failed),
- indent, "", es->loop_depth, edge->sreal_frequency ().to_double (),
- es->call_stmt_size, es->call_stmt_time);
+ indent, "", edge->sreal_frequency ().to_double ());
+
+ if (es)
+ fprintf (f, " loop depth:%2i size:%2i time: %2i",
+ es->loop_depth, es->call_stmt_size, es->call_stmt_time);
ipa_fn_summary *s = ipa_fn_summaries->get (callee);
ipa_size_summary *ss = ipa_size_summaries->get (callee);
(int) (ss->size / ipa_fn_summary::size_scale),
(int) s->estimated_stack_size);
- if (es->predicate)
+ if (es && es->predicate)
{
fprintf (f, " predicate: ");
es->predicate->dump (f, info->conds);
}
else
fprintf (f, "\n");
- if (es->param.exists ())
+ if (es && es->param.exists ())
for (i = 0; i < (int) es->param.length (); i++)
{
int prob = es->param[i].change_prob;
edge->speculative_call_info (direct, indirect, ref);
gcc_assert (direct == edge);
ipa_call_summary *es2
- = ipa_call_summaries->get_create (indirect);
+ = ipa_call_summaries->get (indirect);
ipa_call_summaries->duplicate (edge, indirect,
es, es2);
}
struct cgraph_edge *e;
for (e = node->callees; e; e = e->next_callee)
{
- class ipa_call_summary *es = ipa_call_summaries->get_create (e);
+ if (!e->inline_failed)
+ {
+ gcc_checking_assert (!ipa_call_summaries->get (e));
+ estimate_calls_size_and_time (e->callee, size, min_size, time,
+ hints,
+ possible_truths,
+ known_vals, known_contexts,
+ known_aggs);
+ continue;
+ }
+ class ipa_call_summary *es = ipa_call_summaries->get (e);
/* Do not care about zero sized builtins. */
- if (e->inline_failed && !es->call_stmt_size)
+ if (!es->call_stmt_size)
{
gcc_checking_assert (!es->call_stmt_time);
continue;
if (!es->predicate
|| es->predicate->evaluate (possible_truths))
{
- if (e->inline_failed)
- {
- /* Predicates of calls shall not use NOT_CHANGED codes,
- sowe do not need to compute probabilities. */
- estimate_edge_size_and_time (e, size,
- es->predicate ? NULL : min_size,
- time, REG_BR_PROB_BASE,
- known_vals, known_contexts,
- known_aggs, hints);
- }
- else
- estimate_calls_size_and_time (e->callee, size, min_size, time,
- hints,
- possible_truths,
- known_vals, known_contexts,
- known_aggs);
+ /* Predicates of calls shall not use NOT_CHANGED codes,
+ sowe do not need to compute probabilities. */
+ estimate_edge_size_and_time (e, size,
+ es->predicate ? NULL : min_size,
+ time, REG_BR_PROB_BASE,
+ known_vals, known_contexts,
+ known_aggs, hints);
}
}
for (e = node->indirect_calls; e; e = e->next_callee)
{
- class ipa_call_summary *es = ipa_call_summaries->get_create (e);
+ class ipa_call_summary *es = ipa_call_summaries->get (e);
if (!es->predicate
|| es->predicate->evaluate (possible_truths))
estimate_edge_size_and_time (e, size,
sreal *ret_nonspecialized_time,
ipa_hints *ret_hints)
{
- class ipa_fn_summary *info = ipa_fn_summaries->get_create (m_node);
+ class ipa_fn_summary *info = ipa_fn_summaries->get (m_node);
size_time_entry *e;
int size = 0;
sreal time = 0;
{
if (!e->inline_failed)
inline_update_callee_summaries (e->callee, depth);
- ipa_call_summaries->get (e)->loop_depth += depth;
+ else
+ ipa_call_summaries->get (e)->loop_depth += depth;
}
for (e = node->indirect_calls; e; e = e->next_callee)
ipa_call_summaries->get (e)->loop_depth += depth;
/* Free summaries that are not maintained for inline clones/edges. */
ipa_call_summaries->remove (edge);
ipa_fn_summaries->remove (edge->callee);
+ ipa_remove_from_growth_caches (edge);
}
/* For performance reasons ipa_merge_fn_summary_after_inlining is not updating
void
ipa_update_overall_fn_summary (struct cgraph_node *node)
{
- class ipa_fn_summary *info = ipa_fn_summaries->get_create (node);
- class ipa_size_summary *size_info = ipa_size_summaries->get_create (node);
+ class ipa_fn_summary *info = ipa_fn_summaries->get (node);
+ class ipa_size_summary *size_info = ipa_size_summaries->get (node);
size_time_entry *e;
int i;
#include "gimplify.h"
/* Cached node/edge growths. */
-call_summary<edge_growth_cache_entry *> *edge_growth_cache = NULL;
+fast_call_summary<edge_growth_cache_entry *, va_heap> *edge_growth_cache = NULL;
/* The context cache remembers estimated time/size and hints for given
ipa_call_context of a call. */
initialize_growth_caches ()
{
edge_growth_cache
- = new call_summary<edge_growth_cache_entry *> (symtab, false);
+ = new fast_call_summary<edge_growth_cache_entry *, va_heap> (symtab);
node_context_cache
= new fast_function_summary<node_context_summary *, va_heap> (symtab);
}
else
node_context_cache_clear++;
e->entry.ctx.release (true);
- e->entry.ctx = ctx;
ctx.estimate_size_and_time (&size, &min_size,
&time, &nonspec_time, &hints);
e->entry.size = size;
node_context_cache->remove (node);
}
+/* Remove EDGE from caches once it was inlined. */
+void
+ipa_remove_from_growth_caches (struct cgraph_edge *edge)
+{
+ if (node_context_cache)
+ node_context_cache->remove (edge->callee);
+ if (edge_growth_cache)
+ edge_growth_cache->remove (edge);
+}
+
/* Return estimated callee growth after inlining EDGE.
Only to be called via estimate_edge_size. */