OSDN Git Service

* config/mcore/mcore.h (target_flags, HARDLIT_BIT, ALIGN8_BIT, DIV_BIT)
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop-niter.c
index 6352ba0..abeb500 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions to determine/estimate number of iterations of a loop.
-   Copyright (C) 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
    
 This file is part of GCC.
    
@@ -43,9 +43,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #define SWAP(X, Y) do { void *tmp = (X); (X) = (Y); (Y) = tmp; } while (0)
 
-/* Just to shorten the ugly names.  */
-#define EXEC_BINARY nondestructive_fold_binary_to_constant
-#define EXEC_UNARY nondestructive_fold_unary_to_constant
 
 /*
 
@@ -83,44 +80,6 @@ nonzero_p (tree arg)
   return (TREE_INT_CST_LOW (arg) != 0 || TREE_INT_CST_HIGH (arg) != 0);
 }
 
-/* Returns number of zeros at the end of binary representation of X.
-   
-   ??? Use ffs if available?  */
-
-static tree
-num_ending_zeros (tree x)
-{
-  unsigned HOST_WIDE_INT fr, nfr;
-  unsigned num, abits;
-  tree type = TREE_TYPE (x);
-
-  if (TREE_INT_CST_LOW (x) == 0)
-    {
-      num = HOST_BITS_PER_WIDE_INT;
-      fr = TREE_INT_CST_HIGH (x);
-    }
-  else
-    {
-      num = 0;
-      fr = TREE_INT_CST_LOW (x);
-    }
-
-  for (abits = HOST_BITS_PER_WIDE_INT / 2; abits; abits /= 2)
-    {
-      nfr = fr >> abits;
-      if (nfr << abits == fr)
-       {
-         num += abits;
-         fr = nfr;
-       }
-    }
-
-  if (num > TYPE_PRECISION (type))
-    num = TYPE_PRECISION (type);
-
-  return build_int_cst_type (type, num);
-}
-
 /* Returns inverse of X modulo 2^s, where MASK = 2^s-1.  */
 
 static tree
@@ -156,10 +115,10 @@ inverse (tree x, tree mask)
       rslt = build_int_cst_type (type, 1);
       for (; ctr; ctr--)
        {
-         rslt = EXEC_BINARY (MULT_EXPR, type, rslt, x);
-         x = EXEC_BINARY (MULT_EXPR, type, x, x);
+         rslt = fold_binary_to_constant (MULT_EXPR, type, rslt, x);
+         x = fold_binary_to_constant (MULT_EXPR, type, x, x);
        }
-      rslt = EXEC_BINARY (BIT_AND_EXPR, type, rslt, mask);
+      rslt = fold_binary_to_constant (BIT_AND_EXPR, type, rslt, mask);
     }
 
   return rslt;
@@ -217,7 +176,7 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
       if (code != NE_EXPR)
        return;
 
-      step0 = EXEC_BINARY (MINUS_EXPR, type, step0, step1);
+      step0 = fold_binary_to_constant (MINUS_EXPR, type, step0, step1);
       step1 = NULL_TREE;
     }
 
@@ -311,7 +270,7 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
   if (code != NE_EXPR)
     {
       if (zero_p (step0))
-       step = EXEC_UNARY (NEGATE_EXPR, type, step1);
+       step = fold_unary_to_constant (NEGATE_EXPR, type, step1);
       else
        step = step0;
       delta = build2 (MINUS_EXPR, type, base1, base0);
@@ -320,8 +279,8 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
 
       if (TREE_CODE (delta) == INTEGER_CST)
        {
-         tmp = EXEC_BINARY (MINUS_EXPR, type, step,
-                            build_int_cst_type (type, 1));
+         tmp = fold_binary_to_constant (MINUS_EXPR, type, step,
+                                        build_int_cst_type (type, 1));
          if (was_sharp
              && operand_equal_p (delta, tmp, 0))
            {
@@ -342,8 +301,10 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
                may_xform = boolean_true_node;
              else
                {
-                 bound = EXEC_BINARY (PLUS_EXPR, type, mmin, step);
-                 bound = EXEC_BINARY (MINUS_EXPR, type, bound, delta);
+                 bound = fold_binary_to_constant (PLUS_EXPR, type,
+                                                  mmin, step);
+                 bound = fold_binary_to_constant (MINUS_EXPR, type,
+                                                  bound, delta);
                  may_xform = fold (build2 (LE_EXPR, boolean_type_node,
                                           bound, base0));
                }
@@ -354,8 +315,10 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
                may_xform = boolean_true_node;
              else
                {
-                 bound = EXEC_BINARY (MINUS_EXPR, type, mmax, step);
-                 bound = EXEC_BINARY (PLUS_EXPR, type, bound, delta);
+                 bound = fold_binary_to_constant (MINUS_EXPR, type,
+                                                  mmax, step);
+                 bound = fold_binary_to_constant (PLUS_EXPR, type,
+                                                  bound, delta);
                  may_xform = fold (build2 (LE_EXPR, boolean_type_node,
                                           base1, bound));
                }
@@ -372,12 +335,12 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
 
          if (zero_p (step0))
            {
-             base0 = build2 (PLUS_EXPR, type, base0, delta);
+             base0 = fold (build2 (PLUS_EXPR, type, base0, delta));
              base0 = fold (build2 (MINUS_EXPR, type, base0, step));
            }
          else
            {
-             base1 = build2 (MINUS_EXPR, type, base1, delta);
+             base1 = fold (build2 (MINUS_EXPR, type, base1, delta));
              base1 = fold (build2 (PLUS_EXPR, type, base1, step));
            }
 
@@ -401,11 +364,11 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
       base1 = fold (build2 (MINUS_EXPR, type, base1, base0));
       base0 = NULL_TREE;
       if (!zero_p (step1))
-       step0 = EXEC_UNARY (NEGATE_EXPR, type, step1);
+       step0 = fold_unary_to_constant (NEGATE_EXPR, type, step1);
       step1 = NULL_TREE;
       if (!tree_expr_nonnegative_p (fold_convert (signed_niter_type, step0)))
        {
-         step0 = EXEC_UNARY (NEGATE_EXPR, type, step0);
+         step0 = fold_unary_to_constant (NEGATE_EXPR, type, step0);
          base1 = fold (build1 (NEGATE_EXPR, type, base1));
        }
 
@@ -416,9 +379,9 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
         is infinite.  Otherwise, the number of iterations is
         (inverse(s/d) * (c/d)) mod (size of mode/d).  */
       bits = num_ending_zeros (step0);
-      d = EXEC_BINARY (LSHIFT_EXPR, niter_type,
-                      build_int_cst_type (niter_type, 1), bits);
-      s = EXEC_BINARY (RSHIFT_EXPR, niter_type, step0, bits);
+      d = fold_binary_to_constant (LSHIFT_EXPR, niter_type,
+                                  build_int_cst_type (niter_type, 1), bits);
+      s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, step0, bits);
 
       bound = build_low_bits_mask (niter_type,
                                   (TYPE_PRECISION (niter_type)
@@ -447,7 +410,7 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
        {
          if (mmax)
            {
-             bound = EXEC_BINARY (MINUS_EXPR, type, mmax, step0);
+             bound = fold_binary_to_constant (MINUS_EXPR, type, mmax, step0);
              assumption = fold (build2 (LE_EXPR, boolean_type_node,
                                         base1, bound));
              assumptions = fold (build2 (TRUTH_AND_EXPR, boolean_type_node,
@@ -468,7 +431,7 @@ number_of_iterations_cond (tree type, tree base0, tree step0,
             we can again compute number of iterations as (b - (a - s)) / s.  */
          if (mmin)
            {
-             bound = EXEC_BINARY (MINUS_EXPR, type, mmin, step1);
+             bound = fold_binary_to_constant (MINUS_EXPR, type, mmin, step1);
              assumption = fold (build2 (LE_EXPR, boolean_type_node,
                                        bound, base0));
              assumptions = fold (build2 (TRUTH_AND_EXPR, boolean_type_node,
@@ -555,6 +518,41 @@ simplify_using_outer_evolutions (struct loop *loop, tree expr)
   return expr;
 }
 
+/* Substitute NEW for OLD in EXPR and fold the result.  */
+
+static tree
+simplify_replace_tree (tree expr, tree old, tree new)
+{
+  unsigned i, n;
+  tree ret = NULL_TREE, e, se;
+
+  if (!expr)
+    return NULL_TREE;
+
+  if (expr == old
+      || operand_equal_p (expr, old, 0))
+    return unshare_expr (new);
+
+  if (!EXPR_P (expr))
+    return expr;
+
+  n = TREE_CODE_LENGTH (TREE_CODE (expr));
+  for (i = 0; i < n; i++)
+    {
+      e = TREE_OPERAND (expr, i);
+      se = simplify_replace_tree (e, old, new);
+      if (e == se)
+       continue;
+
+      if (!ret)
+       ret = copy_node (expr);
+
+      TREE_OPERAND (ret, i) = se;
+    }
+
+  return (ret ? fold (ret) : expr);
+}
+
 /* Tries to simplify EXPR using the condition COND.  Returns the simplified
    expression (or EXPR unchanged, if no simplification was possible).*/
 
@@ -603,6 +601,51 @@ tree_simplify_using_condition (tree cond, tree expr)
       return expr;
     }
 
+  /* In case COND is equality, we may be able to simplify EXPR by copy/constant
+     propagation, and vice versa.  Fold does not handle this, since it is
+     considered too expensive.  */
+  if (TREE_CODE (cond) == EQ_EXPR)
+    {
+      e0 = TREE_OPERAND (cond, 0);
+      e1 = TREE_OPERAND (cond, 1);
+
+      /* We know that e0 == e1.  Check whether we cannot simplify expr
+        using this fact.  */
+      e = simplify_replace_tree (expr, e0, e1);
+      if (zero_p (e) || nonzero_p (e))
+       return e;
+
+      e = simplify_replace_tree (expr, e1, e0);
+      if (zero_p (e) || nonzero_p (e))
+       return e;
+    }
+  if (TREE_CODE (expr) == EQ_EXPR)
+    {
+      e0 = TREE_OPERAND (expr, 0);
+      e1 = TREE_OPERAND (expr, 1);
+
+      /* If e0 == e1 (EXPR) implies !COND, then EXPR cannot be true.  */
+      e = simplify_replace_tree (cond, e0, e1);
+      if (zero_p (e))
+       return e;
+      e = simplify_replace_tree (cond, e1, e0);
+      if (zero_p (e))
+       return e;
+    }
+  if (TREE_CODE (expr) == NE_EXPR)
+    {
+      e0 = TREE_OPERAND (expr, 0);
+      e1 = TREE_OPERAND (expr, 1);
+
+      /* If e0 == e1 (!EXPR) implies !COND, then EXPR must be true.  */
+      e = simplify_replace_tree (cond, e0, e1);
+      if (zero_p (e))
+       return boolean_true_node;
+      e = simplify_replace_tree (cond, e1, e0);
+      if (zero_p (e))
+       return boolean_true_node;
+    }
+
   /* Check whether COND ==> EXPR.  */
   notcond = invert_truthvalue (cond);
   e = fold (build2 (TRUTH_OR_EXPR, boolean_type_node,
@@ -639,9 +682,9 @@ simplify_using_initial_conditions (struct loop *loop, tree expr,
        bb != ENTRY_BLOCK_PTR;
        bb = get_immediate_dominator (CDI_DOMINATORS, bb))
     {
-      e = EDGE_PRED (bb, 0);
-      if (EDGE_COUNT (bb->preds) > 1)
+      if (!single_pred_p (bb))
        continue;
+      e = single_pred_edge (bb);
 
       if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)))
        continue;
@@ -742,6 +785,75 @@ number_of_iterations_exit (struct loop *loop, edge exit,
   return integer_onep (niter->assumptions);
 }
 
+/* Try to determine the number of iterations of LOOP.  If we succeed,
+   expression giving number of iterations is returned and *EXIT is
+   set to the edge from that the information is obtained.  Otherwise
+   chrec_dont_know is returned.  */
+
+tree
+find_loop_niter (struct loop *loop, edge *exit)
+{
+  unsigned n_exits, i;
+  edge *exits = get_loop_exit_edges (loop, &n_exits);
+  edge ex;
+  tree niter = NULL_TREE, aniter;
+  struct tree_niter_desc desc;
+
+  *exit = NULL;
+  for (i = 0; i < n_exits; i++)
+    {
+      ex = exits[i];
+      if (!just_once_each_iteration_p (loop, ex->src))
+       continue;
+
+      if (!number_of_iterations_exit (loop, ex, &desc))
+       continue;
+
+      if (nonzero_p (desc.may_be_zero))
+       {
+         /* We exit in the first iteration through this exit.
+            We won't find anything better.  */
+         niter = build_int_cst_type (unsigned_type_node, 0);
+         *exit = ex;
+         break;
+       }
+
+      if (!zero_p (desc.may_be_zero))
+       continue;
+
+      aniter = desc.niter;
+
+      if (!niter)
+       {
+         /* Nothing recorded yet.  */
+         niter = aniter;
+         *exit = ex;
+         continue;
+       }
+
+      /* Prefer constants, the lower the better.  */
+      if (TREE_CODE (aniter) != INTEGER_CST)
+       continue;
+
+      if (TREE_CODE (niter) != INTEGER_CST)
+       {
+         niter = aniter;
+         *exit = ex;
+         continue;
+       }
+
+      if (tree_int_cst_lt (aniter, niter))
+       {
+         niter = aniter;
+         *exit = ex;
+         continue;
+       }
+    }
+  free (exits);
+
+  return niter ? niter : chrec_dont_know;
+}
+
 /*
 
    Analysis of a number of iterations of a loop by a brute-force evaluation.
@@ -974,13 +1086,11 @@ find_loop_niter_by_eval (struct loop *loop, edge *exit)
        continue;
 
       aniter = loop_niter_by_eval (loop, ex);
-      if (chrec_contains_undetermined (aniter)
-         || TREE_CODE (aniter) != INTEGER_CST)
+      if (chrec_contains_undetermined (aniter))
        continue;
 
       if (niter
-         && !nonzero_p (fold (build2 (LT_EXPR, boolean_type_node,
-                                            aniter, niter))))
+         && !tree_int_cst_lt (aniter, niter))
        continue;
 
       niter = aniter;
@@ -1103,78 +1213,6 @@ compare_trees (tree a, tree b)
   return 2;
 }
 
-/* Returns the largest value obtainable by casting something in INNER type to
-   OUTER type.  */
-
-static tree
-upper_bound_in_type (tree outer, tree inner)
-{
-  unsigned HOST_WIDE_INT lo, hi;
-  unsigned bits = TYPE_PRECISION (inner);
-
-  if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
-    {
-      /* Zero extending in these cases.  */
-      if (bits <= HOST_BITS_PER_WIDE_INT)
-       {
-         hi = 0;
-         lo = (~(unsigned HOST_WIDE_INT) 0)
-                 >> (HOST_BITS_PER_WIDE_INT - bits);
-       }
-      else
-       {
-         hi = (~(unsigned HOST_WIDE_INT) 0)
-                 >> (2 * HOST_BITS_PER_WIDE_INT - bits);
-         lo = ~(unsigned HOST_WIDE_INT) 0;
-       }
-    }
-  else
-    {
-      /* Sign extending in these cases.  */
-      if (bits <= HOST_BITS_PER_WIDE_INT)
-       {
-         hi = 0;
-         lo = (~(unsigned HOST_WIDE_INT) 0)
-                 >> (HOST_BITS_PER_WIDE_INT - bits) >> 1;
-       }
-      else
-       {
-         hi = (~(unsigned HOST_WIDE_INT) 0)
-                 >> (2 * HOST_BITS_PER_WIDE_INT - bits) >> 1;
-         lo = ~(unsigned HOST_WIDE_INT) 0;
-       }
-    }
-
-  return fold_convert (outer,
-                      build_int_cst_wide (inner, lo, hi));
-}
-
-/* Returns the smallest value obtainable by casting something in INNER type to
-   OUTER type.  */
-
-static tree
-lower_bound_in_type (tree outer, tree inner)
-{
-  unsigned HOST_WIDE_INT lo, hi;
-  unsigned bits = TYPE_PRECISION (inner);
-
-  if (TYPE_UNSIGNED (outer) || TYPE_UNSIGNED (inner))
-    lo = hi = 0;
-  else if (bits <= HOST_BITS_PER_WIDE_INT)
-    {
-      hi = ~(unsigned HOST_WIDE_INT) 0;
-      lo = (~(unsigned HOST_WIDE_INT) 0) << (bits - 1);
-    }
-  else
-    {
-      hi = (~(unsigned HOST_WIDE_INT) 0) << (bits - HOST_BITS_PER_WIDE_INT - 1);
-      lo = 0;
-    }
-
-  return fold_convert (outer,
-                      build_int_cst_wide (inner, lo, hi));
-}
-
 /* Returns true if statement S1 dominates statement S2.  */
 
 static bool