GCC Middle and Back End API Reference
ipa-inline.c File Reference

Functions

static bool caller_growth_limits ()
static void report_inline_failed_reason ()
static bool can_inline_edge_p (struct cgraph_edge *e, bool report, bool disregard_limits=false)
static bool can_early_inline_edge_p ()
static int num_calls ()
static bool want_early_inline_function_p ()
gcov_type compute_uninlined_call_time (struct inline_summary *callee_info, struct cgraph_edge *edge)
gcov_type compute_inlined_call_time (struct cgraph_edge *edge, int edge_time)
static bool big_speedup_p ()
static bool want_inline_small_function_p ()
static bool want_inline_self_recursive_call_p (struct cgraph_edge *edge, struct cgraph_node *outer_node, bool peeling, int depth)
static bool check_caller_edge ()
static bool want_inline_function_to_all_callers_p ()
static int relative_time_benefit (struct inline_summary *callee_info, struct cgraph_edge *edge, int edge_time)
static int edge_badness ()
static void update_edge_key ()
static void reset_edge_caches ()
static void update_caller_keys (fibheap_t heap, struct cgraph_node *node, bitmap updated_nodes, struct cgraph_edge *check_inlinablity_for)
static void update_callee_keys (fibheap_t heap, struct cgraph_node *node, bitmap updated_nodes)
static void lookup_recursive_calls (struct cgraph_node *node, struct cgraph_node *where, fibheap_t heap)
static bool recursive_inlining (struct cgraph_edge *edge, vec< cgraph_edge_p > *new_edges)
static int compute_max_insns ()
static void add_new_edges_to_heap ()
static void heap_edge_removal_hook ()
bool speculation_useful_p ()
static void resolve_noninline_speculation ()
static void inline_small_functions ()
static void flatten_function ()
static unsigned int ipa_inline ()
static bool inline_always_inline_functions ()
static bool early_inline_small_functions ()
static unsigned int early_inliner ()
gimple_opt_passmake_pass_early_inline ()
static bool gate_ipa_inline ()
ipa_opt_pass_dmake_pass_ipa_inline ()

Variables

static int overall_size
static gcov_type max_count

Function Documentation

static void add_new_edges_to_heap ( )
static
Compute badness of all edges in NEW_EDGES and add them to the HEAP.   

References cgraph_edge::aux, can_inline_edge_p(), edge_badness(), cgraph_edge::inline_failed, and want_inline_small_function_p().

Referenced by inline_small_functions().

static bool big_speedup_p ( )
static
Return true if the speedup for inlining E is bigger than
   PARAM_MAX_INLINE_MIN_SPEEDUP.   

References cgraph_edge::callee, compute_inlined_call_time(), compute_uninlined_call_time(), and estimate_edge_time().

Referenced by edge_badness(), and want_inline_small_function_p().

static bool caller_growth_limits ( )
static
Return false when inlining edge E would lead to violating
   limits on function unit growth or stack usage growth.  

   The relative function body growth limit is present generally
   to avoid problems with non-linear behavior of the compiler.
   To allow inlining huge functions into tiny wrapper, the limit
   is always based on the bigger of the two functions considered.

   For stack growth limits we always base the growth in stack usage
   of the callers.  We want to prevent applications from segfaulting
   on stack overflow when functions with huge stack frames gets
   inlined.  

References cgraph_edge::callee, cgraph_edge::caller, cgraph_node::callers, cgraph_function_or_thunk_node(), estimate_size_after_inlining(), inline_summary::estimated_self_stack_size, inline_summary::estimated_stack_size, cgraph_node::global, HOST_WIDE_INT, cgraph_edge::inline_failed, inline_summary(), cgraph_global_info::inlined_to, limit, inline_summary::self_size, inline_summary::size, and inline_summary::stack_frame_offset.

Referenced by can_inline_edge_p().

static bool can_inline_edge_p ( struct cgraph_edge e,
bool  report,
bool  disregard_limits = false 
)
static
static bool check_caller_edge ( )
static
Return true when NODE has caller other than EDGE. 
   Worker for cgraph_for_node_and_aliases.   

References cgraph_node::callers.

Referenced by want_inline_function_to_all_callers_p().

gcov_type compute_inlined_call_time ( struct cgraph_edge edge,
int  edge_time 
)
inline
Same as compute_uinlined_call_time but compute time when inlining
   does happen.   

References cgraph_edge::caller, cgraph_edge::frequency, cgraph_node::global, inline_summary(), cgraph_global_info::inlined_to, and inline_summary::time.

Referenced by big_speedup_p(), edge_badness(), and relative_time_benefit().

static int compute_max_insns ( )
static
Given whole compilation unit estimate of INSNS, compute how large we can
   allow the unit to grow.   

References HOST_WIDEST_INT.

Referenced by inline_small_functions().

gcov_type compute_uninlined_call_time ( struct inline_summary callee_info,
struct cgraph_edge edge 
)
inline
Compute time of the edge->caller + edge->callee execution when inlining
   does not happen.   

References cgraph_edge::caller, cgraph_edge::frequency, cgraph_node::global, inline_summary(), cgraph_global_info::inlined_to, and inline_summary::time.

Referenced by big_speedup_p(), edge_badness(), and relative_time_benefit().

static bool early_inline_small_functions ( )
static
static bool gate_ipa_inline ( )
static
When to run IPA inlining.  Inlining of always-inline functions
   happens during early inlining.

   Enable inlining unconditoinally at -flto.  We need size estimates to
   drive partitioning.   
static void heap_edge_removal_hook ( )
static
Remove EDGE from the fibheap.   

References cgraph_edge::aux, cgraph_edge::callee, and reset_node_growth_cache().

Referenced by inline_small_functions().

static void inline_small_functions ( )
static
We use greedy algorithm for inlining of small functions:
   All inline candidates are put into prioritized heap ordered in
   increasing badness.

   The inlining of small functions is bounded by unit growth parameters.   

References add_new_edges_to_heap(), symtab_node_base::aux, cgraph_edge::aux, bitmap_clear(), cgraph_edge::call_stmt, cgraph_edge::callee, cgraph_node::callees, cgraph_edge::caller, cgraph_node::callers, can_inline_edge_p(), cgraph_add_edge_removal_hook(), cgraph_edge_recursive_p(), cgraph_function_or_thunk_node(), cgraph_function_with_gimple_body_p(), cgraph_n_nodes, cgraph_node_name(), cgraph_remove_edge_removal_hook(), cgraph_resolve_speculation(), compute_max_insns(), count, cgraph_edge::count, symtab_node_base::decl, dump_file, dump_flags, edge_badness(), edge_removal_hook_holder, estimate_edge_growth(), estimate_growth(), free(), free_growth_caches(), cgraph_edge::frequency, gimple_filename(), gimple_lineno(), cgraph_node::global, inline_summary::growth, heap_edge_removal_hook(), HOST_WIDEST_INT_PRINT_DEC, initialize_growth_caches(), inline_call(), cgraph_edge::inline_failed, inline_summary(), inline_update_overall_summary(), cgraph_global_info::inlined_to, ipa_free_postorder_info(), ipa_reduced_postorder(), max_count, cgraph_edge::next_callee, cgraph_edge::next_caller, ipa_dfs_info::next_cycle, symtab_node_base::order, order, overall_size, profile_info, recursive_inlining(), report_inline_failed_reason(), reset_edge_caches(), reset_edge_growth_cache(), reset_node_growth_cache(), resolve_noninline_speculation(), ipa_dfs_info::scc_no, inline_summary::scc_no, inline_summary::size, speculation_useful_p(), cgraph_edge::speculative, cgraph_node::symbol, cgraph_node::thunk, cgraph_thunk_info::thunk_p, inline_summary::time, update_callee_keys(), update_caller_keys(), update_edge_key(), vNULL, want_inline_self_recursive_call_p(), and want_inline_small_function_p().

Referenced by ipa_inline().

static void lookup_recursive_calls ( struct cgraph_node node,
struct cgraph_node where,
fibheap_t  heap 
)
static
Enqueue all recursive calls from NODE into priority queue depending on
   how likely we want to recursively inline the call.   

References AVAIL_OVERWRITABLE, cgraph_edge::callee, cgraph_node::callees, cgraph_function_or_thunk_node(), cgraph_edge::count, cgraph_edge::frequency, cgraph_edge::inline_failed, max_count, and cgraph_edge::next_callee.

Referenced by recursive_inlining().

gimple_opt_pass* make_pass_early_inline ( )
ipa_opt_pass_d* make_pass_ipa_inline ( )
static int relative_time_benefit ( struct inline_summary callee_info,
struct cgraph_edge edge,
int  edge_time 
)
inlinestatic
Return relative time improvement for inlining EDGE in range
   1...RELATIVE_TIME_BENEFIT_RANGE   

References cgraph_edge::caller, compute_inlined_call_time(), compute_uninlined_call_time(), symtab_node_base::decl, cgraph_node::global, cgraph_global_info::inlined_to, and cgraph_node::symbol.

Referenced by edge_badness().

static void resolve_noninline_speculation ( )
static
static void update_callee_keys ( fibheap_t  heap,
struct cgraph_node node,
bitmap  updated_nodes 
)
static
Recompute HEAP nodes for each uninlined call in NODE.
   This is used when we know that edge badnesses are going only to increase
   (we introduced new call site) and thus all we need is to insert newly
   created edges into heap.   

References cgraph_edge::aux, AVAIL_AVAILABLE, bitmap_bit_p(), cgraph_edge::callee, cgraph_node::callees, cgraph_edge::caller, cgraph_node::callers, can_inline_edge_p(), cgraph_function_or_thunk_node(), cgraph_edge::inline_failed, cgraph_edge::next_callee, report_inline_failed_reason(), cgraph_node::uid, update_edge_key(), and want_inline_small_function_p().

Referenced by inline_small_functions(), and resolve_noninline_speculation().

static void update_caller_keys ( fibheap_t  heap,
struct cgraph_node node,
bitmap  updated_nodes,
struct cgraph_edge check_inlinablity_for 
)
static
Recompute HEAP nodes for each of caller of NODE.
   UPDATED_NODES track nodes we already visited, to avoid redundant work.
   When CHECK_INLINABLITY_FOR is set, re-check for specified edge that
   it is inlinable. Otherwise check all edges.   

References symtab_node_base::alias, cgraph_edge::aux, bitmap_set_bit(), cgraph_node::callers, can_inline_edge_p(), cgraph_node::global, cgraph_edge::inline_failed, cgraph_global_info::inlined_to, IPA_REF_ALIAS, ipa_ref_referring_node(), cgraph_edge::next_caller, symtab_node_base::ref_list, report_inline_failed_reason(), cgraph_node::symbol, cgraph_node::uid, update_edge_key(), and want_inline_small_function_p().

Referenced by inline_small_functions(), and resolve_noninline_speculation().

static void update_edge_key ( )
inlinestatic
static bool want_inline_function_to_all_callers_p ( )
static
Decide if inlining NODE would reduce unit size by eliminating
   the offline copy of function.  
   When COLD is true the cold calls are considered, too.   

References cgraph_node::callers, can_inline_edge_p(), cgraph_for_node_and_aliases(), cgraph_function_or_thunk_node(), cgraph_maybe_hot_edge_p(), check_caller_edge(), estimate_growth(), and cgraph_edge::next_caller.

Referenced by ipa_inline().

static bool want_inline_self_recursive_call_p ( struct cgraph_edge edge,
struct cgraph_node outer_node,
bool  peeling,
int  depth 
)
static
EDGE is self recursive edge.
   We hand two cases - when function A is inlining into itself
   or when function A is being inlined into another inliner copy of function
   A within function B.  

   In first case OUTER_NODE points to the toplevel copy of A, while
   in the second case OUTER_NODE points to the outermost copy of A in B.

   In both cases we want to be extra selective since
   inlining the call will just introduce new recursive calls to appear.   

References cgraph_edge::caller, cgraph_node::callers, cgraph_maybe_hot_edge_p(), cgraph_node::count, cgraph_edge::count, symtab_node_base::decl, dump_file, cgraph_edge::frequency, cgraph_node::global, cgraph_global_info::inlined_to, max_count, max_depth, and cgraph_node::symbol.

Referenced by inline_small_functions(), and recursive_inlining().


Variable Documentation

int overall_size
static
@verbatim Inlining decision heuristics.

Copyright (C) 2003-2013 Free Software Foundation, Inc. Contributed by Jan Hubicka

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see http://www.gnu.org/licenses/.

Inlining decision heuristics

    The implementation of inliner is organized as follows:

    inlining heuristics limits

      can_inline_edge_p allow to check that particular inlining is allowed
      by the limits specified by user (allowed function growth, growth and so
      on).

      Functions are inlined when it is obvious the result is profitable (such
      as functions called once or when inlining reduce code size).
      In addition to that we perform inlining of small functions and recursive
      inlining.

    inlining heuristics

       The inliner itself is split into two passes:

       pass_early_inlining

         Simple local inlining pass inlining callees into current function.
         This pass makes no use of whole unit analysis and thus it can do only
         very simple decisions based on local properties.

         The strength of the pass is that it is run in topological order
         (reverse postorder) on the callgraph. Functions are converted into SSA
         form just before this pass and optimized subsequently. As a result, the
         callees of the function seen by the early inliner was already optimized
         and results of early inlining adds a lot of optimization opportunities
         for the local optimization.

         The pass handle the obvious inlining decisions within the compilation
         unit - inlining auto inline functions, inlining for size and
         flattening.

         main strength of the pass is the ability to eliminate abstraction
         penalty in C++ code (via combination of inlining and early
         optimization) and thus improve quality of analysis done by real IPA
         optimizers.

         Because of lack of whole unit knowledge, the pass can not really make
         good code size/performance tradeoffs.  It however does very simple
         speculative inlining allowing code size to grow by
         EARLY_INLINING_INSNS when callee is leaf function.  In this case the
         optimizations performed later are very likely to eliminate the cost.

       pass_ipa_inline

         This is the real inliner able to handle inlining with whole program
         knowledge. It performs following steps:

         1) inlining of small functions.  This is implemented by greedy
         algorithm ordering all inlinable cgraph edges by their badness and
         inlining them in this order as long as inline limits allows doing so.

         This heuristics is not very good on inlining recursive calls. Recursive
         calls can be inlined with results similar to loop unrolling. To do so,
         special purpose recursive inliner is executed on function when
         recursive edge is met as viable candidate.

         2) Unreachable functions are removed from callgraph.  Inlining leads
         to devirtualization and other modification of callgraph so functions
         may become unreachable during the process. Also functions declared as
         extern inline or virtual functions are removed, since after inlining
         we no longer need the offline bodies.

         3) Functions called once and not exported from the unit are inlined.
         This should almost always lead to reduction of code size by eliminating
         the need for offline copy of the function.   
Statistics we collect about inlining algorithm.   

Referenced by inline_small_functions(), and recursive_inlining().