GCC Middle and Back End API Reference
ipa-inline-analysis.c File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "tree-inline.h"
#include "langhooks.h"
#include "flags.h"
#include "diagnostic.h"
#include "gimple-pretty-print.h"
#include "params.h"
#include "tree-pass.h"
#include "coverage.h"
#include "ggc.h"
#include "gimple.h"
#include "gimple-ssa.h"
#include "tree-cfg.h"
#include "tree-phinodes.h"
#include "ssa-iterators.h"
#include "tree-ssanames.h"
#include "tree-ssa-loop-niter.h"
#include "tree-ssa-loop.h"
#include "ipa-prop.h"
#include "lto-streamer.h"
#include "data-streamer.h"
#include "tree-streamer.h"
#include "ipa-inline.h"
#include "alloc-pool.h"
#include "cfgloop.h"
#include "tree-scalar-evolution.h"
#include "ipa-utils.h"
#include "cilk.h"
Include dependency graph for ipa-inline-analysis.c:

Data Structures

struct  agg_position_info
struct  record_modified_bb_info
struct  growth_data

Macros

#define MAX_TIME   500000
#define NUM_CONDITIONS   32
#define IS_NOT_CONSTANT   ERROR_MARK
#define CHANGED   IDENTIFIER_NODE

Typedefs

typedef struct predicate predicate_t

Enumerations

enum  predicate_conditions { predicate_false_condition = 0, predicate_not_inlined_condition = 1, predicate_first_dynamic_condition = 2 }

Functions

static void inline_node_removal_hook (struct cgraph_node *, void *)
static void inline_node_duplication_hook (struct cgraph_node *, struct cgraph_node *, void *)
static void inline_edge_removal_hook (struct cgraph_edge *, void *)
static void inline_edge_duplication_hook (struct cgraph_edge *, struct cgraph_edge *, void *)
static struct predicate true_predicate ()
static struct predicate single_cond_predicate ()
static struct predicate false_predicate ()
static bool true_predicate_p ()
static bool false_predicate_p ()
static struct predicate not_inlined_predicate ()
static struct predicate add_condition (struct inline_summary *summary, int operand_num, struct agg_position_info *aggpos, enum tree_code code, tree val)
static void add_clause ()
static struct predicate and_predicates (conditions conditions, struct predicate *p, struct predicate *p2)
static bool predicates_equal_p ()
static struct predicate or_predicates (conditions conditions, struct predicate *p, struct predicate *p2)
static bool evaluate_predicate ()
static int predicate_probability (conditions conds, struct predicate *p, clause_t possible_truths, vec< inline_param_summary_t > inline_param_summary)
static void dump_condition ()
static void dump_clause ()
static void dump_predicate ()
void dump_inline_hints ()
static void account_size_time (struct inline_summary *summary, int size, int time, struct predicate *pred)
static void edge_set_predicate ()
static void set_hint_predicate ()
static clause_t evaluate_conditions_for_known_args (struct cgraph_node *node, bool inline_p, vec< tree > known_vals, vec< ipa_agg_jump_function_p > known_aggs)
static void evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, clause_t *clause_ptr, vec< tree > *known_vals_ptr, vec< tree > *known_binfos_ptr, vec< ipa_agg_jump_function_p > *known_aggs_ptr)
static void inline_summary_alloc ()
static void reset_inline_edge_summary ()
static void reset_inline_summary ()
static struct predicate remap_predicate_after_duplication (struct predicate *p, clause_t possible_truths, struct inline_summary *info)
static void remap_hint_predicate_after_duplication (struct predicate **p, clause_t possible_truths, struct inline_summary *info)
void initialize_growth_caches ()
void free_growth_caches ()
static void dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node, struct inline_summary *info)
void dump_inline_summary ()
DEBUG_FUNCTION void debug_inline_summary ()
void dump_inline_summaries ()
void initialize_inline_failed ()
static bool mark_modified (ao_ref *ao, tree vdef, void *data)
static tree unmodified_parm_1 ()
static tree unmodified_parm ()
static bool unmodified_parm_or_parm_agg_item (struct ipa_node_params *info, gimple stmt, tree op, int *index_p, struct agg_position_info *aggpos)
static int eliminated_by_inlining_prob ()
static void set_cond_stmt_execution_predicate (struct ipa_node_params *info, struct inline_summary *summary, basic_block bb)
static void set_switch_stmt_execution_predicate (struct ipa_node_params *info, struct inline_summary *summary, basic_block bb)
static void compute_bb_predicates (struct cgraph_node *node, struct ipa_node_params *parms_info, struct inline_summary *summary)
static struct predicate will_be_nonconstant_expr_predicate (struct ipa_node_params *info, struct inline_summary *summary, tree expr, vec< predicate_t > nonconstant_names)
static struct predicate will_be_nonconstant_predicate (struct ipa_node_params *info, struct inline_summary *summary, gimple stmt, vec< predicate_t > nonconstant_names)
static bool record_modified ()
static int param_change_prob ()
static bool phi_result_unknown_predicate (struct ipa_node_params *info, struct inline_summary *summary, basic_block bb, struct predicate *p, vec< predicate_t > nonconstant_names)
static void predicate_for_phi_result (struct inline_summary *summary, gimple phi, struct predicate *p, vec< predicate_t > nonconstant_names)
static struct predicate array_index_predicate (struct inline_summary *info, vec< predicate_t > nonconstant_names, tree op)
static gimple find_foldable_builtin_expect ()
static void estimate_function_body_sizes ()
void compute_inline_parameters ()
static unsigned int compute_inline_parameters_for_current ()
gimple_opt_passmake_pass_inline_parameters ()
static bool estimate_edge_devirt_benefit (struct cgraph_edge *ie, int *size, int *time, vec< tree > known_vals, vec< tree > known_binfos, vec< ipa_agg_jump_function_p > known_aggs)
static void estimate_edge_size_and_time (struct cgraph_edge *e, int *size, int *time, int prob, vec< tree > known_vals, vec< tree > known_binfos, vec< ipa_agg_jump_function_p > known_aggs, inline_hints *hints)
static void estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, inline_hints *hints, clause_t possible_truths, vec< tree > known_vals, vec< tree > known_binfos, vec< ipa_agg_jump_function_p > known_aggs)
static void estimate_node_size_and_time (struct cgraph_node *node, clause_t possible_truths, vec< tree > known_vals, vec< tree > known_binfos, vec< ipa_agg_jump_function_p > known_aggs, int *ret_size, int *ret_time, inline_hints *ret_hints, vec< inline_param_summary_t > inline_param_summary)
void estimate_ipcp_clone_size_and_time (struct cgraph_node *node, vec< tree > known_vals, vec< tree > known_binfos, vec< ipa_agg_jump_function_p > known_aggs, int *ret_size, int *ret_time, inline_hints *hints)
static struct predicate remap_predicate (struct inline_summary *info, struct inline_summary *callee_info, struct predicate *p, vec< int > operand_map, vec< int > offset_map, clause_t possible_truths, struct predicate *toplev_predicate)
static void inline_update_callee_summaries ()
static void remap_edge_change_prob (struct cgraph_edge *inlined_edge, struct cgraph_edge *edge)
static void remap_edge_summaries (struct cgraph_edge *inlined_edge, struct cgraph_node *node, struct inline_summary *info, struct inline_summary *callee_info, vec< int > operand_map, vec< int > offset_map, clause_t possible_truths, struct predicate *toplev_predicate)
static void remap_hint_predicate (struct inline_summary *info, struct inline_summary *callee_info, struct predicate **hint, vec< int > operand_map, vec< int > offset_map, clause_t possible_truths, struct predicate *toplev_predicate)
void inline_merge_summary ()
void inline_update_overall_summary ()
int simple_edge_hints ()
int do_estimate_edge_time ()
int do_estimate_edge_size ()
inline_hints do_estimate_edge_hints ()
int estimate_time_after_inlining (struct cgraph_node *node, struct cgraph_edge *edge)
int estimate_size_after_inlining (struct cgraph_node *node, struct cgraph_edge *edge)
static bool do_estimate_growth_1 ()
int do_estimate_growth ()
static void inline_indirect_intraprocedural_analysis ()
static void inline_analyze_function ()
static void add_new_function ()
void inline_generate_summary ()
static struct predicate read_predicate ()
static void read_inline_edge_summary ()
static void inline_read_section (struct lto_file_decl_data *file_data, const char *data, size_t len)
void inline_read_summary ()
static void write_predicate ()
static void write_inline_edge_summary ()
void inline_write_summary ()
void inline_free_summary ()

Variables

static struct
cgraph_node_hook_list
function_insertion_hook_holder
static struct
cgraph_node_hook_list
node_removal_hook_holder
static struct
cgraph_2node_hook_list
node_duplication_hook_holder
static struct
cgraph_2edge_hook_list
edge_duplication_hook_holder
static struct
cgraph_edge_hook_list
edge_removal_hook_holder
vec< inline_summary_t, va_gc > * inline_summary_vec
vec< inline_edge_summary_tinline_edge_summary_vec
vec< int > node_growth_cache
vec< edge_growth_cache_entryedge_growth_cache
static alloc_pool edge_predicate_pool

Macro Definition Documentation

#define CHANGED   IDENTIFIER_NODE

Special condition code we use to represent test that operand is not changed across invocation of the function. When operand IS_NOT_CONSTANT it is always CHANGED, however i.e. loop invariants can be NOT_CHANGED given percentage of executions even when they are not compile time constants.

Referenced by evaluate_predicate(), and set_hint_predicate().

#define IS_NOT_CONSTANT   ERROR_MARK

Special condition code we use to represent test that operand is compile time constant.

#define MAX_TIME   500000

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/. Analysis used by the inliner and other passes limiting code size growth.

We estimate for each function

  • function body size
  • average function execution time
  • inlining size benefit (that is how much of function body size and its call sequence is expected to disappear by inlining)
  • inlining time benefit
  • function frame size For each call
  • call statement size and time

inlinie_summary datastructures store above information locally (i.e. parameters of the function itself) and globally (i.e. parameters of the function created by applying all the inline decisions already present in the callgraph).

We provide accestor to the inline_summary datastructure and basic logic updating the parameters when inlining is performed.

The summaries are context sensitive. Context means 1) partial assignment of known constant values of operands 2) whether function is inlined into the call or not. It is easy to add more variants. To represent function size and time that depends on context (i.e. it is known to be optimized away when context is known either by inlining or from IP-CP and clonning), we use predicates. Predicates are logical formulas in conjunctive-disjunctive form consisting of clauses. Clauses are bitmaps specifying what conditions must be true. Conditions are simple test of the form described above.

In order to make predicate (possibly) true, all of its clauses must be (possibly) true. To make clause (possibly) true, one of conditions it mentions must be (possibly) true. There are fixed bounds on number of clauses and conditions and all the manipulation functions are conservative in positive direction. I.e. we may lose precision by thinking that predicate may be true even when it is not.

estimate_edge_size and estimate_edge_growth can be used to query function size/time in the given context. inline_merge_summary merges properties of caller and callee after inlining.

Finally pass_inline_parameters is exported. This is used to drive computation of function parameters used by the early inliner. IPA inlined performs analysis via its analyze_function method. Estimate runtime of function can easilly run into huge numbers with many nested loops. Be sure we can compute time * INLINE_SIZE_SCALE * 2 in an integer. For anything larger we use gcov_type.

Referenced by dump_inline_hints(), and inline_update_overall_summary().

#define NUM_CONDITIONS   32

Number of bits in integer, but we really want to be stable across different hosts.

Referenced by evaluate_predicate().


Typedef Documentation

typedef struct predicate predicate_t

We keep info about constantness of SSA names.


Enumeration Type Documentation

Enumerator:
predicate_false_condition 
predicate_not_inlined_condition 
predicate_first_dynamic_condition 

Function Documentation

static void account_size_time ( struct inline_summary summary,
int  size,
int  time,
struct predicate pred 
)
static

Record SIZE and TIME under condition PRED into the inline summary.

We need to create initial empty unconitional clause, but otherwie we don't need to account empty times and sizes.

 Watch overflow that might result from insane profiles.   
static void add_clause ( )
inlinestatic

Add clause CLAUSE into the predicate P.

 True clause.   
 False clause makes the whole predicate false.  Kill the other variants.   
 No one should be sily enough to add false into nontrivial clauses.   
 Look where to insert the clause.  At the same time prune out
 clauses of P that are implied by the new clause and thus
 redundant.   
     If p->clause[i] implies clause, there is nothing to add.   
         We had nothing to add, none of clauses should've become
         redundant.   
     If clause implies p->clause[i], then p->clause[i] becomes redundant.
     Otherwise the p->clause[i] has to stay.   
 Look for clauses that are obviously true.  I.e.
 op0 == 5 || op0 != 5.   
     We have no way to represent !CHANGED and !IS_NOT_CONSTANT
     and thus there is no point for looking for them.   
 We run out of variants.  Be conservative in positive direction.   
 Keep clauses in decreasing order. This makes equivalence testing easy.   

Referenced by predicates_equal_p().

static struct predicate add_condition ( struct inline_summary summary,
int  operand_num,
struct agg_position_info aggpos,
enum tree_code  code,
tree  val 
)
staticread

Add condition to condition list CONDS. AGGPOS describes whether the used oprand is loaded from an aggregate and where in the aggregate it is. It can be NULL, which means this not a load from an aggregate.

Too many conditions. Give up and return constant true.

static void add_new_function ( )
static

Called when new function is inserted to callgraph late.

static struct predicate and_predicates ( conditions  conditions,
struct predicate p,
struct predicate p2 
)
staticread

Return P & P2.

 Avoid busy work.   
 See how far predicates match.   
 Combine the predicates rest.   

References predicate::clause, gcc_checking_assert, and MAX_CLAUSES.

static struct predicate array_index_predicate ( struct inline_summary info,
vec< predicate_t nonconstant_names,
tree  op 
)
staticread

Return predicate specifying when array index in access OP becomes non-constant.

static void compute_bb_predicates ( struct cgraph_node node,
struct ipa_node_params parms_info,
struct inline_summary summary 
)
static

For each BB in NODE attach to its AUX pointer predicate under which it is executable.

Entry block is always executable.

 A simple dataflow propagation of predicates forward in the CFG.
 TODO: work in reverse postorder.   
void compute_inline_parameters ( )

Compute parameters of functions used by inliner. EARLY is true when we compute parameters for the early inliner

 FIXME: Thunks are inlinable, but tree-inline don't know how to do that.
 Once this happen, we will need to more curefully predict call
 statement size.   
 Even is_gimple_min_invariant rely on current_function_decl.   
 Estimate the stack size for the function if we're optimizing.   
 Can this function be inlined at all?   
 Type attributes can use parameter indices to describe them.   
     Otherwise, inlinable functions always can change signature.   
         Functions calling builtin_apply can not change signature.   
 Inlining characteristics are maintained by the cgraph_mark_inline.   

Referenced by cgraph_process_new_functions().

static unsigned int compute_inline_parameters_for_current ( )
static

Compute parameters of functions used by inliner using current_function_decl.

DEBUG_FUNCTION void debug_inline_summary ( )

References unmodified_parm_1().

inline_hints do_estimate_edge_hints ( )

Estimate the growth of the caller when inlining EDGE. Only to be called via estimate_edge_size.

When we do caching, use do_estimate_edge_time to populate the entry.

 Early inliner runs without caching, go ahead and do the dirty work.   
int do_estimate_edge_size ( )

Return estimated callee growth after inlining EDGE. Only to be called via estimate_edge_size.

When we do caching, use do_estimate_edge_time to populate the entry.

 Early inliner runs without caching, go ahead and do the dirty work.   
int do_estimate_edge_time ( )

Estimate the time cost for the caller when inlining EDGE. Only to be called via estimate_edge_time, that handles the caching mechanism.

When caching, also update the cache entry. Compute both time and size, since we always need both metrics eventually.

When caching, update the cache entry.

References cgraph_edge::caller, cgraph_node::callers, estimate_edge_growth(), gcc_checking_assert, cgraph_node::global, growth_data::growth, cgraph_edge::inline_failed, cgraph_global_info::inlined_to, cgraph_edge::next_caller, growth_data::node, and growth_data::self_recursive.

int do_estimate_growth ( )

Estimate the growth caused by inlining NODE into all callees.

For self recursive functions the growth estimation really should be infinity. We don't want to return very large values because the growth plays various roles in badness computation fractions. Be sure to not return zero or negative growths.

     COMDAT functions are very often not shared across multiple units
     since they come from various template instantiations.
     Take this into account.   
static bool do_estimate_growth_1 ( )
static

Worker for do_estimate_growth. Collect growth for all callers.

static void dump_clause ( )
static

Dump clause CLAUSE.

static void dump_condition ( )
static

Dump conditional COND.

static void dump_inline_edge_summary ( FILE *  f,
int  indent,
struct cgraph_node node,
struct inline_summary info 
)
static

Dump edge summaries associated to NODE and recursively to all clones. Indent by INDENT.

void dump_inline_summaries ( )
void dump_inline_summary ( )
static void dump_predicate ( )
static

Dump predicate PREDICATE.

Referenced by dump_inline_hints(), and initialize_growth_caches().

static void edge_set_predicate ( )
static

Set predicate for edge E.

Referenced by remap_predicate().

static int eliminated_by_inlining_prob ( )
static

See if statement might disappear after inlining. 0 - means not eliminated 1 - half of statements goes away 2 - for sure it is eliminated. We are not terribly sophisticated, basically looking for simple abstraction penalty wrappers.

     Casts of parameters, loads from parameters passed by reference
     and stores to return value or parameters are often free after
     inlining dua to SRA and further combining.
     Assume that half of statements goes away.   
         Reads of parameter are expected to be free.   
         Match expressions of form &this->field. Those will most likely
         combine with something upstream after inlining.   
         When parameter is not SSA register because its address is taken
         and it is just copied into one, the statement will be completely
         free after inlining (we will copy propagate backward).    
         Reads of parameters passed by reference
         expected to be free (i.e. optimized out after inlining).   
         Copying parameter passed by reference into gimple register is
         probably also going to copy propagate, but we can't be quite
         sure.   
         Writes to parameters, parameters passed by value and return value
         (either dirrectly or passed via invisible reference) are free.  

         TODO: We ought to handle testcase like
         struct a {int a,b;};
         struct a
         retrurnsturct (void)
         {
         struct a a ={1,2};
         return a;
         }

         This translate into:

         retrurnsturct ()
         {
         int a$b;
         int a$a;
         struct a a;
         struct a D.2739;

         <bb 2>:
         D.2739.a = 1;
         D.2739.b = 2;
         return D.2739;

         }
         For that we either need to copy ipa-split logic detecting writes
         to return value.   
static void estimate_calls_size_and_time ( struct cgraph_node node,
int *  size,
int *  time,
inline_hints hints,
clause_t  possible_truths,
vec< tree known_vals,
vec< tree known_binfos,
vec< ipa_agg_jump_function_p known_aggs 
)
static

Increase SIZE and TIME for size and time needed to handle all calls in NODE. POSSIBLE_TRUTHS, KNOWN_VALS and KNOWN_BINFOS describe context of the call site.

Predicates of calls shall not use NOT_CHANGED codes, sowe do not need to compute probabilities.

References estimate_node_size_and_time(), evaluate_conditions_for_known_args(), and vNULL.

static bool estimate_edge_devirt_benefit ( struct cgraph_edge ie,
int *  size,
int *  time,
vec< tree known_vals,
vec< tree known_binfos,
vec< ipa_agg_jump_function_p known_aggs 
)
static

Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS and KNOWN_BINFOS.

Account for difference in cost between indirect and direct calls.

static void estimate_edge_size_and_time ( struct cgraph_edge e,
int *  size,
int *  time,
int  prob,
vec< tree known_vals,
vec< tree known_binfos,
vec< ipa_agg_jump_function_p known_aggs,
inline_hints hints 
)
inlinestatic

Increase SIZE and TIME for size and time needed to handle edge E.

static void estimate_function_body_sizes ( )
static

Compute function body size parameters for NODE. When EARLY is true, we compute only simple summaries without non-trivial predicates to drive the early inliner.

 Estimate static overhead for function prologue/epilogue and alignment.  
 Benefits are scaled by probability of elimination that is in range
 <0,2>.   
 When we run into maximal number of entries, we assign everything to the
 constant truth case.  Be sure to have it in list.  
     TODO: Obviously predicates can be propagated down across CFG.   
         This relation stmt should be folded after we remove
         buildin_expect call. Adjust the cost here.   
             Special case: results of BUILT_IN_CONSTANT_P will be always
             resolved as constant.  We however don't want to optimize
             out the cgraph edges.   
         TODO: When conditional jump or swithc is known to be constant, but
         we did not translate it into the predicates, we really can account
         just maximum of the possible paths.   
             We account everything but the calls.  Calls have their own
             size/time info attached to cgraph edges.  This is necessary
             in order to make the cost disappear after inlining.   
               This is slightly inprecise.  We may want to represent each
               loop with independent predicate.   
                     This is slightly inprecise.  We may want to represent
                     each loop with independent predicate.   
void estimate_ipcp_clone_size_and_time ( struct cgraph_node node,
vec< tree known_vals,
vec< tree known_binfos,
vec< ipa_agg_jump_function_p known_aggs,
int *  ret_size,
int *  ret_time,
inline_hints hints 
)

Estimate size and time needed to execute callee of EDGE assuming that parameters known to be constant at caller of EDGE are propagated. KNOWN_VALS and KNOWN_BINFOS are vectors of assumed known constant values and types for parameters.

References combine_probabilities(), inline_edge_summary(), IPA_EDGE_REF, ipa_get_cs_argument_count(), ipa_get_ith_jump_func(), ipa_get_jf_pass_through_formal_id(), IPA_JF_PASS_THROUGH, ipa_node_params_vector, inline_edge_summary::param, and ipa_jump_func::type.

static void estimate_node_size_and_time ( struct cgraph_node node,
clause_t  possible_truths,
vec< tree known_vals,
vec< tree known_binfos,
vec< ipa_agg_jump_function_p known_aggs,
int *  ret_size,
int *  ret_time,
inline_hints ret_hints,
vec< inline_param_summary_t inline_param_summary 
)
static

Estimate size and time needed to execute NODE assuming POSSIBLE_TRUTHS clause, and KNOWN_VALS and KNOWN_BINFOS information about NODE's arguments.

Referenced by estimate_calls_size_and_time().

int estimate_size_after_inlining ( struct cgraph_node node,
struct cgraph_edge edge 
)

Estimate the size of NODE after inlining EDGE which should be an edge to either NODE or a call inlined into NODE.

References predicate::clause, gcc_assert, MAX_CLAUSES, and streamer_read_uhwi().

int estimate_time_after_inlining ( struct cgraph_node node,
struct cgraph_edge edge 
)

Estimate self time of the function NODE after inlining EDGE.

static clause_t evaluate_conditions_for_known_args ( struct cgraph_node node,
bool  inline_p,
vec< tree known_vals,
vec< ipa_agg_jump_function_p known_aggs 
)
static

KNOWN_VALS is partial mapping of parameters of NODE to constant values. KNOWN_AGGS is a vector of aggreggate jump functions for each parameter. Return clause of possible truths. When INLINE_P is true, assume that we are inlining.

ERROR_MARK means compile time invariant.

We allow call stmt to have fewer arguments than the callee function (especially for K&R style programs). So bound check here (we assume known_aggs vector, if non-NULL, has the same length as known_vals).

Referenced by estimate_calls_size_and_time().

static bool evaluate_predicate ( )
static

Having partial truth assignment in POSSIBLE_TRUTHS, return false if predicate P is known to be false.

True remains true.

 See if we can find clause we can disprove.   

References CHANGED, predicate::clause, gcc_checking_assert, i2, MAX, MAX_CLAUSES, NUM_CONDITIONS, condition::operand_num, predicate_first_dynamic_condition, and REG_BR_PROB_BASE.

static void evaluate_properties_for_edge ( struct cgraph_edge e,
bool  inline_p,
clause_t clause_ptr,
vec< tree > *  known_vals_ptr,
vec< tree > *  known_binfos_ptr,
vec< ipa_agg_jump_function_p > *  known_aggs_ptr 
)
static

Work out what conditions might be true at invocation of E.

TODO: When IPA-CP starts propagating and merging aggregate jump functions, use its knowledge of the caller too, just like the scalar case above.

Referenced by remap_edge_change_prob().

static struct predicate false_predicate ( )
staticread

Return false predicate. First clause require false condition.

References predicate::clause, gcc_checking_assert, and predicate_false_condition.

Referenced by find_foldable_builtin_expect(), record_modified(), reset_inline_summary(), and set_cond_stmt_execution_predicate().

static bool false_predicate_p ( )
inlinestatic
static gimple find_foldable_builtin_expect ( )
static

For a typical usage of __builtin_expect (a<b, 1), we may introduce an extra relation stmt: With the builtin, we have t1 = a <= b; t2 = (long int) t1; t3 = __builtin_expect (t2, 1); if (t3 != 0) goto ... Without the builtin, we have if (a<=b) goto... This affects the size/time estimation and may have an impact on the earlier inlining. Here find this pattern and fix it up later.

References basic_block_def::aux, and false_predicate().

void free_growth_caches ( void  )

Free growth caches.

void initialize_inline_failed ( )

Give initial reasons why inlining would fail on EDGE. This gets either nullified or usually overwritten by more precise reasons later.

We can't inline if the function is spawing a function.

References agg_position_info::agg_contents, agg_position_info::by_ref, gcc_checking_assert, gimple_assign_single_p(), ipa_get_param_decl_index(), SSA_NAME_DEF_STMT, SSA_NAME_IS_DEFAULT_DEF, TREE_CODE, and unmodified_parm_1().

Referenced by cgraph_create_edge_1().

static void inline_analyze_function ( )
static

Note function body size.

static void inline_edge_duplication_hook ( struct cgraph_edge src,
struct cgraph_edge dst,
void *  data 
)
static

Hook that is called by cgraph.c when a node is duplicated.

static void inline_edge_removal_hook ( struct cgraph_edge edge,
void *  data 
)
static

Keep edge cache consistent across edge removal.

void inline_free_summary ( void  )

Release inline summary.

void inline_generate_summary ( void  )

Note function body size.

When not optimizing, do not bother to analyze. Inlining is still done because edge redirection needs to happen there.

static void inline_indirect_intraprocedural_analysis ( )
static

This function performs intraprocedural analysis in NODE that is required to inline indirect calls.

void inline_merge_summary ( )

We inlined EDGE. Update summary of the function we inlined into.

    TODO: handle non-NOPs when merging.   
 We do not maintain predicates of inlined edges, free it.   


 Similarly remove param summaries.   
static void inline_node_duplication_hook ( struct cgraph_node src,
struct cgraph_node dst,
void *  data 
)
static

Hook that is called by cgraph.c when a node is duplicated.

 TODO: as an optimization, we may avoid copying conditions
 that are known to be false or true.   
 When there are any replacements in the function body, see if we can figure
 out that something was optimized out.   
     Use SRC parm info since it may not be copied yet.   
     Remap size_time vectors.
     Simplify the predicate by prunning out alternatives that are known
     to be false.
     TODO: as on optimization, we can also eliminate conditions known
     to be true.   
     Remap edge predicates with the same simplification as above.
     Also copy constantness arrays.    
     Remap indirect edge predicates with the same simplificaiton as above. 
     Also copy constantness arrays.    
     If inliner or someone after inliner will ever start producing
     non-trivial clones, we will get trouble with lack of information
     about updating self sizes, because size vectors already contains
     sizes of the calees.   
static void inline_node_removal_hook ( struct cgraph_node node,
void *  data 
)
static
static void inline_read_section ( struct lto_file_decl_data file_data,
const char *  data,
size_t  len 
)
static

Stream in inline summaries from the section.

void inline_read_summary ( void  )

Read inline summary. Jump functions are shared among ipa-cp and inliner, so when ipa-cp is active, we don't need to write them twice.

Fatal error here. We do not want to support compiling ltrans units with different version of compiler or different flags than the WPA unit, so this should never happen.

static void inline_summary_alloc ( )
static

Allocate the inline summary vector or resize it to cover all cgraph nodes.

References inline_summary::loop_iterations, NULL, and pool_free().

Referenced by inline_node_removal_hook().

static void inline_update_callee_summaries ( )
static

Update summary information of inline clones after inlining. Compute peak stack usage.

void inline_update_overall_summary ( )

For performance reasons inline_merge_summary is not updating overall size and time. Recompute it.

References estimate_edge_time(), false_predicate_p(), inline_edge_summary(), inline_summary(), MAX_TIME, inline_edge_summary::predicate, and inline_summary::time.

Referenced by add_new_edges_to_heap().

void inline_write_summary ( void  )

Write inline summary for node in SET. Jump functions are shared among ipa-cp and inliner, so when ipa-cp is active, we don't need to write them twice.

gimple_opt_pass* make_pass_inline_parameters ( )
static bool mark_modified ( ao_ref ao,
tree  vdef,
void *  data 
)
static

Callback of walk_aliased_vdefs. Flags that it has been invoked to the boolean variable pointed to by DATA.

static struct predicate not_inlined_predicate ( )
staticread

Return predicate that is set true when function is not inlined.

static struct predicate or_predicates ( conditions  conditions,
struct predicate p,
struct predicate p2 
)
staticread

Return P | P2.

Avoid busy work.

 OK, combine the predicates.   
static int param_change_prob ( )
static

Return probability (based on REG_BR_PROB_BASE) that I-th parameter of STMT will change since last invocation of STMT.

Value 0 is reserved for compile time invariants. For common parameters it is REG_BR_PROB_BASE. For loop invariants it ought to be REG_BR_PROB_BASE / estimated_iters.

 Global invariants neve change.   
 We would have to do non-trivial analysis to really work out what
 is the probability of value to change (i.e. when init statement
 is in a sibling loop of the call). 

 We do an conservative estimate: when call is executed N times more often
 than the statement defining value, we take the frequency 1/N.   
     Assume that every memory is initialized at entry.
     TODO: Can we easilly determine if value is always defined
     and thus we may skip entry block?   

References edge_def::src.

static bool phi_result_unknown_predicate ( struct ipa_node_params info,
struct inline_summary summary,
basic_block  bb,
struct predicate p,
vec< predicate_t nonconstant_names 
)
static

Find whether a basic block BB is the final block of a (half) diamond CFG sub-graph and if the predicate the condition depends on is known. If so, return true and store the pointer the predicate in *P.

References gcc_assert, gimple_assign_rhs1(), gimple_assign_rhs_code(), gimple_call_arg(), gimple_call_builtin_p(), gimple_call_lhs(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), is_gimple_assign(), NULL, single_imm_use(), SSA_NAME_DEF_STMT, and TREE_CODE.

static void predicate_for_phi_result ( struct inline_summary summary,
gimple  phi,
struct predicate p,
vec< predicate_t nonconstant_names 
)
static

Given a PHI statement in a function described by inline properties SUMMARY and *P being the predicate describing whether the selected PHI argument is known, store a predicate for the result of the PHI statement into NONCONSTANT_NAMES, if possible.

References inline_summary::conds, symtab_node_base::decl, DECL_STRUCT_FUNCTION, inline_summary::entry, inline_summary(), NULL, order, true_predicate(), and vNULL.

static int predicate_probability ( conditions  conds,
struct predicate p,
clause_t  possible_truths,
vec< inline_param_summary_t inline_param_summary 
)
static

Return the probability in range 0...REG_BR_PROB_BASE that the predicated instruction will be recomputed per invocation of the inlined call.

True remains true.

 See if we can find clause we can disprove.   
static bool predicates_equal_p ( )
inlinestatic

Return true if predicates are obviously equal.

References add_clause(), predicate::clause, gcc_checking_assert, and MAX_CLAUSES.

Referenced by dump_inline_hints().

static struct predicate read_predicate ( )
staticread

Read predicate from IB.

Zero-initialize the remaining clauses in OUT.

static bool record_modified ( )
static

Callback of walk_aliased_vdefs. Records basic blocks where the value may be set except for info->stmt.

References false_predicate().

static void remap_edge_change_prob ( struct cgraph_edge inlined_edge,
struct cgraph_edge edge 
)
static

Update change_prob of EDGE after INLINED_EDGE has been inlined. When functoin A is inlined in B and A calls C with parameter that changes with probability PROB1 and C is known to be passthroug of argument if B that change with probability PROB2, the probability of change is now PROB1*PROB2.

References count, evaluate_properties_for_edge(), gcc_assert, HOST_WIDE_INT, INT_MAX, IPA_EDGE_REF, ipa_get_cs_argument_count(), ipa_get_ith_jump_func(), ipa_get_jf_ancestor_agg_preserved(), ipa_get_jf_ancestor_formal_id(), ipa_get_jf_ancestor_offset(), ipa_get_jf_pass_through_agg_preserved(), ipa_get_jf_pass_through_formal_id(), ipa_get_jf_pass_through_operation(), ipa_get_param_count(), IPA_JF_ANCESTOR, IPA_JF_PASS_THROUGH, IPA_NODE_REF, map, NULL, offset, and ipa_jump_func::type.

Referenced by remap_predicate().

static void remap_edge_summaries ( struct cgraph_edge inlined_edge,
struct cgraph_node node,
struct inline_summary info,
struct inline_summary callee_info,
vec< int >  operand_map,
vec< int >  offset_map,
clause_t  possible_truths,
struct predicate toplev_predicate 
)
static

Update edge summaries of NODE after INLINED_EDGE has been inlined.

Remap predicates of callees of NODE. Rest of arguments match remap_predicate.

Also update change probabilities.

TODO: We should remove the edge for code that will be
optimized out, but we need to keep verifiers and tree-inline
happy.  Make it cold for now.   

TODO: We should remove the edge for code that will be optimized out, but we need to keep verifiers and tree-inline happy. Make it cold for now.

Referenced by remap_predicate().

static void remap_hint_predicate ( struct inline_summary info,
struct inline_summary callee_info,
struct predicate **  hint,
vec< int >  operand_map,
vec< int >  offset_map,
clause_t  possible_truths,
struct predicate toplev_predicate 
)
static
static void remap_hint_predicate_after_duplication ( struct predicate **  p,
clause_t  possible_truths,
struct inline_summary info 
)
static

Same as remap_predicate_after_duplication but handle hint predicate *P. Additionally care about allocating new memory slot for updated predicate and set it to NULL when it becomes true or false (and thus uninteresting).

We do not want to free previous predicate; it is used by node origin.

static struct predicate remap_predicate ( struct inline_summary info,
struct inline_summary callee_info,
struct predicate p,
vec< int >  operand_map,
vec< int >  offset_map,
clause_t  possible_truths,
struct predicate toplev_predicate 
)
staticread

Translate all conditions from callee representation into caller representation and symbolically evaluate predicate P into new predicate.

INFO is inline_summary of function we are adding predicate into, CALLEE_INFO is summary of function predicate P is from. OPERAND_MAP is array giving callee formal IDs the caller formal IDs. POSSSIBLE_TRUTHS is clausule of all callee conditions that may be true in caller context. TOPLEV_PREDICATE is predicate under which callee is executed. OFFSET_MAP is an array of of offsets that need to be added to conditions, negative offset means that conditions relying on values passed by reference have to be discarded because they might not be preserved (and should be considered offset zero for other purposes).

 True predicate is easy.   
       Do we have condition we can't disprove?    
           Work out if the condition can translate to predicate in the
           inlined function.   
               See if we can remap condition operand to caller's operand.
               Otherwise give up.   
                   TODO: For non-aggregate conditions, adding an offset is
                   basically an arithmetic jump function processing which
                   we should support in future.   
           Fixed conditions remains same, construct single
           condition predicate.   

References cgraph_edge::callee, cgraph_node::callees, cgraph_edge::count, edge_set_predicate(), false_predicate_p(), cgraph_edge::frequency, cgraph_node::indirect_calls, inline_edge_summary(), cgraph_edge::inline_failed, cgraph_edge::next_callee, inline_edge_summary::predicate, remap_edge_change_prob(), and remap_edge_summaries().

static struct predicate remap_predicate_after_duplication ( struct predicate p,
clause_t  possible_truths,
struct inline_summary info 
)
staticread

Remap predicate P of former function to be predicate of duplicated functoin. POSSIBLE_TRUTHS is clause of possible truths in the duplicated node, INFO is inline summary of the duplicated node.

static void reset_inline_edge_summary ( )
static

We are called multiple time for given function; clear data from previous run so they are not cumulated.

static void reset_inline_summary ( )
static

We are called multiple time for given function; clear data from previous run so they are not cumulated.

References false_predicate().

static void set_cond_stmt_execution_predicate ( struct ipa_node_params info,
struct inline_summary summary,
basic_block  bb 
)
static

If BB ends by a conditional we can turn into predicates, attach corresponding predicates to the CFG edges.

TODO: handle conditionals like var = op0 < 4; if (var != 0).

 Special case
 if (builtin_constant_p (op))
 constant_code
 else
 nonconstant_code.
 Here we can predicate nonconstant_code.  We can't
 really handle constant_code since we have no predicate
 for this and also the constant code is not known to be
 optimized away when inliner doen't see operand is constant.
 Other optimizers might think otherwise.   

References false_predicate(), and pool_alloc().

static void set_hint_predicate ( )
static
static void set_switch_stmt_execution_predicate ( struct ipa_node_params info,
struct inline_summary summary,
basic_block  bb 
)
static

If BB ends by a switch we can turn into predicates, attach corresponding predicates to the CFG edges.

For default we might want to construct predicate that none of cases is met, but it is bit hard to do not having negations of conditionals handy.

static struct predicate single_cond_predicate ( )
staticread

Return predicate testing single condition number COND.

References predicate_false_condition.

Referenced by false_predicate_p().

static struct predicate true_predicate ( )
staticread

Return true predicate (tautology). We represent it by empty list of clauses.

References predicate::clause.

Referenced by predicate_for_phi_result().

static bool true_predicate_p ( )
inlinestatic

Return true if P is (false).

Referenced by will_be_nonconstant_expr_predicate().

static tree unmodified_parm ( )
static

If OP refers to value of function parameter, return the corresponding parameter. Also traverse chains of SSA register assignments.

References get_base_address(), gimple_assign_lhs(), and gimple_assign_rhs1().

Referenced by unmodified_parm_or_parm_agg_item(), and will_be_nonconstant_expr_predicate().

static tree unmodified_parm_1 ( )
static

If OP refers to value of function parameter, return the corresponding parameter.

SSA_NAME referring to parm default def?

 Non-SSA parm reference?   

References gimple_assign_rhs_code(), and gimple_num_ops().

Referenced by debug_inline_summary(), and initialize_inline_failed().

static bool unmodified_parm_or_parm_agg_item ( struct ipa_node_params info,
gimple  stmt,
tree  op,
int *  index_p,
struct agg_position_info aggpos 
)
static

If OP refers to a value of a function parameter or value loaded from an aggregate passed to a parameter (either by value or reference), return TRUE and store the number of the parameter to *INDEX_P and information whether and how it has been loaded from an aggregate into *AGGPOS. INFO describes the function parameters, STMT is the statement in which OP is used or loaded.

References get_base_address(), TREE_CODE, TREE_OPERAND, and unmodified_parm().

static struct predicate will_be_nonconstant_expr_predicate ( struct ipa_node_params info,
struct inline_summary summary,
tree  expr,
vec< predicate_t nonconstant_names 
)
staticread

Return predicate specifying when the STMT might have result that is not a compile time constant.

References ipa_get_param_decl_index(), SSA_NAME_VERSION, TREE_CODE, true_predicate_p(), and unmodified_parm().

static struct predicate will_be_nonconstant_predicate ( struct ipa_node_params info,
struct inline_summary summary,
gimple  stmt,
vec< predicate_t nonconstant_names 
)
staticread

Return predicate specifying when the STMT might have result that is not a compile time constant.

 What statments might be optimized away
 when their arguments are constant
 TODO: also trivial builtins.
 builtin_constant_p is already handled later.   
 Stores will stay anyway.   
 Loads can be optimized when the value is known.   
 See if we understand all operands before we start
 adding conditionals.   
     For arguments we can build a condition.   
     If we know when operand is constant,
     we still can say something useful.   
static void write_inline_edge_summary ( )
static

Write inline summary for edge E to OB.

static void write_predicate ( )
static

Write predicate P to OB.


Variable Documentation

struct cgraph_2edge_hook_list* edge_duplication_hook_holder
static
vec<edge_growth_cache_entry> edge_growth_cache
alloc_pool edge_predicate_pool
static

Edge predicates goes here.

struct cgraph_edge_hook_list* edge_removal_hook_holder
static
struct cgraph_node_hook_list* function_insertion_hook_holder
static

Holders of ipa cgraph hooks:

vec<inline_edge_summary_t> inline_edge_summary_vec
vec<inline_summary_t, va_gc>* inline_summary_vec

VECtor holding inline summaries. In GGC memory because conditions might point to constant trees.

Referenced by cgraph_process_new_functions().

struct cgraph_2node_hook_list* node_duplication_hook_holder
static
vec<int> node_growth_cache

Cached node/edge growths.

struct cgraph_node_hook_list* node_removal_hook_holder
static