|
|
001c85 |
* cif-code.def: Add NEVER_EXECUTED.
|
|
|
001c85 |
* ipa-inline-analysis.c (reset_inline_summary,
|
|
|
001c85 |
compute_inline_parameters, estimate_calls_size_and_time,
|
|
|
001c85 |
inline_update_overall_summary): Track number of calls.
|
|
|
001c85 |
(never_executed_edge_p): New predicate.
|
|
|
001c85 |
* ipa-inline.c (want_inline_self_recursive_call_p): do not inline
|
|
|
001c85 |
recursively for calls that are not going to be executed.
|
|
|
001c85 |
(inline_small_functions): Do not inline never exeucted edge if callee
|
|
|
001c85 |
has too many calls.
|
|
|
001c85 |
* ipa-inline.h (inline_summary): Add num calls.
|
|
|
001c85 |
(never_executed_edge_p): New.
|
|
|
001c85 |
|
|
|
001c85 |
--- gcc/cif-code.def (revision 257016)
|
|
|
001c85 |
+++ gcc/cif-code.def (working copy)
|
|
|
001c85 |
@@ -103,3 +103,6 @@ DEFCIFCODE(TARGET_OPTION_MISMATCH, N_("t
|
|
|
001c85 |
|
|
|
001c85 |
/* We can't inline because of mismatched optimization levels. */
|
|
|
001c85 |
DEFCIFCODE(OPTIMIZATION_MISMATCH, N_("optimization level attribute mismatch"))
|
|
|
001c85 |
+
|
|
|
001c85 |
+/* We know that the call will be optimized out. */
|
|
|
001c85 |
+DEFCIFCODE(NEVER_EXECUTED, N_("never executed"))
|
|
|
001c85 |
--- gcc/ipa-inline-analysis.c (revision 257016)
|
|
|
001c85 |
+++ gcc/ipa-inline-analysis.c (working copy)
|
|
|
001c85 |
@@ -990,6 +990,7 @@ reset_inline_summary (struct cgraph_node
|
|
|
001c85 |
info->stack_frame_offset = 0;
|
|
|
001c85 |
info->size = 0;
|
|
|
001c85 |
info->time = 0;
|
|
|
001c85 |
+ info->num_calls = 0;
|
|
|
001c85 |
info->growth = 0;
|
|
|
001c85 |
info->scc_no = 0;
|
|
|
001c85 |
if (info->loop_iterations)
|
|
|
001c85 |
@@ -2704,6 +2705,7 @@ compute_inline_parameters (struct cgraph
|
|
|
001c85 |
/* Inlining characteristics are maintained by the cgraph_mark_inline. */
|
|
|
001c85 |
info->time = info->self_time;
|
|
|
001c85 |
info->size = info->self_size;
|
|
|
001c85 |
+ info->num_calls = 0;
|
|
|
001c85 |
info->stack_frame_offset = 0;
|
|
|
001c85 |
info->estimated_stack_size = info->estimated_self_stack_size;
|
|
|
001c85 |
#ifdef ENABLE_CHECKING
|
|
|
001c85 |
@@ -2816,7 +2818,7 @@ estimate_edge_size_and_time (struct cgra
|
|
|
001c85 |
|
|
|
001c85 |
static void
|
|
|
001c85 |
estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time,
|
|
|
001c85 |
- inline_hints *hints,
|
|
|
001c85 |
+ inline_hints *hints, int *num,
|
|
|
001c85 |
clause_t possible_truths,
|
|
|
001c85 |
vec<tree> known_vals,
|
|
|
001c85 |
vec<tree> known_binfos,
|
|
|
001c85 |
@@ -2826,6 +2828,7 @@ estimate_calls_size_and_time (struct cgr
|
|
|
001c85 |
for (e = node->callees; e; e = e->next_callee)
|
|
|
001c85 |
{
|
|
|
001c85 |
struct inline_edge_summary *es = inline_edge_summary (e);
|
|
|
001c85 |
+ (*num)++;
|
|
|
001c85 |
if (!es->predicate
|
|
|
001c85 |
|| evaluate_predicate (es->predicate, possible_truths))
|
|
|
001c85 |
{
|
|
|
001c85 |
@@ -2838,7 +2841,7 @@ estimate_calls_size_and_time (struct cgr
|
|
|
001c85 |
known_aggs, hints);
|
|
|
001c85 |
}
|
|
|
001c85 |
else
|
|
|
001c85 |
- estimate_calls_size_and_time (e->callee, size, time, hints,
|
|
|
001c85 |
+ estimate_calls_size_and_time (e->callee, size, time, hints, num,
|
|
|
001c85 |
possible_truths,
|
|
|
001c85 |
known_vals, known_binfos,
|
|
|
001c85 |
known_aggs);
|
|
|
001c85 |
@@ -2846,6 +2849,7 @@ estimate_calls_size_and_time (struct cgr
|
|
|
001c85 |
}
|
|
|
001c85 |
for (e = node->indirect_calls; e; e = e->next_callee)
|
|
|
001c85 |
{
|
|
|
001c85 |
+ (*num)++;
|
|
|
001c85 |
struct inline_edge_summary *es = inline_edge_summary (e);
|
|
|
001c85 |
if (!es->predicate
|
|
|
001c85 |
|| evaluate_predicate (es->predicate, possible_truths))
|
|
|
001c85 |
@@ -2936,7 +2940,8 @@ estimate_node_size_and_time (struct cgra
|
|
|
001c85 |
if (DECL_DECLARED_INLINE_P (node->symbol.decl))
|
|
|
001c85 |
hints |= INLINE_HINT_declared_inline;
|
|
|
001c85 |
|
|
|
001c85 |
- estimate_calls_size_and_time (node, &size, &time, &hints, possible_truths,
|
|
|
001c85 |
+ int num = 0;
|
|
|
001c85 |
+ estimate_calls_size_and_time (node, &size, &time, &hints, &num, possible_truths,
|
|
|
001c85 |
known_vals, known_binfos, known_aggs);
|
|
|
001c85 |
gcc_checking_assert (size >= 0);
|
|
|
001c85 |
gcc_checking_assert (time >= 0);
|
|
|
001c85 |
@@ -3369,13 +3374,14 @@ inline_update_overall_summary (struct cg
|
|
|
001c85 |
|
|
|
001c85 |
info->size = 0;
|
|
|
001c85 |
info->time = 0;
|
|
|
001c85 |
+ info->num_calls = 0;
|
|
|
001c85 |
for (i = 0; vec_safe_iterate (info->entry, i, &e); i++)
|
|
|
001c85 |
{
|
|
|
001c85 |
info->size += e->size, info->time += e->time;
|
|
|
001c85 |
if (info->time > MAX_TIME * INLINE_TIME_SCALE)
|
|
|
001c85 |
info->time = MAX_TIME * INLINE_TIME_SCALE;
|
|
|
001c85 |
}
|
|
|
001c85 |
- estimate_calls_size_and_time (node, &info->size, &info->time, NULL,
|
|
|
001c85 |
+ estimate_calls_size_and_time (node, &info->size, &info->time, NULL, &info->num_calls,
|
|
|
001c85 |
~(clause_t) (1 << predicate_false_condition),
|
|
|
001c85 |
vNULL, vNULL, vNULL);
|
|
|
001c85 |
info->time = (info->time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE;
|
|
|
001c85 |
@@ -3528,6 +3534,14 @@ do_estimate_edge_hints (struct cgraph_ed
|
|
|
001c85 |
return hints;
|
|
|
001c85 |
}
|
|
|
001c85 |
|
|
|
001c85 |
+/* Return true if edge is never executed. */
|
|
|
001c85 |
+bool
|
|
|
001c85 |
+never_executed_edge_p (struct cgraph_edge *e)
|
|
|
001c85 |
+{
|
|
|
001c85 |
+ struct inline_edge_summary *es = inline_edge_summary (e);
|
|
|
001c85 |
+ return es->predicate && false_predicate_p (es->predicate);
|
|
|
001c85 |
+}
|
|
|
001c85 |
+
|
|
|
001c85 |
|
|
|
001c85 |
/* Estimate self time of the function NODE after inlining EDGE. */
|
|
|
001c85 |
|
|
|
001c85 |
--- gcc/ipa-inline.c (revision 257016)
|
|
|
001c85 |
+++ gcc/ipa-inline.c (working copy)
|
|
|
001c85 |
@@ -656,6 +656,11 @@ want_inline_self_recursive_call_p (struc
|
|
|
001c85 |
reason = "--param max-inline-recursive-depth exceeded.";
|
|
|
001c85 |
want_inline = false;
|
|
|
001c85 |
}
|
|
|
001c85 |
+ else if (never_executed_edge_p (edge))
|
|
|
001c85 |
+ {
|
|
|
001c85 |
+ reason = "edge is never executed.";
|
|
|
001c85 |
+ want_inline = false;
|
|
|
001c85 |
+ }
|
|
|
001c85 |
|
|
|
001c85 |
if (outer_node->global.inlined_to)
|
|
|
001c85 |
caller_freq = outer_node->callers->frequency;
|
|
|
001c85 |
@@ -1597,6 +1602,14 @@ inline_small_functions (void)
|
|
|
001c85 |
outer_node = where, depth++;
|
|
|
001c85 |
where = where->callers->caller;
|
|
|
001c85 |
}
|
|
|
001c85 |
+ if (never_executed_edge_p (edge)
|
|
|
001c85 |
+ && inline_summary (edge->callee)->num_calls > 30)
|
|
|
001c85 |
+ {
|
|
|
001c85 |
+ if (dump_file)
|
|
|
001c85 |
+ fprintf (dump_file, "Never executed edge\n");
|
|
|
001c85 |
+ edge->inline_failed = CIF_NEVER_EXECUTED;
|
|
|
001c85 |
+ continue;
|
|
|
001c85 |
+ }
|
|
|
001c85 |
if (outer_node
|
|
|
001c85 |
&& !want_inline_self_recursive_call_p (edge, outer_node,
|
|
|
001c85 |
true, depth))
|
|
|
001c85 |
--- gcc/ipa-inline.h (revision 257016)
|
|
|
001c85 |
+++ gcc/ipa-inline.h (working copy)
|
|
|
001c85 |
@@ -132,6 +132,7 @@ struct GTY(()) inline_summary
|
|
|
001c85 |
/* Estimated size of the function after inlining. */
|
|
|
001c85 |
int time;
|
|
|
001c85 |
int size;
|
|
|
001c85 |
+ int num_calls;
|
|
|
001c85 |
|
|
|
001c85 |
/* Conditional size/time information. The summaries are being
|
|
|
001c85 |
merged during inlining. */
|
|
|
001c85 |
@@ -226,6 +227,7 @@ inline_hints do_estimate_edge_hints (str
|
|
|
001c85 |
void initialize_growth_caches (void);
|
|
|
001c85 |
void free_growth_caches (void);
|
|
|
001c85 |
void compute_inline_parameters (struct cgraph_node *, bool);
|
|
|
001c85 |
+bool never_executed_edge_p (struct cgraph_edge *);
|
|
|
001c85 |
|
|
|
001c85 |
/* In ipa-inline-transform.c */
|
|
|
001c85 |
bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool);
|
|
|
001c85 |
|