GCC Middle and Back End API Reference
tree-scalar-evolution.c File 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"
Include dependency graph for tree-scalar-evolution.c:

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_strnew_scev_info_str ()
static hashval_t hash_scev_info ()
static int eq_scev_info ()
static void del_scev_info ()
static treefind_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_typeglobal_cache

Typedef Documentation

typedef enum t_bool t_bool

Depth first search algorithm.


Enumeration Type Documentation

enum t_bool

Depth first search algorithm.

Enumerator:
t_false 
t_true 
t_dont_know 

Function Documentation

static tree add_to_evolution ( unsigned  loop_nb,
tree  chrec_before,
enum tree_code  code,
tree  to_add,
gimple  at_stmt 
)
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:

  1. a = loop-phi (init, a + expr)
  2. a = loop-phi (init, expr)

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 tree add_to_evolution_1 ( unsigned  loop_nb,
tree  chrec_before,
tree  to_add,
gimple  at_stmt 
)
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.   
static tree analyze_evolution_in_loop ( gimple  loop_phi_node,
tree  init_cond 
)
static

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 tree analyze_initial_condition ( )
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().

static tree analyze_scalar_evolution_1 ( struct loop ,
tree  ,
tree   
)
static

Scalar evolution detector. Copyright (C) 2003-2013 Free Software Foundation, Inc. Contributed by Sebastian Pop s.pop.nosp@m.@lap.nosp@m.oste..nosp@m.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 tree analyze_scalar_evolution_1 ( )
static

Helper recursive function.

Keep the symbolic form.   

Keep the symbolic form.

static tree analyze_scalar_evolution_for_address_of ( struct loop loop,
tree  var 
)
static
static tree analyze_scalar_evolution_for_address_of ( )
static
static tree analyze_scalar_evolution_in_loop ( struct loop wrto_loop,
struct loop use_loop,
tree  version,
bool folded_casts 
)
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 bool backedge_phi_arg_p ( )
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 tree compute_scalar_evolution_in_loop ( struct loop wrto_loop,
struct loop def_loop,
tree  ev 
)
static

This section contains all the entry points:

  • number_of_iterations_in_loop,
  • analyze_scalar_evolution,
  • instantiate_parameters. Compute and return the evolution function in WRTO_LOOP, the nearest common ancestor of DEF_LOOP and USE_LOOP.

References block_before_loop(), dump_file, dump_flags, get_scalar_evolution(), loop::num, and print_generic_expr().

static void del_scev_info ( )
static
static void dump_chrecs_stats ( )
static

Dump the contents of a CHREC_STATS structure.

References loop::nb_iterations, and NULL_TREE.

Referenced by number_of_exit_cond_executions().

static int eq_idx_scev_info ( )
inlinestatic

Compares database elements E1 and E2.

static int eq_scev_info ( )
inlinestatic

Compares database elements E1 and E2.

References ggc_free().

Referenced by reset_chrecs_counters().

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 tree* find_var_scev_info ( )
static

Get the scalar evolution of VAR for INSTANTIATED_BELOW basic block. A first query on VAR returns chrec_not_analyzed_yet.

static t_bool follow_ssa_edge ( struct loop loop,
gimple  def,
gimple  halting_phi,
tree evolution_of_loop,
int  limit 
)
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 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

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 t_bool follow_ssa_edge_expr ( struct loop loop,
gimple  at_stmt,
tree  expr,
gimple  halting_phi,
tree evolution_of_loop,
int  limit 
)
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 t_bool follow_ssa_edge_in_condition_phi ( struct loop loop,
gimple  condition_phi,
gimple  halting_phi,
tree evolution_of_loop,
int  limit 
)
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().

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 
)
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 t_bool follow_ssa_edge_in_rhs ( struct loop loop,
gimple  stmt,
gimple  halting_phi,
tree evolution_of_loop,
int  limit 
)
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 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

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 void gather_chrec_stats ( )
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 int gather_stats_on_scev_database_1 ( )
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 unsigned get_instantiated_value_entry ( instantiate_cache_type cache,
tree  name,
basic_block  instantiate_below 
)
static
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 tree get_scalar_evolution ( )
static

Retrieve the chrec associated to SCALAR instantiated below INSTANTIATED_BELOW block.

Referenced by compute_scalar_evolution_in_loop().

static hashval_t hash_idx_scev_info ( )
inlinestatic

Computes a hash function for database element ELT.

static hashval_t hash_scev_info ( )
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 void initialize_scalar_evolutions_analyzer ( )
static

Initializer.

The elements below are unique.

Referenced by reset_chrecs_counters().

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

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 tree instantiate_scev_1 ( basic_block  instantiate_below,
struct loop evolution_loop,
struct loop inner_loop,
tree  chrec,
bool  fold_conversions,
int  size_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.

References dump_file, dump_flags, global_cache, basic_block_def::index, instantiate_scev_r(), NULL, loop::num, and print_generic_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

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 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

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 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

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 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

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 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

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 &ndash; 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 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

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 tree instantiate_scev_poly ( basic_block  instantiate_below,
struct loop evolution_loop,
struct loop ,
tree  chrec,
bool  fold_conversions,
int  size_expr 
)
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 tree instantiate_scev_r ( basic_block  instantiate_below,
struct loop evolution_loop,
struct loop inner_loop,
tree  chrec,
bool  fold_conversions,
int  size_expr 
)
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 tree interpret_condition_phi ( )
static

This function merges the branches of a condition-phi-node, contained in the outermost loop, and whose arguments are already analyzed.

static tree interpret_expr ( )
static

Interpret the expression EXPR.

static tree interpret_gimple_assign ( )
static

Interpret the rhs of the assignment STMT.

static tree interpret_loop_phi ( )
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 tree interpret_rhs_expr ( struct loop loop,
gimple  at_stmt,
tree  type,
tree  rhs1,
enum tree_code  code,
tree  rhs2 
)
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 tree loop_closed_phi_def ( )
static

Return the closed_loop_phi node for VAR. If there is none, return NULL_TREE.

Referenced by get_instantiated_value_entry().

static bool loop_phi_node_p ( )
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().

static struct scev_info_str* new_scev_info_str ( )
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().

static void reset_chrecs_counters ( )
inlinestatic
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  )
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 void set_scalar_evolution ( )
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().


Variable Documentation

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().

instantiate_cache_type* global_cache
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().

unsigned nb_get_scev = 0
static
unsigned nb_set_scev = 0
static

Counters for the scev database.

htab_t scalar_evolution_info
static