diff options
Diffstat (limited to 'gcc/ipa-inline.c')
-rw-r--r-- | gcc/ipa-inline.c | 174 |
1 files changed, 99 insertions, 75 deletions
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 1dbb3248fab..c605eaed937 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -156,6 +156,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, bool update_original) { HOST_WIDE_INT peak; + struct inline_summary *caller_info, *callee_info; if (duplicate) { @@ -184,7 +185,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, gcc_assert (!e->callee->global.inlined_to); if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->decl)) { - overall_size -= e->callee->global.size; + overall_size -= inline_summary (e->callee)->size; nfunctions_inlined++; } duplicate = false; @@ -201,17 +202,20 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, } } + callee_info = inline_summary (e->callee); + caller_info = inline_summary (e->caller); + if (e->caller->global.inlined_to) e->callee->global.inlined_to = e->caller->global.inlined_to; else e->callee->global.inlined_to = e->caller; - e->callee->global.stack_frame_offset - = e->caller->global.stack_frame_offset - + inline_summary (e->caller)->estimated_self_stack_size; - peak = e->callee->global.stack_frame_offset - + inline_summary (e->callee)->estimated_self_stack_size; - if (e->callee->global.inlined_to->global.estimated_stack_size < peak) - e->callee->global.inlined_to->global.estimated_stack_size = peak; + callee_info->stack_frame_offset + = caller_info->stack_frame_offset + + caller_info->estimated_self_stack_size; + peak = callee_info->stack_frame_offset + + callee_info->estimated_self_stack_size; + if (inline_summary (e->callee->global.inlined_to)->estimated_stack_size < peak) + inline_summary (e->callee->global.inlined_to)->estimated_stack_size = peak; cgraph_propagate_frequency (e->callee); /* Recursively clone all bodies. */ @@ -233,6 +237,7 @@ cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original, int old_size = 0, new_size = 0; struct cgraph_node *to = NULL; struct cgraph_edge *curr = e; + struct inline_summary *info; /* Don't inline inlined edges. */ gcc_assert (e->inline_failed); @@ -248,10 +253,11 @@ cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original, for (;e && !e->inline_failed; e = e->caller->callers) { to = e->caller; - old_size = e->caller->global.size; + info = inline_summary (to); + old_size = info->size; new_size = estimate_size_after_inlining (to, curr); - to->global.size = new_size; - to->global.time = estimate_time_after_inlining (to, curr); + info->size = new_size; + info->time = estimate_time_after_inlining (to, curr); } gcc_assert (curr->callee->global.inlined_to == to); if (new_size > old_size) @@ -280,23 +286,27 @@ cgraph_check_inline_limits (struct cgraph_edge *e, int newsize; int limit; HOST_WIDE_INT stack_size_limit, inlined_stack; + struct inline_summary *info, *what_info; if (to->global.inlined_to) to = to->global.inlined_to; + info = inline_summary (to); + what_info = inline_summary (what); + /* When inlining large function body called once into small function, take the inlined function as base for limiting the growth. */ - if (inline_summary (to)->self_size > inline_summary(what)->self_size) - limit = inline_summary (to)->self_size; + if (info->self_size > what_info->self_size) + limit = info->self_size; else - limit = inline_summary (what)->self_size; + limit = what_info->self_size; limit += limit * PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH) / 100; /* Check the size after inlining against the function limits. But allow the function to shrink if it went over the limits by forced inlining. */ newsize = estimate_size_after_inlining (to, e); - if (newsize >= to->global.size + if (newsize >= info->size && newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS) && newsize > limit) { @@ -305,13 +315,13 @@ cgraph_check_inline_limits (struct cgraph_edge *e, return false; } - stack_size_limit = inline_summary (to)->estimated_self_stack_size; + stack_size_limit = info->estimated_self_stack_size; stack_size_limit += stack_size_limit * PARAM_VALUE (PARAM_STACK_FRAME_GROWTH) / 100; - inlined_stack = (to->global.stack_frame_offset - + inline_summary (to)->estimated_self_stack_size - + what->global.estimated_stack_size); + inlined_stack = (info->stack_frame_offset + + info->estimated_self_stack_size + + what_info->estimated_stack_size); if (inlined_stack > stack_size_limit && inlined_stack > PARAM_VALUE (PARAM_LARGE_STACK_FRAME)) { @@ -328,8 +338,9 @@ static bool cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason) { tree decl = n->decl; + struct inline_summary *info = inline_summary (n); - if (n->local.disregard_inline_limits) + if (info->disregard_inline_limits) return true; if (!flag_inline_small_functions && !DECL_DECLARED_INLINE_P (decl)) @@ -354,7 +365,7 @@ cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason) if (DECL_DECLARED_INLINE_P (decl)) { - if (n->global.size >= MAX_INLINE_INSNS_SINGLE) + if (info->size >= MAX_INLINE_INSNS_SINGLE) { if (reason) *reason = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT; @@ -363,7 +374,7 @@ cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason) } else { - if (n->global.size >= MAX_INLINE_INSNS_AUTO) + if (info->size >= MAX_INLINE_INSNS_AUTO) { if (reason) *reason = CIF_MAX_INLINE_INSNS_AUTO_LIMIT; @@ -385,8 +396,9 @@ cgraph_edge_badness (struct cgraph_edge *edge, bool dump) { gcov_type badness; int growth; + struct inline_summary *callee_info = inline_summary (edge->callee); - if (edge->callee->local.disregard_inline_limits) + if (callee_info->disregard_inline_limits) return INT_MIN; growth = estimate_edge_growth (edge); @@ -398,11 +410,11 @@ cgraph_edge_badness (struct cgraph_edge *edge, bool dump) cgraph_node_name (edge->callee)); fprintf (dump_file, " growth %i, time %i-%i, size %i-%i\n", growth, - edge->callee->global.time, - inline_summary (edge->callee)->time_inlining_benefit + callee_info->time, + callee_info->time_inlining_benefit + edge->call_stmt_time, - edge->callee->global.size, - inline_summary (edge->callee)->size_inlining_benefit + callee_info->size, + callee_info->size_inlining_benefit + edge->call_stmt_size); } @@ -422,7 +434,7 @@ cgraph_edge_badness (struct cgraph_edge *edge, bool dump) badness = ((int) ((double) edge->count * INT_MIN / max_count / (max_benefit + 1)) * - (inline_summary (edge->callee)->time_inlining_benefit + (callee_info->time_inlining_benefit + edge->call_stmt_time + 1)) / growth; if (dump) { @@ -453,9 +465,9 @@ cgraph_edge_badness (struct cgraph_edge *edge, bool dump) int growth_for_all; badness = growth * 10000; benefitperc = - 100 * (inline_summary (edge->callee)->time_inlining_benefit + 100 * (callee_info->time_inlining_benefit + edge->call_stmt_time) - / (edge->callee->global.time + 1) + 1; + / (callee_info->time + 1) + 1; benefitperc = MIN (benefitperc, 100); div *= benefitperc; @@ -543,13 +555,13 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node, struct cgraph_edge *edge; cgraph_inline_failed_t failed_reason; - if (!node->local.inlinable + if (!inline_summary (node)->inlinable || cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE || node->global.inlined_to) return; if (!bitmap_set_bit (updated_nodes, node->uid)) return; - node->global.estimated_growth = INT_MIN; + inline_summary (node)->estimated_growth = INT_MIN; /* See if there is something to do. */ for (edge = node->callers; edge; edge = edge->next_caller) @@ -586,7 +598,7 @@ update_callee_keys (fibheap_t heap, struct cgraph_node *node, bitmap updated_nodes) { struct cgraph_edge *e = node->callees; - node->global.estimated_growth = INT_MIN; + inline_summary (node)->estimated_growth = INT_MIN; if (!e) return; @@ -596,11 +608,11 @@ update_callee_keys (fibheap_t heap, struct cgraph_node *node, else { if (e->inline_failed - && e->callee->local.inlinable + && inline_summary (e->callee)->inlinable && cgraph_function_body_availability (e->callee) >= AVAIL_AVAILABLE && !bitmap_bit_p (updated_nodes, e->callee->uid)) { - node->global.estimated_growth = INT_MIN; + inline_summary (node)->estimated_growth = INT_MIN; /* If function becomes uninlinable, we need to remove it from the heap. */ if (!cgraph_default_inline_p (e->callee, &e->inline_failed)) update_caller_keys (heap, e->callee, updated_nodes); @@ -632,7 +644,7 @@ update_all_callee_keys (fibheap_t heap, struct cgraph_node *node, bitmap updated_nodes) { struct cgraph_edge *e = node->callees; - node->global.estimated_growth = INT_MIN; + inline_summary (node)->estimated_growth = INT_MIN; if (!e) return; @@ -709,7 +721,7 @@ cgraph_decide_recursive_inlining (struct cgraph_edge *edge, /* It does not make sense to recursively inline always-inline functions as we are going to sorry() on the remaining calls anyway. */ - if (node->local.disregard_inline_limits + if (inline_summary (node)->disregard_inline_limits && lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl))) return false; @@ -811,8 +823,8 @@ cgraph_decide_recursive_inlining (struct cgraph_edge *edge, if (dump_file) fprintf (dump_file, "\n Inlined %i times, body grown from size %i to %i, time %i to %i\n", n, - master_clone->global.size, node->global.size, - master_clone->global.time, node->global.time); + inline_summary (master_clone)->size, inline_summary (node)->size, + inline_summary (master_clone)->time, inline_summary (node)->time); /* Remove master clone we used for inlining. We rely that clones inlined into master clone gets queued just before master clone so we don't @@ -870,7 +882,7 @@ add_new_edges_to_heap (fibheap_t heap, VEC (cgraph_edge_p, heap) *new_edges) struct cgraph_edge *edge = VEC_pop (cgraph_edge_p, new_edges); gcc_assert (!edge->aux); - if (edge->callee->local.inlinable + if (inline_summary (edge->callee)->inlinable && edge->inline_failed && cgraph_default_inline_p (edge->callee, &edge->inline_failed)) edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge); @@ -905,26 +917,37 @@ cgraph_decide_inlining_of_small_functions (void) /* Put all inline candidates into the heap. */ for (node = cgraph_nodes; node; node = node->next) - { - if (!node->local.inlinable || !node->callers) - continue; - if (dump_file) - fprintf (dump_file, "Considering inline candidate %s.\n", cgraph_node_name (node)); + if (node->analyzed) + { + struct inline_summary *info = inline_summary (node); - node->global.estimated_growth = INT_MIN; - if (!cgraph_default_inline_p (node, &failed_reason)) - { - cgraph_set_inline_failed (node, failed_reason); - continue; - } + if (!info->inlinable || !node->callers) + { + struct cgraph_edge *e; + for (e = node->callers; e; e = e->next_caller) + { + gcc_assert (e->inline_failed); + e->inline_failed = CIF_FUNCTION_NOT_INLINABLE; + } + continue; + } + if (dump_file) + fprintf (dump_file, "Considering inline candidate %s.\n", cgraph_node_name (node)); - for (edge = node->callers; edge; edge = edge->next_caller) - if (edge->inline_failed) + info->estimated_growth = INT_MIN; + if (!cgraph_default_inline_p (node, &failed_reason)) { - gcc_assert (!edge->aux); - edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge); + cgraph_set_inline_failed (node, failed_reason); + continue; } - } + + for (edge = node->callers; edge; edge = edge->next_caller) + if (edge->inline_failed) + { + gcc_assert (!edge->aux); + edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge); + } + } max_size = compute_max_insns (overall_size); min_size = overall_size; @@ -963,7 +986,7 @@ cgraph_decide_inlining_of_small_functions (void) fprintf (dump_file, "\nConsidering %s with %i size\n", cgraph_node_name (edge->callee), - edge->callee->global.size); + inline_summary (edge->callee)->size); fprintf (dump_file, " to be inlined into %s in %s:%i\n" " Estimated growth after inlined into all callees is %+i insns.\n" @@ -1007,7 +1030,7 @@ cgraph_decide_inlining_of_small_functions (void) if (where->global.inlined_to) { edge->inline_failed - = (edge->callee->local.disregard_inline_limits + = (inline_summary (edge->callee)->disregard_inline_limits ? CIF_RECURSIVE_INLINING : CIF_UNSPECIFIED); if (dump_file) fprintf (dump_file, " inline_failed:Recursive inlining performed only for function itself.\n"); @@ -1015,7 +1038,7 @@ cgraph_decide_inlining_of_small_functions (void) } } - if (edge->callee->local.disregard_inline_limits) + if (inline_summary (edge->callee)->disregard_inline_limits) ; else if (!cgraph_maybe_hot_edge_p (edge)) not_good = CIF_UNLIKELY_CALL; @@ -1112,8 +1135,8 @@ cgraph_decide_inlining_of_small_functions (void) " Inlined into %s which now has time %i and size %i," "net change of %+i.\n", cgraph_node_name (edge->caller), - edge->caller->global.time, - edge->caller->global.size, + inline_summary (edge->caller)->time, + inline_summary (edge->caller)->size, overall_size - old_size); } if (min_size > overall_size) @@ -1142,7 +1165,7 @@ cgraph_decide_inlining_of_small_functions (void) fprintf (dump_file, "\nSkipping %s with %i size\n", cgraph_node_name (edge->callee), - edge->callee->global.size); + inline_summary (edge->callee)->size); fprintf (dump_file, " called by %s in %s:%i\n" " Estimated growth after inlined into all callees is %+i insns.\n" @@ -1159,7 +1182,7 @@ cgraph_decide_inlining_of_small_functions (void) if (dump_flags & TDF_DETAILS) cgraph_edge_badness (edge, true); } - if (!edge->callee->local.disregard_inline_limits && edge->inline_failed) + if (!inline_summary (edge->callee)->disregard_inline_limits && edge->inline_failed) edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT; } @@ -1287,13 +1310,14 @@ cgraph_decide_inlining (void) if (node->analyzed) { struct cgraph_edge *e; + struct inline_summary *info = inline_summary (node); - gcc_assert (inline_summary (node)->self_size == node->global.size); + gcc_assert (info->self_size == info->size); if (!DECL_EXTERNAL (node->decl)) - initial_size += node->global.size; + initial_size += info->size; for (e = node->callees; e; e = e->next_callee) { - int benefit = (inline_summary (node)->time_inlining_benefit + int benefit = (info->time_inlining_benefit + e->call_stmt_time); if (max_count < e->count) max_count = e->count; @@ -1362,7 +1386,7 @@ cgraph_decide_inlining (void) && !node->callers->next_caller && !node->global.inlined_to && cgraph_will_be_removed_from_program_if_no_direct_calls (node) - && node->local.inlinable + && inline_summary (node)->inlinable && cgraph_function_body_availability (node) >= AVAIL_AVAILABLE && node->callers->inline_failed && node->callers->caller != node @@ -1377,11 +1401,11 @@ cgraph_decide_inlining (void) { fprintf (dump_file, "\nConsidering %s size %i.\n", - cgraph_node_name (node), node->global.size); + cgraph_node_name (node), inline_summary (node)->size); fprintf (dump_file, " Called once from %s %i insns.\n", cgraph_node_name (node->callers->caller), - node->callers->caller->global.size); + inline_summary (node->callers->caller)->size); } if (cgraph_check_inline_limits (node->callers, &reason)) @@ -1393,7 +1417,7 @@ cgraph_decide_inlining (void) " Inlined into %s which now has %i size" " for a net change of %+i size.\n", cgraph_node_name (caller), - caller->global.size, + inline_summary (caller)->size, overall_size - old_size); } else @@ -1442,7 +1466,7 @@ leaf_node_p (struct cgraph_node *n) static bool cgraph_edge_early_inlinable_p (struct cgraph_edge *e, FILE *file) { - if (!e->callee->local.inlinable) + if (!inline_summary (e->callee)->inlinable) { if (file) fprintf (file, "Not inlining: Function not inlinable.\n"); @@ -1482,7 +1506,7 @@ cgraph_perform_always_inlining (struct cgraph_node *node) for (e = node->callees; e; e = e->next_callee) { - if (!e->callee->local.disregard_inline_limits) + if (!inline_summary (e->callee)->disregard_inline_limits) continue; if (dump_file) @@ -1524,16 +1548,16 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node) /* Never inline regular functions into always-inline functions during incremental inlining. */ - if (node->local.disregard_inline_limits) + if (inline_summary (node)->disregard_inline_limits) return false; for (e = node->callees; e; e = e->next_callee) { int allowed_growth = 0; - if (!e->callee->local.inlinable + if (!inline_summary (e->callee)->inlinable || !e->inline_failed - || e->callee->local.disregard_inline_limits) + || inline_summary (e->callee)->disregard_inline_limits) continue; /* Do not consider functions not declared inline. */ |