OSDN Git Service

* configure.ac (gcc_cv_nm): Don't use an in-tree nm if
[pf3gnuchains/gcc-fork.git] / gcc / tree-scalar-evolution.c
index 2b0d817..6fcfaa4 100644 (file)
@@ -476,12 +476,12 @@ compute_overall_effect_of_inner_loop (struct loop *loop, tree evolution_fn)
          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 (chrec_type (nb_iter),
-                               nb_iter,
-                               build_int_cst_type (chrec_type (nb_iter), 1));
+             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.  */
@@ -510,10 +510,8 @@ compute_overall_effect_of_inner_loop (struct loop *loop, tree evolution_fn)
 bool
 chrec_is_positive (tree chrec, bool *value)
 {
-  bool value0, value1;
-  bool value2;
-  tree end_value;
-  tree nb_iter;
+  bool value0, value1, value2;
+  tree type, end_value, nb_iter;
   
   switch (TREE_CODE (chrec))
     {
@@ -542,17 +540,14 @@ chrec_is_positive (tree chrec, bool *value)
       if (chrec_contains_undetermined (nb_iter))
        return false;
 
-      nb_iter = chrec_fold_minus 
-       (chrec_type (nb_iter), nb_iter,
-        build_int_cst (chrec_type (nb_iter), 1));
+      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.  */
       if (after_exit)
-       nb_iter = chrec_fold_minus 
-               (chrec_type (nb_iter), nb_iter,
-                build_int_cst (chrec_type (nb_iter), 1));
+       nb_iter = chrec_fold_minus (type, nb_iter, build_int_cst (type, 1));
 #endif
 
       end_value = chrec_apply (CHREC_VARIABLE (chrec), chrec, nb_iter);
@@ -659,18 +654,19 @@ get_scalar_evolution (tree scalar)
    part for this loop.  */
 
 static tree
-add_to_evolution_1 (unsigned loop_nb, 
-                   tree chrec_before, 
-                   tree to_add)
+add_to_evolution_1 (unsigned loop_nb, tree chrec_before, tree to_add,
+                   tree at_stmt)
 {
+  tree type, left, right;
+
   switch (TREE_CODE (chrec_before))
     {
     case POLYNOMIAL_CHREC:
       if (CHREC_VARIABLE (chrec_before) <= loop_nb)
        {
          unsigned var;
-         tree left, right;
-         tree type = chrec_type (chrec_before);
+
+         type = chrec_type (chrec_before);
          
          /* When there is no evolution part in this loop, build it.  */
          if (CHREC_VARIABLE (chrec_before) < loop_nb)
@@ -688,21 +684,30 @@ add_to_evolution_1 (unsigned loop_nb,
              right = CHREC_RIGHT (chrec_before);
            }
 
-         return build_polynomial_chrec 
-           (var, left, chrec_fold_plus (type, right, to_add));
+         to_add = chrec_convert (type, to_add, at_stmt);
+         right = chrec_convert (type, right, at_stmt);
+         right = chrec_fold_plus (type, right, to_add);
+         return build_polynomial_chrec (var, left, right);
        }
       else
-       /* Search the evolution in LOOP_NB.  */
-       return build_polynomial_chrec 
-         (CHREC_VARIABLE (chrec_before),
-          add_to_evolution_1 (loop_nb, CHREC_LEFT (chrec_before), to_add),
-          CHREC_RIGHT (chrec_before));
+       {
+         /* Search the evolution in LOOP_NB.  */
+         left = add_to_evolution_1 (loop_nb, CHREC_LEFT (chrec_before),
+                                    to_add, at_stmt);
+         right = CHREC_RIGHT (chrec_before);
+         right = chrec_convert (chrec_type (left), right, at_stmt);
+         return build_polynomial_chrec (CHREC_VARIABLE (chrec_before),
+                                        left, right);
+       }
       
     default:
       /* These nodes do not depend on a loop.  */
       if (chrec_before == chrec_dont_know)
        return chrec_dont_know;
-      return build_polynomial_chrec (loop_nb, chrec_before, to_add);
+
+      left = chrec_before;
+      right = chrec_convert (chrec_type (left), to_add, at_stmt);
+      return build_polynomial_chrec (loop_nb, left, right);
     }
 }
 
@@ -841,10 +846,8 @@ add_to_evolution_1 (unsigned loop_nb,
 */
 
 static tree 
-add_to_evolution (unsigned loop_nb, 
-                 tree chrec_before,
-                 enum tree_code code,
-                 tree to_add)
+add_to_evolution (unsigned loop_nb, tree chrec_before, enum tree_code code,
+                 tree to_add, tree at_stmt)
 {
   tree type = chrec_type (to_add);
   tree res = NULL_TREE;
@@ -874,7 +877,7 @@ add_to_evolution (unsigned loop_nb,
                                  ? build_real (type, dconstm1)
                                  : build_int_cst_type (type, -1));
 
-  res = add_to_evolution_1 (loop_nb, chrec_before, to_add);
+  res = add_to_evolution_1 (loop_nb, chrec_before, to_add, at_stmt);
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
@@ -892,8 +895,9 @@ static inline tree
 set_nb_iterations_in_loop (struct loop *loop, 
                           tree res)
 {
-  res = chrec_fold_plus (chrec_type (res), res,
-                        build_int_cst_type (chrec_type (res), 1));
+  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
@@ -1094,7 +1098,7 @@ follow_ssa_edge_in_rhs (struct loop *loop, tree at_stmt, tree rhs,
                *evolution_of_loop = add_to_evolution 
                  (loop->num, 
                   chrec_convert (type_rhs, evol, at_stmt), 
-                  PLUS_EXPR, rhs1);
+                  PLUS_EXPR, rhs1, at_stmt);
              
              else if (res == t_false)
                {
@@ -1106,7 +1110,7 @@ follow_ssa_edge_in_rhs (struct loop *loop, tree at_stmt, tree rhs,
                    *evolution_of_loop = add_to_evolution 
                      (loop->num, 
                       chrec_convert (type_rhs, *evolution_of_loop, at_stmt), 
-                      PLUS_EXPR, rhs0);
+                      PLUS_EXPR, rhs0, at_stmt);
 
                  else if (res == t_dont_know)
                    *evolution_of_loop = chrec_dont_know;
@@ -1127,7 +1131,7 @@ follow_ssa_edge_in_rhs (struct loop *loop, tree at_stmt, tree rhs,
                *evolution_of_loop = add_to_evolution 
                  (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
                                             at_stmt),
-                  PLUS_EXPR, rhs1);
+                  PLUS_EXPR, rhs1, at_stmt);
 
              else if (res == t_dont_know)
                *evolution_of_loop = chrec_dont_know;
@@ -1145,7 +1149,7 @@ follow_ssa_edge_in_rhs (struct loop *loop, tree at_stmt, tree rhs,
            *evolution_of_loop = add_to_evolution 
              (loop->num, chrec_convert (type_rhs, *evolution_of_loop,
                                         at_stmt),
-              PLUS_EXPR, rhs0);
+              PLUS_EXPR, rhs0, at_stmt);
 
          else if (res == t_dont_know)
            *evolution_of_loop = chrec_dont_know;
@@ -1175,7 +1179,7 @@ follow_ssa_edge_in_rhs (struct loop *loop, tree at_stmt, tree rhs,
          if (res == t_true)
            *evolution_of_loop = add_to_evolution 
              (loop->num, chrec_convert (type_rhs, *evolution_of_loop, at_stmt),
-              MINUS_EXPR, rhs1);
+              MINUS_EXPR, rhs1, at_stmt);
 
          else if (res == t_dont_know)
            *evolution_of_loop = chrec_dont_know;
@@ -1647,9 +1651,9 @@ interpret_rhs_modify_expr (struct loop *loop, tree at_stmt,
       opnd10 = TREE_OPERAND (opnd1, 0);
       chrec10 = analyze_scalar_evolution (loop, opnd10);
       chrec10 = chrec_convert (type, chrec10, at_stmt);
-      res = chrec_fold_multiply (type, chrec10, SCALAR_FLOAT_TYPE_P (type)
-                                 ? build_real (type, dconstm1)
-                                 : build_int_cst_type (type, -1));
+      /* TYPE may be integer, real or complex, so use fold_convert.  */
+      res = chrec_fold_multiply (type, chrec10,
+                                fold_convert (type, integer_minus_one_node));
       break;
 
     case MULT_EXPR:
@@ -1723,7 +1727,7 @@ analyze_scalar_evolution_1 (struct loop *loop, tree var, tree res)
   basic_block bb;
   struct loop *def_loop;
 
-  if (loop == NULL)
+  if (loop == NULL || TREE_CODE (type) == VECTOR_TYPE)
     return chrec_dont_know;
 
   if (TREE_CODE (var) != SSA_NAME)
@@ -1831,19 +1835,28 @@ analyze_scalar_evolution (struct loop *loop, tree var)
 
 /* Analyze scalar evolution of use of VERSION in USE_LOOP with respect to
    WRTO_LOOP (which should be a superloop of both USE_LOOP and definition
-   of VERSION).  */
+   of VERSION).
+
+   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).  */
 
 static tree
 analyze_scalar_evolution_in_loop (struct loop *wrto_loop, struct loop *use_loop,
-                                 tree version)
+                                 tree version, bool *folded_casts)
 {
   bool val = false;
-  tree ev = version;
+  tree ev = version, tmp;
 
+  if (folded_casts)
+    *folded_casts = false;
   while (1)
     {
-      ev = analyze_scalar_evolution (use_loop, ev);
-      ev = resolve_mixers (use_loop, ev);
+      tmp = analyze_scalar_evolution (use_loop, ev);
+      ev = resolve_mixers (use_loop, tmp);
+
+      if (folded_casts && tmp != ev)
+       *folded_casts = true;
 
       if (use_loop == wrto_loop)
        return ev;
@@ -1941,6 +1954,7 @@ instantiate_parameters_1 (struct loop *loop, tree chrec, int flags, htab_t cache
   tree res, op0, op1, op2;
   basic_block def_bb;
   struct loop *def_loop;
+  tree type = chrec_type (chrec);
 
   /* Give up if the expression is larger than the MAX that we allow.  */
   if (size_expr++ > PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
@@ -2034,7 +2048,10 @@ instantiate_parameters_1 (struct loop *loop, tree chrec, int flags, htab_t cache
 
       if (CHREC_LEFT (chrec) != op0
          || CHREC_RIGHT (chrec) != op1)
-       chrec = build_polynomial_chrec (CHREC_VARIABLE (chrec), op0, op1);
+       {
+         op1 = chrec_convert (chrec_type (op0), op1, NULL_TREE);
+         chrec = build_polynomial_chrec (CHREC_VARIABLE (chrec), op0, op1);
+       }
       return chrec;
 
     case PLUS_EXPR:
@@ -2050,7 +2067,11 @@ instantiate_parameters_1 (struct loop *loop, tree chrec, int flags, htab_t cache
 
       if (TREE_OPERAND (chrec, 0) != op0
          || TREE_OPERAND (chrec, 1) != op1)
-       chrec = chrec_fold_plus (TREE_TYPE (chrec), op0, op1);
+       {
+         op0 = chrec_convert (type, op0, NULL_TREE);
+         op1 = chrec_convert (type, op1, NULL_TREE);
+         chrec = chrec_fold_plus (type, op0, op1);
+       }
       return chrec;
 
     case MINUS_EXPR:
@@ -2066,7 +2087,11 @@ instantiate_parameters_1 (struct loop *loop, tree chrec, int flags, htab_t cache
 
       if (TREE_OPERAND (chrec, 0) != op0
          || TREE_OPERAND (chrec, 1) != op1)
-        chrec = chrec_fold_minus (TREE_TYPE (chrec), op0, op1);
+       {
+         op0 = chrec_convert (type, op0, NULL_TREE);
+         op1 = chrec_convert (type, op1, NULL_TREE);
+         chrec = chrec_fold_minus (type, op0, op1);
+       }
       return chrec;
 
     case MULT_EXPR:
@@ -2082,7 +2107,11 @@ instantiate_parameters_1 (struct loop *loop, tree chrec, int flags, htab_t cache
 
       if (TREE_OPERAND (chrec, 0) != op0
          || TREE_OPERAND (chrec, 1) != op1)
-       chrec = chrec_fold_multiply (TREE_TYPE (chrec), op0, op1);
+       {
+         op0 = chrec_convert (type, op0, NULL_TREE);
+         op1 = chrec_convert (type, op1, NULL_TREE);
+         chrec = chrec_fold_multiply (type, op0, op1);
+       }
       return chrec;
 
     case NOP_EXPR:
@@ -2561,33 +2590,38 @@ scev_reset (void)
 }
 
 /* Checks whether OP behaves as a simple affine iv of LOOP in STMT and returns
-   its BASE and STEP if possible.  If ALLOW_NONCONSTANT_STEP is true, we
-   want STEP to be invariant in LOOP.  Otherwise we require it to be an
-   integer constant.  */
+   its base and step in IV if possible.  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).  */
 
 bool
-simple_iv (struct loop *loop, tree stmt, tree op, tree *base, tree *step,
+simple_iv (struct loop *loop, tree stmt, tree op, affine_iv *iv,
           bool allow_nonconstant_step)
 {
   basic_block bb = bb_for_stmt (stmt);
   tree type, ev;
+  bool folded_casts;
 
-  *base = NULL_TREE;
-  *step = NULL_TREE;
+  iv->base = NULL_TREE;
+  iv->step = NULL_TREE;
+  iv->no_overflow = false;
 
   type = TREE_TYPE (op);
   if (TREE_CODE (type) != INTEGER_TYPE
       && TREE_CODE (type) != POINTER_TYPE)
     return false;
 
-  ev = analyze_scalar_evolution_in_loop (loop, bb->loop_father, op);
+  ev = analyze_scalar_evolution_in_loop (loop, bb->loop_father, op,
+                                        &folded_casts);
   if (chrec_contains_undetermined (ev))
     return false;
 
   if (tree_does_not_contain_chrecs (ev)
       && !chrec_contains_symbols_defined_in_loop (ev, loop->num))
     {
-      *base = ev;
+      iv->base = ev;
+      iv->no_overflow = true;
       return true;
     }
 
@@ -2595,21 +2629,24 @@ simple_iv (struct loop *loop, tree stmt, tree op, tree *base, tree *step,
       || CHREC_VARIABLE (ev) != (unsigned) loop->num)
     return false;
 
-  *step = CHREC_RIGHT (ev);
+  iv->step = CHREC_RIGHT (ev);
   if (allow_nonconstant_step)
     {
-      if (tree_contains_chrecs (*step, NULL)
-         || chrec_contains_symbols_defined_in_loop (*step, loop->num))
+      if (tree_contains_chrecs (iv->step, NULL)
+         || chrec_contains_symbols_defined_in_loop (iv->step, loop->num))
        return false;
     }
-  else if (TREE_CODE (*step) != INTEGER_CST)
+  else if (TREE_CODE (iv->step) != INTEGER_CST)
     return false;
 
-  *base = CHREC_LEFT (ev);
-  if (tree_contains_chrecs (*base, NULL)
-      || chrec_contains_symbols_defined_in_loop (*base, loop->num))
+  iv->base = CHREC_LEFT (ev);
+  if (tree_contains_chrecs (iv->base, NULL)
+      || chrec_contains_symbols_defined_in_loop (iv->base, loop->num))
     return false;
 
+  iv->no_overflow = (!folded_casts
+                    && !flag_wrapv
+                    && !TYPE_UNSIGNED (type));
   return true;
 }
 
@@ -2654,7 +2691,7 @@ expression_expensive_p (tree expr)
    We only consider SSA names defined by phi nodes; rest is left to the
    ordinary constant propagation pass.  */
 
-void
+unsigned int
 scev_const_prop (void)
 {
   basic_block bb;
@@ -2664,7 +2701,7 @@ scev_const_prop (void)
   unsigned i;
 
   if (!current_loops)
-    return;
+    return 0;
 
   FOR_EACH_BB (bb)
     {
@@ -2722,7 +2759,7 @@ scev_const_prop (void)
   for (i = current_loops->num - 1; i > 0; i--)
     {
       edge exit;
-      tree def, rslt, ass;
+      tree def, rslt, ass, niter;
       block_stmt_iterator bsi;
 
       loop = current_loops->parray[i];
@@ -2732,8 +2769,14 @@ scev_const_prop (void)
       /* If we do not know exact number of iterations of the loop, we cannot
         replace the final value.  */
       exit = loop->single_exit;
-      if (!exit
-         || number_of_iterations_in_loop (loop) == chrec_dont_know)
+      if (!exit)
+       continue;
+
+      niter = number_of_iterations_in_loop (loop);
+      if (niter == chrec_dont_know
+         /* If computing the number of iterations is expensive, it may be
+            better not to introduce computations involving it.  */
+         || expression_expensive_p (niter))
        continue;
 
       /* Ensure that it is possible to insert new statements somewhere.  */
@@ -2756,17 +2799,12 @@ scev_const_prop (void)
              && !INTEGRAL_TYPE_P (TREE_TYPE (def)))
            continue;
 
-         def = analyze_scalar_evolution_in_loop (ex_loop, loop, def);
+         def = analyze_scalar_evolution_in_loop (ex_loop, loop, def, NULL);
          def = compute_overall_effect_of_inner_loop (ex_loop, def);
          if (!tree_does_not_contain_chrecs (def)
              || chrec_contains_symbols_defined_in_loop (def, ex_loop->num))
            continue;
 
-         /* If computing the expression is expensive, let it remain in the
-            loop.  */
-         if (expression_expensive_p (def))
-           continue;
-
          /* Eliminate the phi node and replace it by a computation outside
             the loop.  */
          def = unshare_expr (def);
@@ -2775,10 +2813,14 @@ scev_const_prop (void)
 
          ass = build2 (MODIFY_EXPR, void_type_node, rslt, NULL_TREE);
          SSA_NAME_DEF_STMT (rslt) = ass;
-         bsi_insert_after (&bsi, ass, BSI_NEW_STMT);
-         def = force_gimple_operand_bsi (&bsi, def, false, NULL_TREE);
+         {
+           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;
          update_stmt (ass);
        }
     }
+  return 0;
 }