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_pass * | make_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 () |
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().
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 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_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.
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 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.
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().