GCC Middle and Back End API Reference
|
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "hash-table.h"
#include "gimple-pretty-print.h"
#include "gimple.h"
#include "gimple-ssa.h"
#include "tree-cfg.h"
#include "tree-phinodes.h"
#include "tree-ssanames.h"
#include "tree-ssa-loop-ivopts.h"
#include "tree-ssa-loop-manip.h"
#include "tree-ssa-loop-niter.h"
#include "tree-ssa-loop.h"
#include "tree-ssa.h"
#include "cfgloop.h"
#include "tree-chrec.h"
#include "tree-scalar-evolution.h"
#include "dumpfile.h"
#include "params.h"
#include "tree-ssa-propagate.h"
#include "gt-tree-scalar-evolution.h"
Data Structures | |
struct | scev_info_str |
struct | instantiate_cache_type |
struct | chrec_stats |
Typedefs | |
typedef enum t_bool | t_bool |
Enumerations | |
enum | t_bool { t_false, t_true, t_dont_know } |
Functions | |
static tree | analyze_scalar_evolution_1 (struct loop *, tree, tree) |
static tree | analyze_scalar_evolution_for_address_of (struct loop *loop, tree var) |
static struct scev_info_str * | new_scev_info_str () |
static hashval_t | hash_scev_info () |
static int | eq_scev_info () |
static void | del_scev_info () |
static tree * | find_var_scev_info () |
bool | chrec_contains_symbols_defined_in_loop () |
static bool | loop_phi_node_p () |
tree | compute_overall_effect_of_inner_loop () |
static void | set_scalar_evolution () |
static tree | get_scalar_evolution () |
static tree | add_to_evolution_1 (unsigned loop_nb, tree chrec_before, tree to_add, gimple at_stmt) |
static tree | add_to_evolution (unsigned loop_nb, tree chrec_before, enum tree_code code, tree to_add, gimple at_stmt) |
gimple | get_loop_exit_condition () |
static t_bool | follow_ssa_edge (struct loop *loop, gimple, gimple, tree *, int) |
static t_bool | follow_ssa_edge_binary (struct loop *loop, gimple at_stmt, tree type, tree rhs0, enum tree_code code, tree rhs1, gimple halting_phi, tree *evolution_of_loop, int limit) |
static t_bool | follow_ssa_edge_expr (struct loop *loop, gimple at_stmt, tree expr, gimple halting_phi, tree *evolution_of_loop, int limit) |
static t_bool | follow_ssa_edge_in_rhs (struct loop *loop, gimple stmt, gimple halting_phi, tree *evolution_of_loop, int limit) |
static bool | backedge_phi_arg_p () |
static t_bool | follow_ssa_edge_in_condition_phi_branch (int i, struct loop *loop, gimple condition_phi, gimple halting_phi, tree *evolution_of_branch, tree init_cond, int limit) |
static t_bool | follow_ssa_edge_in_condition_phi (struct loop *loop, gimple condition_phi, gimple halting_phi, tree *evolution_of_loop, int limit) |
static t_bool | follow_ssa_edge_inner_loop_phi (struct loop *outer_loop, gimple loop_phi_node, gimple halting_phi, tree *evolution_of_loop, int limit) |
static tree | analyze_evolution_in_loop (gimple loop_phi_node, tree init_cond) |
static tree | analyze_initial_condition () |
static tree | interpret_loop_phi () |
static tree | interpret_condition_phi () |
static tree | interpret_rhs_expr (struct loop *loop, gimple at_stmt, tree type, tree rhs1, enum tree_code code, tree rhs2) |
static tree | interpret_expr () |
static tree | interpret_gimple_assign () |
static tree | compute_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *def_loop, tree ev) |
static tree | analyze_scalar_evolution_1 () |
tree | analyze_scalar_evolution () |
static tree | analyze_scalar_evolution_for_address_of () |
static tree | analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop, tree version, bool *folded_casts) |
static hashval_t | hash_idx_scev_info () |
static int | eq_idx_scev_info () |
static unsigned | get_instantiated_value_entry (instantiate_cache_type &cache, tree name, basic_block instantiate_below) |
static tree | loop_closed_phi_def () |
static tree | instantiate_scev_r (basic_block, struct loop *, struct loop *, tree, bool, int) |
static tree | instantiate_scev_name (basic_block instantiate_below, struct loop *evolution_loop, struct loop *inner_loop, tree chrec, bool fold_conversions, int size_expr) |
static tree | instantiate_scev_poly (basic_block instantiate_below, struct loop *evolution_loop, struct loop *, tree chrec, bool fold_conversions, int size_expr) |
static tree | instantiate_scev_binary (basic_block instantiate_below, struct loop *evolution_loop, struct loop *inner_loop, tree chrec, enum tree_code code, tree type, tree c0, tree c1, bool fold_conversions, int size_expr) |
static tree | instantiate_array_ref (basic_block instantiate_below, struct loop *evolution_loop, struct loop *inner_loop, tree chrec, bool fold_conversions, int size_expr) |
static tree | instantiate_scev_convert (basic_block instantiate_below, struct loop *evolution_loop, struct loop *inner_loop, tree chrec, tree type, tree op, bool fold_conversions, int size_expr) |
static tree | instantiate_scev_not (basic_block instantiate_below, struct loop *evolution_loop, struct loop *inner_loop, tree chrec, enum tree_code code, tree type, tree op, bool fold_conversions, int size_expr) |
static tree | instantiate_scev_3 (basic_block instantiate_below, struct loop *evolution_loop, struct loop *inner_loop, tree chrec, bool fold_conversions, int size_expr) |
static tree | instantiate_scev_2 (basic_block instantiate_below, struct loop *evolution_loop, struct loop *inner_loop, tree chrec, bool fold_conversions, int size_expr) |
static tree | instantiate_scev_1 (basic_block instantiate_below, struct loop *evolution_loop, struct loop *inner_loop, tree chrec, bool fold_conversions, int size_expr) |
tree | instantiate_scev (basic_block instantiate_below, struct loop *evolution_loop, tree chrec) |
tree | resolve_mixers () |
tree | number_of_latch_executions () |
tree | number_of_exit_cond_executions () |
static void | reset_chrecs_counters () |
static void | dump_chrecs_stats () |
static void | gather_chrec_stats () |
static int | gather_stats_on_scev_database_1 () |
void | gather_stats_on_scev_database () |
static void | initialize_scalar_evolutions_analyzer () |
void | scev_initialize () |
bool | scev_initialized_p () |
void | scev_reset_htab () |
void | scev_reset () |
bool | simple_iv (struct loop *wrto_loop, struct loop *use_loop, tree op, affine_iv *iv, bool allow_nonconstant_step) |
void | scev_finalize () |
bool | expression_expensive_p () |
unsigned int | scev_const_prop () |
Variables | |
static unsigned | nb_set_scev = 0 |
static unsigned | nb_get_scev = 0 |
tree | chrec_not_analyzed_yet |
tree | chrec_dont_know |
tree | chrec_known |
static htab_t | scalar_evolution_info |
static instantiate_cache_type * | global_cache |
enum t_bool |
|
static |
Add TO_ADD to the evolution part of CHREC_BEFORE in the dimension of LOOP_NB.
Description (provided for completeness, for those who read code in a plane, and for my poor 62 bytes brain that would have forgotten all this in the next two or three months):
The algorithm of translation of programs from the SSA representation into the chrecs syntax is based on a pattern matching. After having reconstructed the overall tree expression for a loop, there are only two cases that can arise:
where EXPR is either a scalar constant with respect to the analyzed loop (this is a degree 0 polynomial), or an expression containing other loop-phi definitions (these are higher degree polynomials).
Examples:
1. | init = ... | loop_1 | a = phi (init, a + 5) | endloop
2. | inita = ... | initb = ... | loop_1 | a = phi (inita, 2 * b + 3) | b = phi (initb, b + 1) | endloop
For the first case, the semantics of the SSA representation is:
| a (x) = init + {j = 0}^{x - 1} expr (j)
that is, there is a loop index "x" that determines the scalar value of the variable during the loop execution. During the first iteration, the value is that of the initial condition INIT, while during the subsequent iterations, it is the sum of the initial condition with the sum of all the values of EXPR from the initial iteration to the before last considered iteration.
For the second case, the semantics of the SSA program is:
| a (x) = init, if x = 0; | expr (x - 1), otherwise.
The second case corresponds to the PEELED_CHREC, whose syntax is close to the syntax of a loop-phi-node:
| phi (init, expr) vs. (init, expr)_x
The proof of the translation algorithm for the first case is a proof by structural induction based on the degree of EXPR.
Degree 0: When EXPR is a constant with respect to the analyzed loop, or in other words when EXPR is a polynomial of degree 0, the evolution of the variable A in the loop is an affine function with an initial condition INIT, and a step EXPR. In order to show this, we start from the semantics of the SSA representation:
f (x) = init + {j = 0}^{x - 1} expr (j)
and since "expr (j)" is a constant with respect to "j",
f (x) = init + x * expr
Finally, based on the semantics of the pure sum chrecs, by identification we get the corresponding chrecs syntax:
f (x) = init * {x}{0} + expr * {x}{1} f (x) -> {init, +, expr}_x
Higher degree: Suppose that EXPR is a polynomial of degree N with respect to the analyzed loop_x for which we have already determined that it is written under the chrecs syntax:
| expr (x) -> {b_0, +, b_1, +, ..., +, b_{n-1}} (x)
We start from the semantics of the SSA program:
| f (x) = init + {j = 0}^{x - 1} expr (j) | | f (x) = init + {j = 0}^{x - 1} | (b_0 * {j}{0} + ... + b_{n-1} * {j}{n-1}) | | f (x) = init + {j = 0}^{x - 1} | {k = 0}^{n - 1} (b_k * {j}{k}) | | f (x) = init + {k = 0}^{n - 1} | (b_k * {j = 0}^{x - 1} {j}{k}) | | f (x) = init + {k = 0}^{n - 1} | (b_k * {x}{k + 1}) | | f (x) = init + b_0 * {x}{1} + ... | + b_{n-1} * {x}{n} | | f (x) = init * {x}{0} + b_0 * {x}{1} + ... | + b_{n-1} * {x}{n} |
And finally from the definition of the chrecs syntax, we identify: | f (x) -> {init, +, b_0, +, ..., +, b_{n-1}}_x
This shows the mechanism that stands behind the add_to_evolution function. An important point is that the use of symbolic parameters avoids the need of an analysis schedule.
Example:
| inita = ... | initb = ... | loop_1 | a = phi (inita, a + 2 + b) | b = phi (initb, b + 1) | endloop
When analyzing "a", the algorithm keeps "b" symbolically:
| a -> {inita, +, 2 + b}_1
Then, after instantiation, the analyzer ends on the evolution:
| a -> {inita, +, 2 + initb, +, 1}_1
TO_ADD is either a scalar, or a parameter. TO_ADD is not instantiated at this point.
This should not happen.
Referenced by follow_ssa_edge_binary().
|
static |
Helper function for add_to_evolution. Returns the evolution function for an assignment of the form "a = b + c", where "a" and "b" are on the strongly connected component. CHREC_BEFORE is the information that we already have collected up to this point. TO_ADD is the evolution of "c".
When CHREC_BEFORE has an evolution part in LOOP_NB, add to this evolution the expression TO_ADD, otherwise construct an evolution part for this loop.
When there is no evolution part in this loop, build it.
Search the evolution in LOOP_NB.
These nodes do not depend on a loop.
Given a LOOP_PHI_NODE, this function determines the evolution function from LOOP_PHI_NODE to LOOP_PHI_NODE in the loop.
Select the edges that enter the loop body.
Pass in the initial condition to the follow edge function.
If ev_fn has no evolution in the inner loop, and the init_cond is not equal to ev_fn, then we have an ambiguity between two possible values, as we cannot know the number of iterations at this point.
When it is impossible to go back on the same loop_phi_node by following the ssa edges, the evolution is represented by a peeled chrec, i.e. the first iteration, EV_FN has the value INIT_COND, then all the other iterations it has the value of ARG. For the moment, PEELED_CHREC nodes are not built.
When there are multiple back edges of the loop (which in fact never happens currently, but nevertheless), merge their evolutions.
References chrec_dont_know, chrec_merge(), chrec_not_analyzed_yet, degenerate_phi_result(), dump_file, dump_flags, flow_bb_inside_loop_p(), gimple_phi_arg_edge(), gimple_phi_num_args(), is_gimple_min_invariant(), loop_containing_stmt(), NULL_TREE, PHI_ARG_DEF, print_generic_expr(), print_gimple_stmt(), edge_def::src, SSA_NAME_DEF_STMT, and TREE_CODE.
|
static |
Given a loop-phi-node, return the initial conditions of the variable on entry of the loop. When the CCP has propagated constants into the loop-phi-node, the initial condition is instantiated, otherwise the initial condition is kept symbolic. This analyzer does not analyze the evolution outside the current loop, and leaves this task to the on-demand tree reconstructor.
When the branch is oriented to the loop's body, it does not contribute to the initial condition.
Ooops – a loop without an entry??? During early loop unrolling we do not have fully constant propagated IL. Handle degenerate PHIs here to not miss important unrollings.
Only allow invariants here, otherwise we may break loop-closed SSA form.
tree analyze_scalar_evolution | ( | ) |
Analyzes and returns the scalar evolution of the ssa_name VAR in LOOP. LOOP is the loop in which the variable is used.
Example of use: having a pointer VAR to a SSA_NAME node, STMT a pointer to the statement that uses this variable, in order to determine the evolution function of the variable, use the following calls:
loop_p loop = loop_containing_stmt (stmt); tree chrec_with_symbols = analyze_scalar_evolution (loop, var); tree chrec_instantiated = instantiate_parameters (loop, chrec_with_symbols);
References chrec_dont_know, loop_outer(), no_evolution_in_loop_p(), loop::num, and resolve_mixers().
Referenced by dr_analyze_indices(), extract_range_from_comparison(), get_instantiated_value_entry(), interpret_loop_phi(), move_sese_in_condition(), scev_reset(), and set_ifsese_condition().
Scalar evolution detector. Copyright (C) 2003-2013 Free Software Foundation, Inc. Contributed by Sebastian Pop s.pop @lap oste. net
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/.
|
static |
Helper recursive function.
Keep the symbolic form.
Keep the symbolic form.
|
static |
Analyzes and returns the scalar evolution of VAR address in LOOP.
References instantiate_cache_type::entries, instantiate_cache_type::instantiate_cache_type(), instantiate_cache_type::map, NULL, vNULL, and instantiate_cache_type::~instantiate_cache_type().
|
static |
Analyze scalar evolution of use of VERSION in USE_LOOP with respect to WRTO_LOOP (which should be a superloop of USE_LOOP)
FOLDED_CASTS is set to true if resolve_mixers used chrec_convert_aggressive (TODO – not really, we are way too conservative at the moment in order to keep things simple).
To illustrate the meaning of USE_LOOP and WRTO_LOOP, consider the following example:
for (i = 0; i < 100; i++) – loop 1 { for (j = 0; j < 100; j++) – loop 2 { k1 = i; k2 = j;
use2 (k1, k2);
for (t = 0; t < 100; t++) – loop 3 use3 (k1, k2);
} use1 (k1, k2); }
Both k1 and k2 are invariants in loop3, thus analyze_scalar_evolution_in_loop (loop3, loop3, k1) = k1 analyze_scalar_evolution_in_loop (loop3, loop3, k2) = k2
As they are invariant, it does not matter whether we consider their usage in loop 3 or loop 2, hence analyze_scalar_evolution_in_loop (loop2, loop3, k1) = analyze_scalar_evolution_in_loop (loop2, loop2, k1) = i analyze_scalar_evolution_in_loop (loop2, loop3, k2) = analyze_scalar_evolution_in_loop (loop2, loop2, k2) = [0,+,1]_2
Similarly for their evolutions with respect to loop 1. The values of K2 in the use in loop 2 vary independently on loop 1, thus we cannot express the evolution with respect to loop 1: analyze_scalar_evolution_in_loop (loop1, loop3, k1) = analyze_scalar_evolution_in_loop (loop1, loop2, k1) = [0,+,1]_1 analyze_scalar_evolution_in_loop (loop1, loop3, k2) = analyze_scalar_evolution_in_loop (loop1, loop2, k2) = dont_know
The value of k2 in the use in loop 1 is known, though: analyze_scalar_evolution_in_loop (loop1, loop1, k1) = [0,+,1]_1 analyze_scalar_evolution_in_loop (loop1, loop1, k2) = 100
We cannot just do
tmp = analyze_scalar_evolution (use_loop, version); ev = resolve_mixers (wrto_loop, tmp);
as resolve_mixers would query the scalar evolution with respect to wrto_loop. For example, in the situation described in the function comment, suppose that wrto_loop = loop1, use_loop = loop3 and version = k2. Then
analyze_scalar_evolution (use_loop, version) = k2
and resolve_mixers (loop1, k2) finds that the value of k2 in loop 1 is 100, which is a wrong result, since we are interested in the value in loop 3.
Instead, we need to proceed from use_loop to wrto_loop loop by loop, each time checking that there is no evolution in the inner loop.
If the value of the use changes in the inner loop, we cannot express its value in the outer loop (we might try to return interval chrec, but we do not have a user for it anyway)
|
static |
Checks whether the I-th argument of a PHI comes from a backedge.
We would in fact like to test EDGE_DFS_BACK here, but we do not care about updating it anywhere, and this should work as well most of the time.
References follow_ssa_edge_in_condition_phi_branch(), gimple_phi_num_args(), t_dont_know, and t_false.
bool chrec_contains_symbols_defined_in_loop | ( | ) |
Return true when CHREC contains symbolic names defined in LOOP_NB.
tree compute_overall_effect_of_inner_loop | ( | ) |
Compute the scalar evolution for EVOLUTION_FN after crossing LOOP. In general, in the case of multivariate evolutions we want to get the evolution in different loops. LOOP specifies the level for which to get the evolution.
Example:
| for (j = 0; j < 100; j++) | { | for (k = 0; k < 100; k++) | { | i = k + j; - Here the value of i is a function of j, k. | } | ... = i - Here the value of i is a function of j. | } | ... = i - Here the value of i is a scalar.
Example:
| i_0 = ... | loop_1 10 times | i_1 = phi (i_0, i_2) | i_2 = i_1 + 2 | endloop
This loop has the same effect as: LOOP_1 has the same effect as:
| i_1 = i_0 + 20
The overall effect of the loop, "i_0 + 20" in the previous example, is obtained by passing in the parameters: LOOP = 1, EVOLUTION_FN = {i_0, +, 2}_1.
evolution_fn is the evolution function in LOOP. Get its value in the nb_iter-th iteration.
Continue the computation until ending on a parent of LOOP.
If the evolution function is an invariant, there is nothing to do.
References chrec_apply(), chrec_contains_symbols_defined_in_loop(), instantiate_parameters(), and loop::num.
Referenced by get_instantiated_value_entry(), and set_ifsese_condition().
|
static |
This section contains all the entry points:
References block_before_loop(), dump_file, dump_flags, get_scalar_evolution(), loop::num, and print_generic_expr().
|
static |
Deletes database element E.
References basic_block_def::index, scev_info_str::instantiated_below, scev_info_str::name_version, new_scev_info_str(), scalar_evolution_info, and SSA_NAME_VERSION.
Referenced by reset_chrecs_counters().
|
static |
Dump the contents of a CHREC_STATS structure.
References loop::nb_iterations, and NULL_TREE.
Referenced by number_of_exit_cond_executions().
|
inlinestatic |
Compares database elements E1 and E2.
|
inlinestatic |
bool expression_expensive_p | ( | ) |
Returns true if the expression EXPR is considered to be too expensive for scev_const_prop.
Division by power of two is usually cheap, so we allow it. Forbid anything else.
Fallthru.
References gsi_next().
|
static |
Get the scalar evolution of VAR for INSTANTIATED_BELOW basic block. A first query on VAR returns chrec_not_analyzed_yet.
|
static |
Follow an SSA edge from a loop-phi-node to itself, constructing a path that is analyzed on the return walk.
Give up if the path is longer than the MAX that we allow.
DEF is a condition-phi-node. Follow the branches, and record their evolutions. Finally, merge the collected information and set the approximation to the main variable.
When the analyzed phi is the halting_phi, the depth-first search is over: we have found a path from the halting_phi to itself in the loop.
Otherwise, the evolution of the HALTING_PHI depends on the evolution of another loop-phi-node, i.e. the evolution function is a higher degree polynomial.
Inner loop.
Outer loop.
At this level of abstraction, the program is just a set of GIMPLE_ASSIGNs and PHI_NODEs. In principle there is no other node to be handled.
Referenced by follow_ssa_edge_binary().
|
static |
Follow the ssa edge into the binary expression RHS0 CODE RHS1. Return true if the strongly connected component has been found.
Match an assignment under the form: "a = b + c".
We want only assignments of form "name + name" contribute to LIMIT, as the other cases do not necessarily contribute to the complexity of the expression.
Match an assignment under the form: "a = b + ...".
Match an assignment under the form: "a = ... + c".
Otherwise, match an assignment under the form: "a = ... + ...".
And there is nothing to do.
This case is under the form "opnd0 = rhs0 - rhs1".
Match an assignment under the form: "a = b - ...".
We want only assignments of form "name - name" contribute to LIMIT, as the other cases do not necessarily contribute to the complexity of the expression.
Otherwise, match an assignment under the form: "a = ... - ...".
And there is nothing to do.
References add_to_evolution(), chrec_convert(), chrec_dont_know, follow_ssa_edge(), loop::num, SSA_NAME_DEF_STMT, t_dont_know, and t_true.
|
static |
Follow the ssa edge into the expression EXPR. Return true if the strongly connected component has been found.
The EXPR is one of the following cases: - an SSA_NAME, - an INTEGER_CST, - a PLUS_EXPR, - a POINTER_PLUS_EXPR, - a MINUS_EXPR, - an ASSERT_EXPR, - other cases are not yet handled.
This assignment is under the form "a_1 = (cast) rhs.
This assignment is under the form "a_1 = 7".
This assignment is under the form: "a_1 = b_2".
This case is under the form "rhs0 +- rhs1".
Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.
This assignment is of the form: "a_1 = ASSERT_EXPR <a_2, ...>" It must be handled as a copy assignment of the form a_1 = a_2.
|
static |
This function merges the branches of a condition-phi-node in a loop.
Quickly give up when the evolution of one of the branches is not known.
Increase the limit by the PHI argument number to avoid exponential time and memory complexity.
Referenced by follow_ssa_edge_inner_loop_phi().
|
inlinestatic |
Helper function for one branch of the condition-phi-node. Return true if the strongly connected component has been found following this path.
Do not follow back edges (they must belong to an irreducible loop, which we really do not want to worry about).
This case occurs when one of the condition branches sets the variable to a constant: i.e. a phi-node like "a_2 = PHI <a_7(5), 2(6)>;". FIXME: This case have to be refined correctly: in some cases it is possible to say something better than chrec_dont_know, for example using a wrap-around notation.
Referenced by backedge_phi_arg_p().
|
static |
Follow the ssa edge into the right hand side of an assignment STMT. Return true if the strongly connected component has been found.
This assignment is under the form "a_1 = (cast) rhs.
Referenced by follow_ssa_edge_inner_loop_phi().
|
static |
Follow an SSA edge in an inner loop. It computes the overall effect of the loop, and following the symbolic initial conditions, it follows the edges in the parent loop. The inner loop is considered as a single statement.
Sometimes, the inner loop is too difficult to analyze, and the result of the analysis is a symbolic parameter.
Follow the edges that exit the inner loop.
If the path crosses this loop-phi, give up.
Otherwise, compute the overall effect of the inner loop.
References flow_loop_nested_p(), follow_ssa_edge_in_condition_phi(), follow_ssa_edge_in_rhs(), loop_phi_node_p(), t_false, and t_true.
|
static |
Gather statistics about CHREC.
References current_loops, FOR_EACH_LOOP, loop::nb_iterations, NULL_TREE, and scev_reset_htab().
void gather_stats_on_scev_database | ( | void | ) |
Classify the chrecs of the whole database.
|
static |
Callback for htab_traverse, gathers information on chrecs in the hashtable.
References affine_iv_d::base, build_int_cst(), affine_iv_d::no_overflow, affine_iv_d::step, and TREE_TYPE.
Referenced by number_of_exit_cond_executions().
|
static |
Returns from CACHE the slot number of the cached chrec for NAME.
References analyze_scalar_evolution(), CDI_DOMINATORS, compute_overall_effect_of_inner_loop(), dominated_by_p(), instantiate_scev_r(), loop_closed_phi_def(), loop_containing_stmt(), NULL_TREE, and SSA_NAME_DEF_STMT.
gimple get_loop_exit_condition | ( | ) |
This section selects the loops that will be good candidates for the scalar evolution analysis. For the moment, greedily select all the loop nests we could analyze. For a loop with a single exit edge, return the COND_EXPR that guards the exit edge. If the expression is too difficult to analyze, then give up.
|
static |
Retrieve the chrec associated to SCALAR instantiated below INSTANTIATED_BELOW block.
Referenced by compute_scalar_evolution_in_loop().
|
inlinestatic |
Computes a hash function for database element ELT.
|
inlinestatic |
Computes a hash function for database element ELT.
References scev_info_str::instantiated_below, and scev_info_str::name_version.
Referenced by reset_chrecs_counters().
|
static |
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
"CHREC" is an array reference to be instantiated.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
References chrec_dont_know, instantiate_scev_r(), and TREE_OPERAND.
tree instantiate_scev | ( | basic_block | instantiate_below, |
struct loop * | evolution_loop, | ||
tree | chrec | ||
) |
Analyze all the parameters of the chrec that were left under a symbolic form. INSTANTIATE_BELOW is the basic block that stops the recursive instantiation of parameters: a parameter is a variable that is defined in a basic block that dominates INSTANTIATE_BELOW or a function parameter.
Referenced by dr_analyze_indices(), and move_sese_in_condition().
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is an expression with 2 operands to be instantiated.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
References dump_file, dump_flags, global_cache, basic_block_def::index, instantiate_scev_r(), NULL, loop::num, and print_generic_expr().
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is an expression with 2 operands to be instantiated.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is an expression with 3 operands to be instantiated.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
References CASE_CONVERT, chrec_dont_know, chrec_known, chrec_type(), instantiate_scev_binary(), instantiate_scev_convert(), instantiate_scev_name(), instantiate_scev_not(), instantiate_scev_poly(), TREE_CODE, TREE_OPERAND, and TREE_TYPE.
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
"C0 CODE C1" is a binary expression of type TYPE to be instantiated.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
References chrec_convert(), chrec_dont_know, chrec_fold_minus(), chrec_fold_multiply(), fold_build1, fold_convert, gcc_unreachable, instantiate_scev_r(), integer_minus_one_node, and NULL.
Referenced by instantiate_scev_3().
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
"CHREC" that stands for a convert expression "(TYPE) OP" is to be instantiated.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
If we used chrec_convert_aggressive, we can no longer assume that signed chrecs do not overflow, as chrec_convert does, so avoid calling it in that case.
Referenced by instantiate_scev_3().
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is an SSA_NAME to be instantiated.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
A parameter (or loop invariant and we do not want to include evolutions in outer loops), nothing to do.
We cache the value of instantiated variable to avoid exponential time complexity due to reevaluations. We also store the convenient value in the cache in order to prevent infinite recursion – we do not want to instantiate the SSA_NAME if it is in a mixer structure. This is used for avoiding the instantiation of recursively defined functions, such as: | a_2 -> {0, +, 1, +, a_2}_1
On recursion return chrec_dont_know.
If the analysis yields a parametric chrec, instantiate the result again.
Don't instantiate default definitions.
Don't instantiate loop-closed-ssa phi nodes.
When there is no loop_closed_phi_def, it means that the variable is not used after the loop: try to still compute the value of the variable when exiting the loop.
??? We could try to compute the overall effect of the loop here.
Store the correct value to the cache.
Referenced by instantiate_scev_3().
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is a BIT_NOT_EXPR or a NEGATE_EXPR expression to be instantiated. Handle ~X as -1 - X. Handle -X as -1 * X.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
References chrec_dont_know, fold_build1, instantiate_scev_r(), TREE_CODE, TREE_OPERAND, and TREE_TYPE.
Referenced by instantiate_scev_3().
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is a polynomial chain of recurrence to be instantiated.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
References chrec_convert(), chrec_convert_aggressive(), chrec_dont_know, fold_convert, instantiate_scev_r(), and NULL.
Referenced by instantiate_scev_3().
|
static |
Analyze all the parameters of the chrec, between INSTANTIATE_BELOW and EVOLUTION_LOOP, that were left under a symbolic form.
CHREC is the scalar evolution to instantiate.
CACHE is the cache of already instantiated values.
FOLD_CONVERSIONS should be set to true when the conversions that may wrap in signed/pointer type are folded, as long as the value of the chrec is preserved.
SIZE_EXPR is used for computing the size of the expression to be instantiated, and to stop if it exceeds some limit.
Give up if the expression is larger than the MAX that we allow.
Too complicated to handle.
Referenced by get_instantiated_value_entry(), instantiate_array_ref(), instantiate_scev_1(), instantiate_scev_binary(), instantiate_scev_not(), and instantiate_scev_poly().
|
static |
This function merges the branches of a condition-phi-node, contained in the outermost loop, and whose arguments are already analyzed.
|
static |
Interpret the expression EXPR.
|
static |
Interpret the rhs of the assignment STMT.
|
static |
Analyze the scalar evolution for LOOP_PHI_NODE.
Dive one level deeper.
Interpret the subloop.
Otherwise really interpret the loop phi.
Verify we maintained the correct initial condition throughout possible conversions in the SSA chain.
References analyze_scalar_evolution(), ASSERT_EXPR_VAR, chrec_convert(), and is_gimple_min_invariant().
|
static |
Interpret the operation RHS1 OP RHS2. If we didn't analyze this node before, follow the definitions until ending either on an analyzed GIMPLE_ASSIGN, or on a loop-phi-node. On the return path, this function propagates evolutions (ala constant copy propagation). OPND1 is not a GIMPLE expression because we could analyze the effect of an inner loop: see interpret_loop_phi.
TYPE may be integer, real or complex, so use fold_convert.
Handle ~X as -1 - X.
In case we have a truncation of a widened operation that in the truncated type has undefined overflow behavior analyze the operation done in an unsigned type of the same precision as the final truncation. We cannot derive a scalar evolution for the widened operation but for the truncated result.
|
static |
Return the closed_loop_phi node for VAR. If there is none, return NULL_TREE.
Referenced by get_instantiated_value_entry().
|
static |
Return true when PHI is a loop-phi-node.
The implementation of this function is based on the following property: "all the loop-phi-nodes of a loop are contained in the loop's header basic block".
References chrec_dont_know, flow_loop_nested_p(), get_chrec_loop(), number_of_latch_executions(), and TREE_CODE.
Referenced by follow_ssa_edge_inner_loop_phi().
|
staticread |
Constructs a new SCEV_INFO_STR structure for VAR and INSTANTIATED_BELOW.
Referenced by del_scev_info().
tree number_of_exit_cond_executions | ( | ) |
Returns the number of executions of the exit condition of LOOP, i.e., the number by one higher than number_of_latch_executions. Note that unlike number_of_latch_executions, this number does not necessarily fit in the unsigned variant of the type of the control variable – if the number of iterations is a constant, we return chrec_dont_know if adding one to number_of_latch_executions overflows; however, in case the number of iterations is symbolic expression, the caller is responsible for dealing with this the possible overflow.
References dump_chrecs_stats(), dump_file, gather_stats_on_scev_database_1(), reset_chrecs_counters(), and scalar_evolution_info.
Referenced by vect_analyze_scalar_cycles().
tree number_of_latch_executions | ( | ) |
Entry point for the analysis of the number of iterations pass. This function tries to safely approximate the number of iterations the loop will run. When this property is not decidable at compile time, the result is chrec_dont_know. Otherwise the result is a scalar or a symbolic parameter. When the number of iterations may be equal to zero and the property cannot be determined at compile time, the result is a COND_EXPR that represents in a symbolic form the conditions under which the number of iterations is not zero.
Example of analysis: suppose that the loop has an exit condition:
"if (b > 49) goto end_loop;"
and that in a previous analysis we have determined that the variable 'b' has an evolution function:
"EF = {23, +, 5}_2".
When we evaluate the function at the point 5, i.e. the value of the variable 'b' after 5 iterations in the loop, we have EF (5) = 48, and EF (6) = 53. In this case the value of 'b' on exit is '53' and the loop body has been executed 6 times.
Determine whether the number of iterations in loop has already been computed.
Referenced by analyze_ziv_subscript(), and loop_phi_node_p().
|
inlinestatic |
Reset the counters.
References del_scev_info(), eq_scev_info(), hash_scev_info(), htab_create_ggc, initialize_scalar_evolutions_analyzer(), and scalar_evolution_info.
Referenced by number_of_exit_cond_executions().
tree resolve_mixers | ( | ) |
Similar to instantiate_parameters, but does not introduce the evolutions in outer loops for LOOP invariants in CHREC, and does not care about causing overflows, as long as they do not affect value of an expression.
References chrec_stats::nb_affine, chrec_stats::nb_affine_multivar, chrec_stats::nb_chrec_dont_know, chrec_stats::nb_chrecs, chrec_stats::nb_higher_poly, and chrec_stats::nb_undetermined.
Referenced by analyze_scalar_evolution(), and scev_reset().
unsigned int scev_const_prop | ( | void | ) |
Replace ssa names for that scev can prove they are constant by the appropriate constants. Also perform final value replacement in loops, in case the replacement expressions are cheap.
We only consider SSA names defined by phi nodes; rest is left to the ordinary constant propagation pass.
Replace the uses of the name.
Remove the ssa names that were replaced by constants. We do not remove them directly in the previous cycle, since this invalidates scev cache. Now the regular final value replacement.
If we do not know exact number of iterations of the loop, we cannot replace the final value.
Ensure that it is possible to insert new statements somewhere.
Moving the computation from the loop may prolong life range of some ssa names, which may cause problems if they appear on abnormal edges.
Do not emit expensive expressions. The rationale is that when someone writes a code like while (n > 45) n -= 45; he probably knows that n is not large, and does not want it to be turned into n %= 45.
Eliminate the PHI node and replace it by a computation outside the loop.
void scev_finalize | ( | void | ) |
Finalize the scalar evolution analysis.
References gsi_next(), gsi_stmt(), INTEGRAL_TYPE_P, PHI_ARG_DEF_FROM_EDGE, PHI_RESULT, POINTER_TYPE_P, TREE_TYPE, and virtual_operand_p().
Referenced by analyze_function().
void scev_initialize | ( | void | ) |
Initialize the analysis of scalar evolutions for LOOPS.
References integer_pow2p(), and TREE_OPERAND.
Referenced by analyze_function().
bool scev_initialized_p | ( | void | ) |
Return true if SCEV is initialized.
void scev_reset | ( | void | ) |
Cleans up the information cached by the scalar evolutions analysis in the hash table and in the loop->nb_iterations.
References analyze_scalar_evolution(), BITMAP_ALLOC, gsi_end_p(), gsi_next(), gsi_start_phis(), gsi_stmt(), INTEGRAL_TYPE_P, is_gimple_min_invariant(), basic_block_def::loop_father, may_propagate_copy(), NULL, PHI_RESULT, POINTER_TYPE_P, replace_uses_by(), resolve_mixers(), TREE_TYPE, and virtual_operand_p().
Referenced by vect_update_ivs_after_vectorizer().
void scev_reset_htab | ( | void | ) |
Cleans up the information cached by the scalar evolutions analysis in the hash table.
References type().
Referenced by gather_chrec_stats().
|
static |
Associate CHREC to SCALAR.
bool simple_iv | ( | struct loop * | wrto_loop, |
struct loop * | use_loop, | ||
tree | op, | ||
affine_iv * | iv, | ||
bool | allow_nonconstant_step | ||
) |
Checks whether use of OP in USE_LOOP behaves as a simple affine iv with respect to WRTO_LOOP and returns its base and step in IV if possible (see analyze_scalar_evolution_in_loop for more details on USE_LOOP and WRTO_LOOP). If ALLOW_NONCONSTANT_STEP is true, we want step to be invariant in LOOP. Otherwise we require it to be an integer constant.
IV->no_overflow is set to true if we are sure the iv cannot overflow (e.g. because it is computed in signed arithmetics). Consequently, adding an induction variable
for (i = IV->base; ; i += IV->step)
is only safe if IV->no_overflow is false, or TYPE_OVERFLOW_UNDEFINED is false for the type of the induction variable, or you can prove that i does not wrap by some other argument. Otherwise, this might introduce undefined behavior, and
for (i = iv->base; ; i = (type) ((unsigned type) i + (unsigned type) iv->step))
must be used instead.
Referenced by create_expression_by_pieces(), release_mem_refs(), and simplify_using_outer_evolutions().
tree chrec_dont_know |
Reserved to the cases where the analyzer has detected an undecidable property at compile time.
Referenced by affine_fn_univar(), analyze_evolution_in_loop(), analyze_miv_subscript(), analyze_scalar_evolution(), chrec_evaluate(), follow_ssa_edge_binary(), initialize_data_dependence_relation(), initialize_matrix_A(), instantiate_array_ref(), instantiate_scev_3(), instantiate_scev_binary(), instantiate_scev_not(), instantiate_scev_poly(), lambda_matrix_row_exchange(), loop_phi_node_p(), same_access_functions(), and vect_analyze_scalar_cycles().
tree chrec_known |
When the analyzer has detected that a property will never happen, then it qualifies it with chrec_known.
Referenced by analyze_overlapping_iterations(), instantiate_scev_3(), omega_extract_distance_vectors(), and vect_analyze_data_ref_dependences().
tree chrec_not_analyzed_yet |
The following trees are unique elements. Thus the comparison of another element to these elements should be done on the pointer to these trees, and not on their value. The SSA_NAMEs that are not yet analyzed are qualified with NULL_TREE.
Referenced by analyze_evolution_in_loop().
|
static |
Cache to avoid infinite recursion when instantiating an SSA name. Live during the outermost instantiate_scev or resolve_mixers call.
Referenced by instantiate_scev_1().
|
static |
|
static |
Counters for the scev database.
|
static |
Referenced by del_scev_info(), number_of_exit_cond_executions(), and reset_chrecs_counters().