OSDN Git Service

2007-01-05 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-scalar-evolution.c
index d4570a5..1946901 100644 (file)
@@ -48,7 +48,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    Given a scalar variable to be analyzed, follow the SSA edge to
    its definition:
      
-   - When the definition is a MODIFY_EXPR: if the right hand side
+   - When the definition is a GIMPLE_MODIFY_STMT: if the right hand side
    (RHS) of the definition cannot be statically analyzed, the answer
    of the analyzer is: "don't know".  
    Otherwise, for all the variables that are not yet analyzed in the
@@ -375,7 +375,7 @@ chrec_contains_symbols_defined_in_loop (tree chrec, unsigned loop_nb)
     {
       tree def = SSA_NAME_DEF_STMT (chrec);
       struct loop *def_loop = loop_containing_stmt (def);
-      struct loop *loop = current_loops->parray[loop_nb];
+      struct loop *loop = get_loop (loop_nb);
 
       if (def_loop == NULL)
        return false;
@@ -467,22 +467,15 @@ compute_overall_effect_of_inner_loop (struct loop *loop, tree evolution_fn)
     {
       if (CHREC_VARIABLE (evolution_fn) >= (unsigned) loop->num)
        {
-         struct loop *inner_loop = 
-           current_loops->parray[CHREC_VARIABLE (evolution_fn)];
-         tree nb_iter = number_of_iterations_in_loop (inner_loop);
+         struct loop *inner_loop = get_chrec_loop (evolution_fn);
+         tree nb_iter = number_of_latch_executions (inner_loop);
 
          if (nb_iter == chrec_dont_know)
            return chrec_dont_know;
          else
            {
              tree res;
-             tree type = chrec_type (nb_iter);
 
-             /* Number of iterations is off by one (the ssa name we
-                analyze must be defined before the exit).  */
-             nb_iter = chrec_fold_minus (type, nb_iter,
-                                         build_int_cst (type, 1));
-             
              /* evolution_fn is the evolution function in LOOP.  Get
                 its value in the nb_iter-th iteration.  */
              res = chrec_apply (inner_loop->num, evolution_fn, nb_iter);
@@ -511,7 +504,7 @@ bool
 chrec_is_positive (tree chrec, bool *value)
 {
   bool value0, value1, value2;
-  tree type, end_value, nb_iter;
+  tree end_value, nb_iter;
   
   switch (TREE_CODE (chrec))
     {
@@ -534,15 +527,10 @@ chrec_is_positive (tree chrec, bool *value)
       if (!evolution_function_is_affine_p (chrec))
        return false;
 
-      nb_iter = number_of_iterations_in_loop
-       (current_loops->parray[CHREC_VARIABLE (chrec)]);
-
+      nb_iter = number_of_latch_executions (get_chrec_loop (chrec));
       if (chrec_contains_undetermined (nb_iter))
        return false;
 
-      type = chrec_type (nb_iter);
-      nb_iter = chrec_fold_minus (type, nb_iter, build_int_cst (type, 1));
-
 #if 0
       /* TODO -- If the test is after the exit, we may decrease the number of
         iterations by one.  */
@@ -895,19 +883,6 @@ static inline tree
 set_nb_iterations_in_loop (struct loop *loop, 
                           tree res)
 {
-  tree type = chrec_type (res);
-
-  res = chrec_fold_plus (type, res, build_int_cst (type, 1));
-
-  /* FIXME HWI: However we want to store one iteration less than the
-     count of the loop in order to be compatible with the other
-     nb_iter computations in loop-iv.  This also allows the
-     representation of nb_iters that are equal to MAX_INT.  */
-  if (TREE_CODE (res) == INTEGER_CST
-      && (TREE_INT_CST_LOW (res) == 0
-         || TREE_OVERFLOW (res)))
-    res = chrec_dont_know;
-  
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "  (set_nb_iterations_in_loop = ");
@@ -1015,10 +990,9 @@ get_exit_conditions_rec (struct loop *loop,
    initializes the EXIT_CONDITIONS array.  */
 
 static void
-select_loops_exit_conditions (struct loops *loops, 
-                             VEC(tree,heap) **exit_conditions)
+select_loops_exit_conditions (VEC(tree,heap) **exit_conditions)
 {
-  struct loop *function_body = loops->parray[0];
+  struct loop *function_body = current_loops->tree_root;
   
   get_exit_conditions_rec (function_body->inner, exit_conditions);
 }
@@ -1406,15 +1380,15 @@ follow_ssa_edge (struct loop *loop, tree def, tree halting_phi,
       /* Outer loop.  */
       return t_false;
 
-    case MODIFY_EXPR:
+    case GIMPLE_MODIFY_STMT:
       return follow_ssa_edge_in_rhs (loop, def,
-                                    TREE_OPERAND (def, 1), 
+                                    GIMPLE_STMT_OPERAND (def, 1), 
                                     halting_phi, 
                                     evolution_of_loop, limit);
       
     default:
       /* At this level of abstraction, the program is just a set
-        of MODIFY_EXPRs and PHI_NODEs.  In principle there is no
+        of GIMPLE_MODIFY_STMTs and PHI_NODEs.  In principle there is no
         other node to be handled.  */
       return t_false;
     }
@@ -1608,16 +1582,16 @@ interpret_condition_phi (struct loop *loop, tree condition_phi)
   return res;
 }
 
-/* Interpret the right hand side of a modify_expr OPND1.  If we didn't
+/* Interpret the right hand side of a GIMPLE_MODIFY_STMT OPND1.  If we didn't
    analyze this node before, follow the definitions until ending
-   either on an analyzed modify_expr, or on a loop-phi-node.  On the
+   either on an analyzed GIMPLE_MODIFY_STMT, 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.  */
 
 static tree
-interpret_rhs_modify_expr (struct loop *loop, tree at_stmt,
-                          tree opnd1, tree type)
+interpret_rhs_modify_stmt (struct loop *loop, tree at_stmt,
+                                 tree opnd1, tree type)
 {
   tree res, opnd10, opnd11, chrec10, chrec11;
 
@@ -1870,12 +1844,11 @@ pointer_used_p (tree ptr)
   imm_use_iterator imm_iter;
   tree stmt, rhs;
   struct ptr_info_def *pi = get_ptr_info (ptr);
-  var_ann_t v_ann = var_ann (SSA_NAME_VAR (ptr));
 
   /* Check whether the pointer has a memory tag; if it does, it is
      (or at least used to be) dereferenced.  */
   if ((pi != NULL && pi->name_mem_tag != NULL)
-      || v_ann->symbol_mem_tag)
+      || symbol_mem_tag (SSA_NAME_VAR (ptr)))
     return true;
 
   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ptr)
@@ -1884,15 +1857,15 @@ pointer_used_p (tree ptr)
       if (TREE_CODE (stmt) == COND_EXPR)
        return true;
 
-      if (TREE_CODE (stmt) != MODIFY_EXPR)
+      if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
        continue;
 
-      rhs = TREE_OPERAND (stmt, 1);
+      rhs = GIMPLE_STMT_OPERAND (stmt, 1);
       if (!COMPARISON_CLASS_P (rhs))
        continue;
 
-      if (TREE_OPERAND (stmt, 0) == ptr
-         || TREE_OPERAND (stmt, 1) == ptr)
+      if (GIMPLE_STMT_OPERAND (stmt, 0) == ptr
+         || GIMPLE_STMT_OPERAND (stmt, 1) == ptr)
        return true;
     }
 
@@ -1912,7 +1885,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
     return chrec_dont_know;
 
   if (TREE_CODE (var) != SSA_NAME)
-    return interpret_rhs_modify_expr (loop, NULL_TREE, var, type);
+    return interpret_rhs_modify_stmt (loop, NULL_TREE, var, type);
 
   def = SSA_NAME_DEF_STMT (var);
   bb = bb_for_stmt (def);
@@ -1945,8 +1918,9 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
 
   switch (TREE_CODE (def))
     {
-    case MODIFY_EXPR:
-      res = interpret_rhs_modify_expr (loop, def, TREE_OPERAND (def, 1), type);
+    case GIMPLE_MODIFY_STMT:
+      res = interpret_rhs_modify_stmt (loop, def,
+                                      GIMPLE_STMT_OPERAND (def, 1), type);
 
       if (POINTER_TYPE_P (type)
          && !automatically_generated_chrec_p (res)
@@ -2468,7 +2442,7 @@ resolve_mixers (struct loop *loop, tree chrec)
    the loop body has been executed 6 times.  */
 
 tree 
-number_of_iterations_in_loop (struct loop *loop)
+number_of_latch_executions (struct loop *loop)
 {
   tree res, type;
   edge exit;
@@ -2503,6 +2477,33 @@ end:
   return set_nb_iterations_in_loop (loop, res);
 }
 
+/* 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 unline 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.  */
+
+tree 
+number_of_exit_cond_executions (struct loop *loop)
+{
+  tree ret = number_of_latch_executions (loop);
+  tree type = chrec_type (ret);
+
+  if (chrec_contains_undetermined (ret))
+    return ret;
+
+  ret = chrec_fold_plus (type, ret, build_int_cst (type, 1));
+  if (TREE_CODE (ret) == INTEGER_CST
+      && TREE_OVERFLOW (ret))
+    return chrec_dont_know;
+
+  return ret;
+}
+
 /* One of the drivers for testing the scalar evolutions analysis.
    This function computes the number of iterations for all the loops
    from the EXIT_CONDITIONS array.  */
@@ -2517,7 +2518,7 @@ number_of_iterations_for_all_loops (VEC(tree,heap) **exit_conditions)
   
   for (i = 0; VEC_iterate (tree, *exit_conditions, i, cond); i++)
     {
-      tree res = number_of_iterations_in_loop (loop_containing_stmt (cond));
+      tree res = number_of_latch_executions (loop_containing_stmt (cond));
       if (chrec_contains_undetermined (res))
        nb_chrec_dont_know_loops++;
       else
@@ -2530,7 +2531,7 @@ number_of_iterations_for_all_loops (VEC(tree,heap) **exit_conditions)
       fprintf (dump_file, "-----------------------------------------\n");
       fprintf (dump_file, "%d\tnb_chrec_dont_know_loops\n", nb_chrec_dont_know_loops);
       fprintf (dump_file, "%d\tnb_static_loops\n", nb_static_loops);
-      fprintf (dump_file, "%d\tnb_total_loops\n", current_loops->num);
+      fprintf (dump_file, "%d\tnb_total_loops\n", number_of_loops ());
       fprintf (dump_file, "-----------------------------------------\n");
       fprintf (dump_file, ")\n\n");
       
@@ -2745,10 +2746,10 @@ initialize_scalar_evolutions_analyzer (void)
 /* Initialize the analysis of scalar evolutions for LOOPS.  */
 
 void
-scev_initialize (struct loops *loops)
+scev_initialize (void)
 {
-  unsigned i;
-  current_loops = loops;
+  loop_iterator li;
+  struct loop *loop;
 
   scalar_evolution_info = htab_create (100, hash_scev_info,
                                       eq_scev_info, del_scev_info);
@@ -2756,9 +2757,10 @@ scev_initialize (struct loops *loops)
   
   initialize_scalar_evolutions_analyzer ();
 
-  for (i = 1; i < loops->num; i++)
-    if (loops->parray[i])
-      loops->parray[i]->nb_iterations = NULL_TREE;
+  FOR_EACH_LOOP (li, loop, 0)
+    {
+      loop->nb_iterations = NULL_TREE;
+    }
 }
 
 /* Cleans up the information cached by the scalar evolutions analysis.  */
@@ -2766,18 +2768,16 @@ scev_initialize (struct loops *loops)
 void
 scev_reset (void)
 {
-  unsigned i;
+  loop_iterator li;
   struct loop *loop;
 
   if (!scalar_evolution_info || !current_loops)
     return;
 
   htab_empty (scalar_evolution_info);
-  for (i = 1; i < current_loops->num; i++)
+  FOR_EACH_LOOP (li, loop, 0)
     {
-      loop = current_loops->parray[i];
-      if (loop)
-       loop->nb_iterations = NULL_TREE;
+      loop->nb_iterations = NULL_TREE;
     }
 }
 
@@ -2813,6 +2813,7 @@ simple_iv (struct loop *loop, tree stmt, tree op, affine_iv *iv,
       && !chrec_contains_symbols_defined_in_loop (ev, loop->num))
     {
       iv->base = ev;
+      iv->step = build_int_cst (TREE_TYPE (ev), 0);
       iv->no_overflow = true;
       return true;
     }
@@ -2850,7 +2851,7 @@ scev_analysis (void)
   VEC(tree,heap) *exit_conditions;
   
   exit_conditions = VEC_alloc (tree, heap, 37);
-  select_loops_exit_conditions (current_loops, &exit_conditions);
+  select_loops_exit_conditions (&exit_conditions);
 
   if (dump_file && (dump_flags & TDF_STATS))
     analyze_scalar_evolution_for_all_loop_phi_nodes (&exit_conditions);
@@ -2891,6 +2892,7 @@ scev_const_prop (void)
   struct loop *loop, *ex_loop;
   bitmap ssa_names_to_remove = NULL;
   unsigned i;
+  loop_iterator li;
 
   if (!current_loops)
     return 0;
@@ -2927,12 +2929,12 @@ scev_const_prop (void)
        }
     }
 
-  /* Remove the ssa names that were replaced by constants.  We do not remove them
-     directly in the previous cycle, since this invalidates scev cache.  */
+  /* Remove the ssa names that were replaced by constants.  We do not
+     remove them directly in the previous cycle, since this
+     invalidates scev cache.  */
   if (ssa_names_to_remove)
     {
       bitmap_iterator bi;
-      unsigned i;
 
       EXECUTE_IF_SET_IN_BITMAP (ssa_names_to_remove, 0, i, bi)
        {
@@ -2940,7 +2942,7 @@ scev_const_prop (void)
          phi = SSA_NAME_DEF_STMT (name);
 
          gcc_assert (TREE_CODE (phi) == PHI_NODE);
-         remove_phi_node (phi, NULL);
+         remove_phi_node (phi, NULL, true);
        }
 
       BITMAP_FREE (ssa_names_to_remove);
@@ -2948,23 +2950,19 @@ scev_const_prop (void)
     }
 
   /* Now the regular final value replacement.  */
-  for (i = current_loops->num - 1; i > 0; i--)
+  FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
     {
       edge exit;
       tree def, rslt, ass, niter;
       block_stmt_iterator bsi;
 
-      loop = current_loops->parray[i];
-      if (!loop)
-       continue;
-
       /* If we do not know exact number of iterations of the loop, we cannot
         replace the final value.  */
       exit = single_exit (loop);
       if (!exit)
        continue;
 
-      niter = number_of_iterations_in_loop (loop);
+      niter = number_of_latch_executions (loop);
       if (niter == chrec_dont_know
          /* If computing the number of iterations is expensive, it may be
             better not to introduce computations involving it.  */
@@ -3001,20 +2999,19 @@ scev_const_prop (void)
              || contains_abnormal_ssa_name_p (def))
            continue;
 
-         /* Eliminate the phi node and replace it by a computation outside
+         /* Eliminate the PHI node and replace it by a computation outside
             the loop.  */
          def = unshare_expr (def);
-         SET_PHI_RESULT (phi, NULL_TREE);
-         remove_phi_node (phi, NULL_TREE);
+         remove_phi_node (phi, NULL_TREE, false);
 
-         ass = build2 (MODIFY_EXPR, void_type_node, rslt, NULL_TREE);
+         ass = build2 (GIMPLE_MODIFY_STMT, void_type_node, rslt, NULL_TREE);
          SSA_NAME_DEF_STMT (rslt) = ass;
          {
            block_stmt_iterator dest = bsi;
            bsi_insert_before (&dest, ass, BSI_NEW_STMT);
            def = force_gimple_operand_bsi (&dest, def, false, NULL_TREE);
          }
-         TREE_OPERAND (ass, 1) = def;
+         GIMPLE_STMT_OPERAND (ass, 1) = def;
          update_stmt (ass);
        }
     }