Commit 1532500e by Jan Hubicka Committed by Jan Hubicka

ipa-fnsummary.c (ipa_call_context): New constructor.


	* ipa-fnsummary.c (ipa_call_context): New constructor.
	(estimate_node_size_and_time): Turn to ...
	(ipa_call_context::estimate_size_and_time): ... this one.
	(ipa_call_context::release): New.
	* ipa-fnsummary.h (ipa_call_context): New class.
	(estimate_node_size_and_time): Remove.
	* ipa-inline-analysis.c (do_estimate_edge_time, do_estimate_edge_size,
	do_estimate_edge_hints): Update.

From-SVN: r277755
parent a9a0fd0e
2019-11-02 Jan Hubicka <hubicka@ucw.cz> 2019-11-02 Jan Hubicka <hubicka@ucw.cz>
* ipa-fnsummary.c (ipa_call_context): New constructor.
(estimate_node_size_and_time): Turn to ...
(ipa_call_context::estimate_size_and_time): ... this one.
(ipa_call_context::release): New.
* ipa-fnsummary.h (ipa_call_context): New class.
(estimate_node_size_and_time): Remove.
* ipa-inline-analysis.c (do_estimate_edge_time, do_estimate_edge_size,
do_estimate_edge_hints): Update.
2019-11-02 Jan Hubicka <hubicka@ucw.cz>
* config.in: Regenerate. * config.in: Regenerate.
* configure: Regenerate. * configure: Regenerate.
* configure.ac: Check for mallinfo. * configure.ac: Check for mallinfo.
...@@ -2940,31 +2940,54 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, ...@@ -2940,31 +2940,54 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size,
} }
} }
/* Default constructor for ipa call context.
Memory alloction of known_vals, known_contexts
and known_aggs vectors is owned by the caller, but can
be release by ipa_call_context::release.
inline_param_summary is owned by the caller. */
ipa_call_context::ipa_call_context (cgraph_node *node,
clause_t possible_truths,
clause_t nonspec_possible_truths,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context>
known_contexts,
vec<ipa_agg_jump_function_p> known_aggs,
vec<inline_param_summary>
inline_param_summary)
: m_node (node), m_possible_truths (possible_truths),
m_nonspec_possible_truths (nonspec_possible_truths),
m_inline_param_summary (inline_param_summary),
m_known_vals (known_vals),
m_known_contexts (known_contexts),
m_known_aggs (known_aggs)
{
}
/* Release memory used by known_vals/contexts/aggs vectors. */
void
ipa_call_context::release ()
{
m_known_vals.release ();
m_known_contexts.release ();
m_known_aggs.release ();
}
/* Estimate size and time needed to execute NODE assuming /* Estimate size and time needed to execute call in the given context.
POSSIBLE_TRUTHS clause, and KNOWN_VALS, KNOWN_AGGS and KNOWN_CONTEXTS
information about NODE's arguments. If non-NULL use also probability
information present in INLINE_PARAM_SUMMARY vector.
Additionally detemine hints determined by the context. Finally compute Additionally detemine hints determined by the context. Finally compute
minimal size needed for the call that is independent on the call context and minimal size needed for the call that is independent on the call context and
can be used for fast estimates. Return the values in RET_SIZE, can be used for fast estimates. Return the values in RET_SIZE,
RET_MIN_SIZE, RET_TIME and RET_HINTS. */ RET_MIN_SIZE, RET_TIME and RET_HINTS. */
void void
estimate_node_size_and_time (struct cgraph_node *node, ipa_call_context::estimate_size_and_time (int *ret_size,
clause_t possible_truths, int *ret_min_size,
clause_t nonspec_possible_truths, sreal *ret_time,
vec<tree> known_vals, sreal *ret_nonspecialized_time,
vec<ipa_polymorphic_call_context> known_contexts, ipa_hints *ret_hints)
vec<ipa_agg_jump_function_p> known_aggs,
int *ret_size, int *ret_min_size,
sreal *ret_time,
sreal *ret_nonspecialized_time,
ipa_hints *ret_hints,
vec<inline_param_summary>
inline_param_summary)
{ {
class ipa_fn_summary *info = ipa_fn_summaries->get_create (node); class ipa_fn_summary *info = ipa_fn_summaries->get_create (m_node);
size_time_entry *e; size_time_entry *e;
int size = 0; int size = 0;
sreal time = 0; sreal time = 0;
...@@ -2976,13 +2999,13 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -2976,13 +2999,13 @@ estimate_node_size_and_time (struct cgraph_node *node,
{ {
bool found = false; bool found = false;
fprintf (dump_file, " Estimating body: %s/%i\n" fprintf (dump_file, " Estimating body: %s/%i\n"
" Known to be false: ", node->name (), " Known to be false: ", m_node->name (),
node->order); m_node->order);
for (i = predicate::not_inlined_condition; for (i = predicate::not_inlined_condition;
i < (predicate::first_dynamic_condition i < (predicate::first_dynamic_condition
+ (int) vec_safe_length (info->conds)); i++) + (int) vec_safe_length (info->conds)); i++)
if (!(possible_truths & (1 << i))) if (!(m_possible_truths & (1 << i)))
{ {
if (found) if (found)
fprintf (dump_file, ", "); fprintf (dump_file, ", ");
...@@ -2991,19 +3014,19 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -2991,19 +3014,19 @@ estimate_node_size_and_time (struct cgraph_node *node,
} }
} }
estimate_calls_size_and_time (node, &size, &min_size, &time, &hints, possible_truths, estimate_calls_size_and_time (m_node, &size, &min_size, &time, &hints, m_possible_truths,
known_vals, known_contexts, known_aggs); m_known_vals, m_known_contexts, m_known_aggs);
sreal nonspecialized_time = time; sreal nonspecialized_time = time;
for (i = 0; vec_safe_iterate (info->size_time_table, i, &e); i++) for (i = 0; vec_safe_iterate (info->size_time_table, i, &e); i++)
{ {
bool exec = e->exec_predicate.evaluate (nonspec_possible_truths); bool exec = e->exec_predicate.evaluate (m_nonspec_possible_truths);
/* Because predicates are conservative, it can happen that nonconst is 1 /* Because predicates are conservative, it can happen that nonconst is 1
but exec is 0. */ but exec is 0. */
if (exec) if (exec)
{ {
bool nonconst = e->nonconst_predicate.evaluate (possible_truths); bool nonconst = e->nonconst_predicate.evaluate (m_possible_truths);
gcc_checking_assert (e->time >= 0); gcc_checking_assert (e->time >= 0);
gcc_checking_assert (time >= 0); gcc_checking_assert (time >= 0);
...@@ -3019,7 +3042,7 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -3019,7 +3042,7 @@ estimate_node_size_and_time (struct cgraph_node *node,
nonspecialized_time += e->time; nonspecialized_time += e->time;
if (!nonconst) if (!nonconst)
; ;
else if (!inline_param_summary.exists ()) else if (!m_inline_param_summary.exists ())
{ {
if (nonconst) if (nonconst)
time += e->time; time += e->time;
...@@ -3027,8 +3050,8 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -3027,8 +3050,8 @@ estimate_node_size_and_time (struct cgraph_node *node,
else else
{ {
int prob = e->nonconst_predicate.probability int prob = e->nonconst_predicate.probability
(info->conds, possible_truths, (info->conds, m_possible_truths,
inline_param_summary); m_inline_param_summary);
gcc_checking_assert (prob >= 0); gcc_checking_assert (prob >= 0);
gcc_checking_assert (prob <= REG_BR_PROB_BASE); gcc_checking_assert (prob <= REG_BR_PROB_BASE);
time += e->time * prob / REG_BR_PROB_BASE; time += e->time * prob / REG_BR_PROB_BASE;
...@@ -3052,14 +3075,14 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -3052,14 +3075,14 @@ estimate_node_size_and_time (struct cgraph_node *node,
time = nonspecialized_time; time = nonspecialized_time;
if (info->loop_iterations if (info->loop_iterations
&& !info->loop_iterations->evaluate (possible_truths)) && !info->loop_iterations->evaluate (m_possible_truths))
hints |= INLINE_HINT_loop_iterations; hints |= INLINE_HINT_loop_iterations;
if (info->loop_stride if (info->loop_stride
&& !info->loop_stride->evaluate (possible_truths)) && !info->loop_stride->evaluate (m_possible_truths))
hints |= INLINE_HINT_loop_stride; hints |= INLINE_HINT_loop_stride;
if (info->scc_no) if (info->scc_no)
hints |= INLINE_HINT_in_scc; hints |= INLINE_HINT_in_scc;
if (DECL_DECLARED_INLINE_P (node->decl)) if (DECL_DECLARED_INLINE_P (m_node->decl))
hints |= INLINE_HINT_declared_inline; hints |= INLINE_HINT_declared_inline;
size = RDIV (size, ipa_fn_summary::size_scale); size = RDIV (size, ipa_fn_summary::size_scale);
...@@ -3101,10 +3124,11 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node, ...@@ -3101,10 +3124,11 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
evaluate_conditions_for_known_args (node, false, known_vals, known_aggs, evaluate_conditions_for_known_args (node, false, known_vals, known_aggs,
&clause, &nonspec_clause); &clause, &nonspec_clause);
estimate_node_size_and_time (node, clause, nonspec_clause, ipa_call_context ctx (node, clause, nonspec_clause,
known_vals, known_contexts, known_vals, known_contexts,
known_aggs, ret_size, NULL, ret_time, known_aggs, vNULL);
ret_nonspec_time, hints, vNULL); ctx.estimate_size_and_time (ret_size, NULL, ret_time,
ret_nonspec_time, hints);
} }
/* Return stack frame offset where frame of NODE is supposed to start inside /* Return stack frame offset where frame of NODE is supposed to start inside
......
...@@ -281,6 +281,47 @@ public: ...@@ -281,6 +281,47 @@ public:
ipa_call_summary *dst_data); ipa_call_summary *dst_data);
}; };
/* This object describe a context of call. That is a summary of known
information about its parameters. Main purpose of this context is
to give more realistic esitmations of function runtime, size and
inline hints. */
class ipa_call_context
{
public:
ipa_call_context (cgraph_node *node,
clause_t possible_truths,
clause_t nonspec_possible_truths,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context> known_contexts,
vec<ipa_agg_jump_function_p> known_aggs,
vec<inline_param_summary> m_inline_param_summary);
void estimate_size_and_time (int *ret_size, int *ret_min_size,
sreal *ret_time,
sreal *ret_nonspecialized_time,
ipa_hints *ret_hints);
void release ();
private:
/* Called function. */
cgraph_node *m_node;
/* Clause describing what predicate conditionals can be satisfied
in this context if function is inlined/specialised. */
clause_t m_possible_truths;
/* Clause describing what predicate conditionals can be satisfied
in this context if function is kept offline. */
clause_t m_nonspec_possible_truths;
/* Inline summary maintains info about change probabilities. */
vec<inline_param_summary> m_inline_param_summary;
/* The following is used only to resolve indirect calls. */
/* Vector describing known values of parameters. */
vec<tree> m_known_vals;
/* Vector describing known polymorphic call contexts. */
vec<ipa_polymorphic_call_context> m_known_contexts;
/* Vector describing known aggregate values. */
vec<ipa_agg_jump_function_p> m_known_aggs;
};
extern fast_call_summary <ipa_call_summary *, va_heap> *ipa_call_summaries; extern fast_call_summary <ipa_call_summary *, va_heap> *ipa_call_summaries;
/* In ipa-fnsummary.c */ /* In ipa-fnsummary.c */
...@@ -302,25 +343,14 @@ void ipa_update_overall_fn_summary (struct cgraph_node *node); ...@@ -302,25 +343,14 @@ void ipa_update_overall_fn_summary (struct cgraph_node *node);
void compute_fn_summary (struct cgraph_node *, bool); void compute_fn_summary (struct cgraph_node *, bool);
void evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, void evaluate_properties_for_edge (struct cgraph_edge *e,
bool inline_p,
clause_t *clause_ptr, clause_t *clause_ptr,
clause_t *nonspec_clause_ptr, clause_t *nonspec_clause_ptr,
vec<tree> *known_vals_ptr, vec<tree> *known_vals_ptr,
vec<ipa_polymorphic_call_context> vec<ipa_polymorphic_call_context>
*known_contexts_ptr, *known_contexts_ptr,
vec<ipa_agg_jump_function_p> *); vec<ipa_agg_jump_function_p> *);
void estimate_node_size_and_time (struct cgraph_node *node,
clause_t possible_truths,
clause_t nonspec_possible_truths,
vec<tree> known_vals,
vec<ipa_polymorphic_call_context>,
vec<ipa_agg_jump_function_p> known_aggs,
int *ret_size, int *ret_min_size,
sreal *ret_time,
sreal *ret_nonspecialized_time,
ipa_hints *ret_hints,
vec<inline_param_summary>
inline_param_summary);
void ipa_fnsummary_c_finalize (void); void ipa_fnsummary_c_finalize (void);
HOST_WIDE_INT ipa_get_stack_frame_offset (struct cgraph_node *node); HOST_WIDE_INT ipa_get_stack_frame_offset (struct cgraph_node *node);
......
...@@ -137,9 +137,10 @@ do_estimate_edge_time (struct cgraph_edge *edge) ...@@ -137,9 +137,10 @@ do_estimate_edge_time (struct cgraph_edge *edge)
evaluate_properties_for_edge (edge, true, evaluate_properties_for_edge (edge, true,
&clause, &nonspec_clause, &known_vals, &clause, &nonspec_clause, &known_vals,
&known_contexts, &known_aggs); &known_contexts, &known_aggs);
estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, ipa_call_context ctx (callee, clause, nonspec_clause, known_vals,
known_contexts, known_aggs, &size, &min_size, known_contexts, known_aggs, es->param);
&time, &nonspec_time, &hints, es->param); ctx.estimate_size_and_time (&size, &min_size,
&time, &nonspec_time, &hints);
/* When we have profile feedback, we can quite safely identify hot /* When we have profile feedback, we can quite safely identify hot
edges and for those we disable size limits. Don't do that when edges and for those we disable size limits. Don't do that when
...@@ -152,9 +153,7 @@ do_estimate_edge_time (struct cgraph_edge *edge) ...@@ -152,9 +153,7 @@ do_estimate_edge_time (struct cgraph_edge *edge)
: edge->caller->count.ipa ()))) : edge->caller->count.ipa ())))
hints |= INLINE_HINT_known_hot; hints |= INLINE_HINT_known_hot;
known_vals.release (); ctx.release ();
known_contexts.release ();
known_aggs.release ();
gcc_checking_assert (size >= 0); gcc_checking_assert (size >= 0);
gcc_checking_assert (time >= 0); gcc_checking_assert (time >= 0);
...@@ -207,12 +206,10 @@ do_estimate_edge_size (struct cgraph_edge *edge) ...@@ -207,12 +206,10 @@ do_estimate_edge_size (struct cgraph_edge *edge)
&clause, &nonspec_clause, &clause, &nonspec_clause,
&known_vals, &known_contexts, &known_vals, &known_contexts,
&known_aggs); &known_aggs);
estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, ipa_call_context ctx (callee, clause, nonspec_clause, known_vals,
known_contexts, known_aggs, &size, NULL, NULL, known_contexts, known_aggs, vNULL);
NULL, NULL, vNULL); ctx.estimate_size_and_time (&size, NULL, NULL, NULL, NULL);
known_vals.release (); ctx.release ();
known_contexts.release ();
known_aggs.release ();
return size; return size;
} }
...@@ -248,12 +245,10 @@ do_estimate_edge_hints (struct cgraph_edge *edge) ...@@ -248,12 +245,10 @@ do_estimate_edge_hints (struct cgraph_edge *edge)
&clause, &nonspec_clause, &clause, &nonspec_clause,
&known_vals, &known_contexts, &known_vals, &known_contexts,
&known_aggs); &known_aggs);
estimate_node_size_and_time (callee, clause, nonspec_clause, known_vals, ipa_call_context ctx (callee, clause, nonspec_clause, known_vals,
known_contexts, known_aggs, NULL, NULL, known_contexts, known_aggs, vNULL);
NULL, NULL, &hints, vNULL); ctx.estimate_size_and_time (NULL, NULL, NULL, NULL, &hints);
known_vals.release (); ctx.release ();
known_contexts.release ();
known_aggs.release ();
hints |= simple_edge_hints (edge); hints |= simple_edge_hints (edge);
return hints; return hints;
} }
......
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