GCC Middle and Back End API 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"
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 } |
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_t > | inline_edge_summary_vec |
vec< int > | node_growth_cache |
vec< edge_growth_cache_entry > | edge_growth_cache |
static alloc_pool | edge_predicate_pool |
#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
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 struct predicate predicate_t |
We keep info about constantness of SSA names.
enum predicate_conditions |
|
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.
|
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().
|
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 |
Called when new function is inserted to callgraph late.
|
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.
|
staticread |
Return predicate specifying when array index in access OP becomes non-constant.
|
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 |
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 |
Worker for do_estimate_growth. Collect growth for all callers.
|
static |
Dump clause CLAUSE.
|
static |
Dump conditional COND.
|
static |
Dump edge summaries associated to NODE and recursively to all clones. Indent by INDENT.
void dump_inline_hints | ( | ) |
Dump inline hints.
References predicate::clause, inline_summary::conds, dump_file, dump_flags, dump_predicate(), inline_summary::entry, false_predicate_p(), gcc_assert, INLINE_SIZE_SCALE, INLINE_TIME_SCALE, MAX_TIME, size_time_entry::predicate, predicates_equal_p(), size_time_entry::size, TDF_DETAILS, size_time_entry::time, and vec_safe_iterate().
void dump_inline_summaries | ( | ) |
void dump_inline_summary | ( | ) |
|
static |
Dump predicate PREDICATE.
Referenced by dump_inline_hints(), and initialize_growth_caches().
|
static |
Set predicate for edge E.
Referenced by remap_predicate().
|
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 |
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 |
Estimate benefit devirtualizing indirect edge IE, provided KNOWN_VALS and KNOWN_BINFOS.
Account for difference in cost between indirect and direct calls.
|
inlinestatic |
Increase SIZE and TIME for size and time needed to handle edge E.
|
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 |
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 |
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 |
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 |
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().
|
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().
|
inlinestatic |
Return true if P is (false).
References predicate_not_inlined_condition, and single_cond_predicate().
Referenced by dump_inline_hints(), inline_update_overall_summary(), remap_predicate(), and simple_edge_hints().
|
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_growth_caches | ( | void | ) |
Initialize growth caches.
References inline_edge_summary::call_stmt_size, inline_edge_summary::call_stmt_time, inline_summary::conds, dump_predicate(), cgraph_edge::frequency, inline_edge_summary(), inline_edge_summary::loop_depth, and inline_edge_summary::predicate.
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 |
Note function body size.
|
static |
Hook that is called by cgraph.c when a node is duplicated.
|
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 |
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 |
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 |
Hook that is called by cgraph.c when a node is removed.
References cgraph_node::clone, inline_summary::conds, inline_summary::entry, inline_summary(), inline_summary_alloc(), ipa_node_params_vector, IPA_NODE_REF, cgraph_clone_info::tree_map, and vec_safe_copy().
|
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 |
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 |
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 | ( | ) |
Callback of walk_aliased_vdefs. Flags that it has been invoked to the boolean variable pointed to by DATA.
|
staticread |
Return predicate that is set true when function is not inlined.
|
staticread |
Return P | P2.
Avoid busy work.
OK, combine the predicates.
|
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 |
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 |
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 |
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.
|
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 |
Write inline summary for edge E to OB.
References symtab_node_base::alias, create_output_block(), output_block::decl_state, symtab_node_base::definition, dyn_cast(), inline_summary(), LTO_section_inline_summary, lto_symtab_encoder_deref(), lto_symtab_encoder_size(), streamer_write_uhwi(), and lto_out_decl_state::symtab_node_encoder.
|
staticread |
Read predicate from IB.
Zero-initialize the remaining clauses in OUT.
|
static |
Callback of walk_aliased_vdefs. Records basic blocks where the value may be set except for info->stmt.
References false_predicate().
|
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 |
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 |
Same as remap_predicate, but set result into hint *HINT.
References cgraph_edge::callee, cgraph_edge::caller, cgraph_edge_recursive_p(), cgraph_node::global, INLINE_HINT_cross_module, inline_summary(), cgraph_global_info::inlined_to, symtab_node_base::lto_file_data, and inline_summary::scc_no.
|
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.
|
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().
|
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 |
We are called multiple time for given function; clear data from previous run so they are not cumulated.
|
static |
We are called multiple time for given function; clear data from previous run so they are not cumulated.
References false_predicate().
|
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 |
Set predicate for hint *P.
References condition::by_ref, CHANGED, error_mark_node, ipa_find_agg_cst_for_param(), NULL_TREE, condition::offset, and condition::operand_num.
|
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.
int simple_edge_hints | ( | ) |
Return hints derrived from EDGE.
References estimate_edge_growth(), false_predicate_p(), gcc_assert, inline_edge_summary(), inline_summary(), inline_edge_summary::predicate, and inline_summary::size.
|
staticread |
Return predicate testing single condition number COND.
References predicate_false_condition.
Referenced by false_predicate_p().
|
staticread |
Return true predicate (tautology). We represent it by empty list of clauses.
References predicate::clause.
Referenced by predicate_for_phi_result().
|
inlinestatic |
Return true if P is (false).
Referenced by will_be_nonconstant_expr_predicate().
|
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 |
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 |
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().
|
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().
|
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 |
Write inline summary for edge E to OB.
|
static |
Write predicate P to OB.
|
static |
vec<edge_growth_cache_entry> edge_growth_cache |
|
static |
Edge predicates goes here.
|
static |
|
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().
|
static |
vec<int> node_growth_cache |
Cached node/edge growths.
|
static |