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

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(), print_generic_expr(), print_gimple_stmt(), and edge_def::src.

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 ( )
@verbatim 

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

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 ( )
@verbatim 

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

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.

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, 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 loop::nb_iterations, 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, and affine_iv_d::step.

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, and instantiate_scev_r().

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(), 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 chrec_dont_know, chrec_known, chrec_type(), instantiate_scev_binary(), instantiate_scev_convert(), instantiate_scev_name(), instantiate_scev_not(), and instantiate_scev_poly().

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(), and instantiate_scev_r().

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 -- 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, and instantiate_scev_r().

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, and instantiate_scev_r().

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(), 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(), and number_of_latch_executions().

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(), find_scop_parameters(), 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(), and virtual_operand_p().

Referenced by analyze_function().

void scev_initialize ( void  )
   Initialize the analysis of scalar evolutions for LOOPS.  

References integer_pow2p().

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(), gsi_end_p(), gsi_next(), gsi_start_phis(), gsi_stmt(), is_gimple_min_invariant(), basic_block_def::loop_father, may_propagate_copy(), replace_uses_by(), resolve_mixers(), 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 close_phi_written_to_memory(), and 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