Commit 37678631 by Jan Hubicka Committed by Jan Hubicka

re PR lto/45375 ([meta-bug] Issues with building Mozilla (i.e. Firefox) with LTO)


	PR lto/45375
	* ipa-inline.c (want_inline_small_function_p): Bypass
	inline limits for hinted functions.
	(edge_badness): Dump hints; decrease badness for hinted funcitons.
	* ipa-inline.h (enum inline_hints_vals): New enum.
	(inline_hints): New type.
	(edge_growth_cache_entry): Add hints.
	(dump_inline_summary): Update.
	(dump_inline_hints): Declare.
	(do_estimate_edge_hints): Declare.
	(estimate_edge_hints): New inline function.
	(reset_edge_growth_cache): Update.
	* predict.c (cgraph_maybe_hot_edge_p): Do not ice on indirect edges.
	* ipa-inline-analysis.c (dump_inline_hints): New function.
	(estimate_edge_devirt_benefit): Return true when function should be
	hinted.
	(estimate_calls_size_and_time): New hints argument; set it when
	devritualization happens.
	(estimate_node_size_and_time): New hints argument.
	(do_estimate_edge_time): Cache hints.
	(do_estimate_edge_growth): Update.	
	(do_estimate_edge_hints): New function

From-SVN: r190509
parent ecfdae6f
2012-08-18 Jan Hubicka <jh@suse.cz>
PR lto/45375
* ipa-inline.c (want_inline_small_function_p): Bypass
inline limits for hinted functions.
(edge_badness): Dump hints; decrease badness for hinted funcitons.
* ipa-inline.h (enum inline_hints_vals): New enum.
(inline_hints): New type.
(edge_growth_cache_entry): Add hints.
(dump_inline_summary): Update.
(dump_inline_hints): Declare.
(do_estimate_edge_hints): Declare.
(estimate_edge_hints): New inline function.
(reset_edge_growth_cache): Update.
* predict.c (cgraph_maybe_hot_edge_p): Do not ice on indirect edges.
* ipa-inline-analysis.c (dump_inline_hints): New function.
(estimate_edge_devirt_benefit): Return true when function should be
hinted.
(estimate_calls_size_and_time): New hints argument; set it when
devritualization happens.
(estimate_node_size_and_time): New hints argument.
(do_estimate_edge_time): Cache hints.
(do_estimate_edge_growth): Update.
(do_estimate_edge_hints): New function
2012-08-18 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> 2012-08-18 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR middle-end/53823 PR middle-end/53823
......
...@@ -615,6 +615,22 @@ dump_predicate (FILE *f, conditions conds, struct predicate *pred) ...@@ -615,6 +615,22 @@ dump_predicate (FILE *f, conditions conds, struct predicate *pred)
} }
/* Dump inline hints. */
void
dump_inline_hints (FILE *f, inline_hints hints)
{
if (!hints)
return;
fprintf (f, "inline hints:");
if (hints & INLINE_HINT_indirect_call)
{
hints &= ~INLINE_HINT_indirect_call;
fprintf (f, " indirect_call");
}
gcc_assert (!hints);
}
/* Record SIZE and TIME under condition PRED into the inline summary. */ /* Record SIZE and TIME under condition PRED into the inline summary. */
static void static void
...@@ -2302,7 +2318,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *time, ...@@ -2302,7 +2318,7 @@ estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *time,
/* Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS and /* Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS and
KNOWN_BINFOS. */ KNOWN_BINFOS. */
static void static bool
estimate_edge_devirt_benefit (struct cgraph_edge *ie, estimate_edge_devirt_benefit (struct cgraph_edge *ie,
int *size, int *time, int prob, int *size, int *time, int prob,
VEC (tree, heap) *known_vals, VEC (tree, heap) *known_vals,
...@@ -2311,14 +2327,16 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, ...@@ -2311,14 +2327,16 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
{ {
tree target; tree target;
int time_diff, size_diff; int time_diff, size_diff;
struct cgraph_node *callee;
struct inline_summary *isummary;
if (!known_vals && !known_binfos) if (!known_vals && !known_binfos)
return; return false;
target = ipa_get_indirect_edge_target (ie, known_vals, known_binfos, target = ipa_get_indirect_edge_target (ie, known_vals, known_binfos,
known_aggs); known_aggs);
if (!target) if (!target)
return; return false;
/* Account for difference in cost between indirect and direct calls. */ /* Account for difference in cost between indirect and direct calls. */
size_diff = ((eni_size_weights.indirect_call_cost - eni_size_weights.call_cost) size_diff = ((eni_size_weights.indirect_call_cost - eni_size_weights.call_cost)
...@@ -2328,40 +2346,11 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, ...@@ -2328,40 +2346,11 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
* INLINE_TIME_SCALE * prob / REG_BR_PROB_BASE); * INLINE_TIME_SCALE * prob / REG_BR_PROB_BASE);
*time -= time_diff; *time -= time_diff;
/* TODO: This code is trying to benefit indirect calls that will be inlined later.
The logic however do not belong into local size/time estimates and can not be
done here, or the accounting of changes will get wrong and we result with
negative function body sizes. We need to introduce infrastructure for independent
benefits to the inliner. */
#if 0
struct cgraph_node *callee;
struct inline_summary *isummary;
int edge_size, edge_time, time_diff, size_diff;
callee = cgraph_get_node (target); callee = cgraph_get_node (target);
if (!callee || !callee->analyzed) if (!callee || !callee->analyzed)
return; return false;
isummary = inline_summary (callee); isummary = inline_summary (callee);
if (!isummary->inlinable) return isummary->inlinable;
return;
estimate_edge_size_and_time (ie, &edge_size, &edge_time, prob);
/* Count benefit only from functions that definitely will be inlined
if additional context from NODE's caller were available.
We just account overall size change by inlining. TODO:
we really need to add sort of benefit metrics for these kind of
cases. */
if (edge_size - size_diff >= isummary->size * INLINE_SIZE_SCALE)
{
/* Subtract size and time that we added for edge IE. */
*size -= edge_size - size_diff;
/* Account inlined call. */
*size += isummary->size * INLINE_SIZE_SCALE;
}
#endif
} }
...@@ -2371,6 +2360,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, ...@@ -2371,6 +2360,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie,
static void static void
estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time,
inline_hints *hints,
clause_t possible_truths, clause_t possible_truths,
VEC (tree, heap) *known_vals, VEC (tree, heap) *known_vals,
VEC (tree, heap) *known_binfos, VEC (tree, heap) *known_binfos,
...@@ -2389,7 +2379,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, ...@@ -2389,7 +2379,7 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time,
estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE); estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE);
} }
else else
estimate_calls_size_and_time (e->callee, size, time, estimate_calls_size_and_time (e->callee, size, time, hints,
possible_truths, possible_truths,
known_vals, known_binfos, known_aggs); known_vals, known_binfos, known_aggs);
} }
...@@ -2400,8 +2390,11 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, ...@@ -2400,8 +2390,11 @@ estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time,
if (!es->predicate || evaluate_predicate (es->predicate, possible_truths)) if (!es->predicate || evaluate_predicate (es->predicate, possible_truths))
{ {
estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE); estimate_edge_size_and_time (e, size, time, REG_BR_PROB_BASE);
estimate_edge_devirt_benefit (e, size, time, REG_BR_PROB_BASE, if (estimate_edge_devirt_benefit (e, size, time, REG_BR_PROB_BASE,
known_vals, known_binfos, known_aggs); known_vals, known_binfos, known_aggs)
&& hints
&& cgraph_maybe_hot_edge_p (e))
*hints |= INLINE_HINT_indirect_call;
} }
} }
} }
...@@ -2418,12 +2411,14 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -2418,12 +2411,14 @@ estimate_node_size_and_time (struct cgraph_node *node,
VEC (tree, heap) *known_binfos, VEC (tree, heap) *known_binfos,
VEC (ipa_agg_jump_function_p, heap) *known_aggs, VEC (ipa_agg_jump_function_p, heap) *known_aggs,
int *ret_size, int *ret_time, int *ret_size, int *ret_time,
inline_hints *ret_hints,
VEC (inline_param_summary_t, heap) VEC (inline_param_summary_t, heap)
*inline_param_summary) *inline_param_summary)
{ {
struct inline_summary *info = inline_summary (node); struct inline_summary *info = inline_summary (node);
size_time_entry *e; size_time_entry *e;
int size = 0, time = 0; int size = 0, time = 0;
inline_hints hints = 0;
int i; int i;
if (dump_file if (dump_file
...@@ -2467,7 +2462,7 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -2467,7 +2462,7 @@ estimate_node_size_and_time (struct cgraph_node *node,
if (time > MAX_TIME * INLINE_TIME_SCALE) if (time > MAX_TIME * INLINE_TIME_SCALE)
time = MAX_TIME * INLINE_TIME_SCALE; time = MAX_TIME * INLINE_TIME_SCALE;
estimate_calls_size_and_time (node, &size, &time, possible_truths, estimate_calls_size_and_time (node, &size, &time, &hints, possible_truths,
known_vals, known_binfos, known_aggs); known_vals, known_binfos, known_aggs);
time = (time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE; time = (time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE;
size = (size + INLINE_SIZE_SCALE / 2) / INLINE_SIZE_SCALE; size = (size + INLINE_SIZE_SCALE / 2) / INLINE_SIZE_SCALE;
...@@ -2480,6 +2475,8 @@ estimate_node_size_and_time (struct cgraph_node *node, ...@@ -2480,6 +2475,8 @@ estimate_node_size_and_time (struct cgraph_node *node,
*ret_time = time; *ret_time = time;
if (ret_size) if (ret_size)
*ret_size = size; *ret_size = size;
if (ret_hints)
*ret_hints = hints;
return; return;
} }
...@@ -2499,7 +2496,7 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node, ...@@ -2499,7 +2496,7 @@ estimate_ipcp_clone_size_and_time (struct cgraph_node *node,
clause = evaluate_conditions_for_known_args (node, false, known_vals, NULL); clause = evaluate_conditions_for_known_args (node, false, known_vals, NULL);
estimate_node_size_and_time (node, clause, known_vals, known_binfos, NULL, estimate_node_size_and_time (node, clause, known_vals, known_binfos, NULL,
ret_size, ret_time, ret_size, ret_time, NULL,
NULL); NULL);
} }
...@@ -2871,7 +2868,7 @@ inline_update_overall_summary (struct cgraph_node *node) ...@@ -2871,7 +2868,7 @@ inline_update_overall_summary (struct cgraph_node *node)
info->time = 0; info->time = 0;
for (i = 0; VEC_iterate (size_time_entry, info->entry, i, e); i++) for (i = 0; VEC_iterate (size_time_entry, info->entry, i, e); i++)
info->size += e->size, info->time += e->time; info->size += e->size, info->time += e->time;
estimate_calls_size_and_time (node, &info->size, &info->time, estimate_calls_size_and_time (node, &info->size, &info->time, NULL,
~(clause_t)(1 << predicate_false_condition), ~(clause_t)(1 << predicate_false_condition),
NULL, NULL, NULL); NULL, NULL, NULL);
info->time = (info->time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE; info->time = (info->time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE;
...@@ -2890,6 +2887,7 @@ do_estimate_edge_time (struct cgraph_edge *edge) ...@@ -2890,6 +2887,7 @@ do_estimate_edge_time (struct cgraph_edge *edge)
{ {
int time; int time;
int size; int size;
inline_hints hints;
gcov_type ret; gcov_type ret;
struct cgraph_node *callee; struct cgraph_node *callee;
clause_t clause; clause_t clause;
...@@ -2905,7 +2903,7 @@ do_estimate_edge_time (struct cgraph_edge *edge) ...@@ -2905,7 +2903,7 @@ do_estimate_edge_time (struct cgraph_edge *edge)
&clause, &known_vals, &known_binfos, &clause, &known_vals, &known_binfos,
&known_aggs); &known_aggs);
estimate_node_size_and_time (callee, clause, known_vals, known_binfos, estimate_node_size_and_time (callee, clause, known_vals, known_binfos,
known_aggs, &size, &time, es->param); known_aggs, &size, &time, &hints, es->param);
VEC_free (tree, heap, known_vals); VEC_free (tree, heap, known_vals);
VEC_free (tree, heap, known_binfos); VEC_free (tree, heap, known_binfos);
VEC_free (ipa_agg_jump_function_p, heap, known_aggs); VEC_free (ipa_agg_jump_function_p, heap, known_aggs);
...@@ -2929,6 +2927,8 @@ do_estimate_edge_time (struct cgraph_edge *edge) ...@@ -2929,6 +2927,8 @@ do_estimate_edge_time (struct cgraph_edge *edge)
gcc_checking_assert (es->call_stmt_size); gcc_checking_assert (es->call_stmt_size);
VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).size VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).size
= ret_size + (ret_size >= 0); = ret_size + (ret_size >= 0);
VEC_index (edge_growth_cache_entry, edge_growth_cache, edge->uid).hints
= hints + 1;
} }
return ret; return ret;
} }
...@@ -2967,7 +2967,7 @@ do_estimate_edge_growth (struct cgraph_edge *edge) ...@@ -2967,7 +2967,7 @@ do_estimate_edge_growth (struct cgraph_edge *edge)
&clause, &known_vals, &known_binfos, &clause, &known_vals, &known_binfos,
&known_aggs); &known_aggs);
estimate_node_size_and_time (callee, clause, known_vals, known_binfos, estimate_node_size_and_time (callee, clause, known_vals, known_binfos,
known_aggs, &size, NULL, NULL); known_aggs, &size, NULL, NULL, NULL);
VEC_free (tree, heap, known_vals); VEC_free (tree, heap, known_vals);
VEC_free (tree, heap, known_binfos); VEC_free (tree, heap, known_binfos);
VEC_free (ipa_agg_jump_function_p, heap, known_aggs); VEC_free (ipa_agg_jump_function_p, heap, known_aggs);
...@@ -2976,6 +2976,47 @@ do_estimate_edge_growth (struct cgraph_edge *edge) ...@@ -2976,6 +2976,47 @@ do_estimate_edge_growth (struct cgraph_edge *edge)
} }
/* Estimate the growth of the caller when inlining EDGE.
Only to be called via estimate_edge_size. */
inline_hints
do_estimate_edge_hints (struct cgraph_edge *edge)
{
inline_hints hints;
struct cgraph_node *callee;
clause_t clause;
VEC (tree, heap) *known_vals;
VEC (tree, heap) *known_binfos;
VEC (ipa_agg_jump_function_p, heap) *known_aggs;
/* When we do caching, use do_estimate_edge_time to populate the entry. */
if (edge_growth_cache)
{
do_estimate_edge_time (edge);
hints = VEC_index (edge_growth_cache_entry,
edge_growth_cache,
edge->uid).hints;
gcc_checking_assert (hints);
return hints - 1;
}
callee = cgraph_function_or_thunk_node (edge->callee, NULL);
/* Early inliner runs without caching, go ahead and do the dirty work. */
gcc_checking_assert (edge->inline_failed);
evaluate_properties_for_edge (edge, true,
&clause, &known_vals, &known_binfos,
&known_aggs);
estimate_node_size_and_time (callee, clause, known_vals, known_binfos,
known_aggs, NULL, NULL, &hints, NULL);
VEC_free (tree, heap, known_vals);
VEC_free (tree, heap, known_binfos);
VEC_free (ipa_agg_jump_function_p, heap, known_aggs);
return hints;
}
/* Estimate self time of the function NODE after inlining EDGE. */ /* Estimate self time of the function NODE after inlining EDGE. */
int int
......
...@@ -472,11 +472,15 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -472,11 +472,15 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
else else
{ {
int growth = estimate_edge_growth (e); int growth = estimate_edge_growth (e);
inline_hints hints = estimate_edge_hints (e);
if (growth <= 0) if (growth <= 0)
; ;
/* Apply MAX_INLINE_INSNS_SINGLE limit. Do not do so when
hints suggests that inlining given function is very profitable. */
else if (DECL_DECLARED_INLINE_P (callee->symbol.decl) else if (DECL_DECLARED_INLINE_P (callee->symbol.decl)
&& growth >= MAX_INLINE_INSNS_SINGLE) && growth >= MAX_INLINE_INSNS_SINGLE
&& !(hints & INLINE_HINT_indirect_call))
{ {
e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT; e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
want_inline = false; want_inline = false;
...@@ -523,8 +527,14 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ...@@ -523,8 +527,14 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
e->inline_failed = CIF_NOT_DECLARED_INLINED; e->inline_failed = CIF_NOT_DECLARED_INLINED;
want_inline = false; want_inline = false;
} }
/* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline
Upgrade it to MAX_INLINE_INSNS_SINGLE when hints suggests that
inlining given function is very profitable. */
else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl) else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl)
&& growth >= MAX_INLINE_INSNS_AUTO) && growth >= ((hints & INLINE_HINT_indirect_call)
? MAX (MAX_INLINE_INSNS_AUTO,
MAX_INLINE_INSNS_SINGLE)
: MAX_INLINE_INSNS_AUTO))
{ {
e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT; e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
want_inline = false; want_inline = false;
...@@ -743,21 +753,25 @@ edge_badness (struct cgraph_edge *edge, bool dump) ...@@ -743,21 +753,25 @@ edge_badness (struct cgraph_edge *edge, bool dump)
struct cgraph_node *callee = cgraph_function_or_thunk_node (edge->callee, struct cgraph_node *callee = cgraph_function_or_thunk_node (edge->callee,
NULL); NULL);
struct inline_summary *callee_info = inline_summary (callee); struct inline_summary *callee_info = inline_summary (callee);
inline_hints hints;
if (DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl)) if (DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl))
return INT_MIN; return INT_MIN;
growth = estimate_edge_growth (edge); growth = estimate_edge_growth (edge);
time_growth = estimate_edge_time (edge); time_growth = estimate_edge_time (edge);
hints = estimate_edge_hints (edge);
if (dump) if (dump)
{ {
fprintf (dump_file, " Badness calculation for %s -> %s\n", fprintf (dump_file, " Badness calculation for %s -> %s\n",
xstrdup (cgraph_node_name (edge->caller)), xstrdup (cgraph_node_name (edge->caller)),
xstrdup (cgraph_node_name (callee))); xstrdup (cgraph_node_name (callee)));
fprintf (dump_file, " size growth %i, time growth %i\n", fprintf (dump_file, " size growth %i, time growth %i ",
growth, growth,
time_growth); time_growth);
dump_inline_hints (dump_file, hints);
fprintf (dump_file, "\n");
} }
/* Always prefer inlining saving code size. */ /* Always prefer inlining saving code size. */
...@@ -849,6 +863,8 @@ edge_badness (struct cgraph_edge *edge, bool dump) ...@@ -849,6 +863,8 @@ edge_badness (struct cgraph_edge *edge, bool dump)
if (dump) if (dump)
fprintf (dump_file, "Badness overflow\n"); fprintf (dump_file, "Badness overflow\n");
} }
if (hints & INLINE_HINT_indirect_call)
badness /= 8;
if (dump) if (dump)
{ {
fprintf (dump_file, fprintf (dump_file,
......
...@@ -42,6 +42,13 @@ typedef struct GTY(()) condition ...@@ -42,6 +42,13 @@ typedef struct GTY(()) condition
unsigned by_ref : 1; unsigned by_ref : 1;
} condition; } condition;
/* Inline hints are reasons why inline heuristics should preffer inlining given function.
They are represtented as bitmap of the following values. */
enum inline_hints_vals {
INLINE_HINT_indirect_call = 1
};
typedef int inline_hints;
DEF_VEC_O (condition); DEF_VEC_O (condition);
DEF_VEC_ALLOC_O (condition, gc); DEF_VEC_ALLOC_O (condition, gc);
...@@ -158,6 +165,7 @@ extern VEC(inline_edge_summary_t,heap) *inline_edge_summary_vec; ...@@ -158,6 +165,7 @@ extern VEC(inline_edge_summary_t,heap) *inline_edge_summary_vec;
typedef struct edge_growth_cache_entry typedef struct edge_growth_cache_entry
{ {
int time, size; int time, size;
inline_hints hints;
} edge_growth_cache_entry; } edge_growth_cache_entry;
DEF_VEC_O(edge_growth_cache_entry); DEF_VEC_O(edge_growth_cache_entry);
DEF_VEC_ALLOC_O(edge_growth_cache_entry,heap); DEF_VEC_ALLOC_O(edge_growth_cache_entry,heap);
...@@ -168,7 +176,8 @@ extern VEC(edge_growth_cache_entry,heap) *edge_growth_cache; ...@@ -168,7 +176,8 @@ extern VEC(edge_growth_cache_entry,heap) *edge_growth_cache;
/* In ipa-inline-analysis.c */ /* In ipa-inline-analysis.c */
void debug_inline_summary (struct cgraph_node *); void debug_inline_summary (struct cgraph_node *);
void dump_inline_summaries (FILE *f); void dump_inline_summaries (FILE *f);
void dump_inline_summary (FILE * f, struct cgraph_node *node); void dump_inline_summary (FILE *f, struct cgraph_node *node);
void dump_inline_hints (FILE *f, inline_hints);
void inline_generate_summary (void); void inline_generate_summary (void);
void inline_read_summary (void); void inline_read_summary (void);
void inline_write_summary (void); void inline_write_summary (void);
...@@ -185,6 +194,7 @@ void inline_merge_summary (struct cgraph_edge *edge); ...@@ -185,6 +194,7 @@ void inline_merge_summary (struct cgraph_edge *edge);
void inline_update_overall_summary (struct cgraph_node *node); void inline_update_overall_summary (struct cgraph_node *node);
int do_estimate_edge_growth (struct cgraph_edge *edge); int do_estimate_edge_growth (struct cgraph_edge *edge);
int do_estimate_edge_time (struct cgraph_edge *edge); int do_estimate_edge_time (struct cgraph_edge *edge);
inline_hints do_estimate_edge_hints (struct cgraph_edge *edge);
void initialize_growth_caches (void); void initialize_growth_caches (void);
void free_growth_caches (void); void free_growth_caches (void);
void compute_inline_parameters (struct cgraph_node *, bool); void compute_inline_parameters (struct cgraph_node *, bool);
...@@ -257,6 +267,22 @@ estimate_edge_time (struct cgraph_edge *edge) ...@@ -257,6 +267,22 @@ estimate_edge_time (struct cgraph_edge *edge)
} }
/* Return estimated callee runtime increase after inlning
EDGE. */
static inline inline_hints
estimate_edge_hints (struct cgraph_edge *edge)
{
inline_hints ret;
if ((int)VEC_length (edge_growth_cache_entry, edge_growth_cache) <= edge->uid
|| !(ret = VEC_index (edge_growth_cache_entry,
edge_growth_cache,
edge->uid).hints))
return do_estimate_edge_time (edge);
return ret - 1;
}
/* Reset cached value for NODE. */ /* Reset cached value for NODE. */
static inline void static inline void
...@@ -273,7 +299,7 @@ reset_edge_growth_cache (struct cgraph_edge *edge) ...@@ -273,7 +299,7 @@ reset_edge_growth_cache (struct cgraph_edge *edge)
{ {
if ((int)VEC_length (edge_growth_cache_entry, edge_growth_cache) > edge->uid) if ((int)VEC_length (edge_growth_cache_entry, edge_growth_cache) > edge->uid)
{ {
struct edge_growth_cache_entry zero = {0, 0}; struct edge_growth_cache_entry zero = {0, 0, 0};
VEC_replace (edge_growth_cache_entry, edge_growth_cache, edge->uid, zero); VEC_replace (edge_growth_cache_entry, edge_growth_cache, edge->uid, zero);
} }
} }
...@@ -165,10 +165,12 @@ cgraph_maybe_hot_edge_p (struct cgraph_edge *edge) ...@@ -165,10 +165,12 @@ cgraph_maybe_hot_edge_p (struct cgraph_edge *edge)
<= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION))) <= profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION)))
return false; return false;
if (edge->caller->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED if (edge->caller->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED
|| edge->callee->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED) || (edge->callee
&& edge->callee->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED))
return false; return false;
if (edge->caller->frequency > NODE_FREQUENCY_UNLIKELY_EXECUTED if (edge->caller->frequency > NODE_FREQUENCY_UNLIKELY_EXECUTED
&& edge->callee->frequency <= NODE_FREQUENCY_EXECUTED_ONCE) && (edge->callee
&& edge->callee->frequency <= NODE_FREQUENCY_EXECUTED_ONCE))
return false; return false;
if (optimize_size) if (optimize_size)
return false; return false;
......
2012-08-18 Jan Hubicka <jh@suse.cz>
* gcc.dg/ipa/iinline-1.c: Update testcase to test inline hints.
2012-08-18 Mikael Morin <mikael@gcc.gnu.org> 2012-08-18 Mikael Morin <mikael@gcc.gnu.org>
PR fortran/39290 PR fortran/39290
......
/* Verify that simple indirect calls are inlined even without early /* Verify that simple indirect calls are inlined even without early
inlining.. */ inlining.. */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O3 -c -fdump-ipa-inline -fno-early-inlining" } */ /* { dg-options "-O3 -c -fdump-ipa-inline-details -fno-early-inlining -fno-ipa-cp" } */
extern void non_existent(int); extern void non_existent(int);
...@@ -22,5 +22,6 @@ int test (void) ...@@ -22,5 +22,6 @@ int test (void)
return 0; return 0;
} }
/* { dg-final { scan-ipa-dump "indirect_call" "inline" } } */
/* { dg-final { scan-ipa-dump "hooray\[^\\n\]*inline copy in test" "inline" } } */ /* { dg-final { scan-ipa-dump "hooray\[^\\n\]*inline copy in test" "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */ /* { dg-final { cleanup-ipa-dump "inline" } } */
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