re PR tree-optimization/18529 (When the lower bound of a loop is non-constant we...
authorZdenek Dvorak <dvorakz@suse.cz>
Mon, 22 Nov 2004 21:33:47 +0000 (22:33 +0100)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Mon, 22 Nov 2004 21:33:47 +0000 (21:33 +0000)
PR tree-optimization/18529
* fold-const.c (fold_to_nonsharp_ineq_using_bound): New function.
(simple_operand_p): Use STRIP_NOPS.  Consider SSA names simple.
(fold): Call fold_to_nonsharp_ineq_using_bound.
* tree-ssa-loop-niter.c (simplify_replace_tree): New function.
(number_of_iterations_cond): Fold the expressions before futher
processing.
(tree_simplify_using_condition): Handle case when cond or expr is
an EQ_EXPR specially.

From-SVN: r91031

gcc/ChangeLog
gcc/fold-const.c
gcc/tree-ssa-loop-niter.c

index d94b75d394467a81a8a4a435a81dbf5112e9836f..2c974a0d81d4a0a6f6082ea8ad726f7daf40d132 100644 (file)
@@ -1,3 +1,15 @@
+2004-11-22  Zdenek Dvorak  <dvorakz@suse.cz>
+
+       PR tree-optimization/18529
+       * fold-const.c (fold_to_nonsharp_ineq_using_bound): New function.
+       (simple_operand_p): Use STRIP_NOPS.  Consider SSA names simple.
+       (fold): Call fold_to_nonsharp_ineq_using_bound.
+       * tree-ssa-loop-niter.c (simplify_replace_tree): New function.
+       (number_of_iterations_cond): Fold the expressions before futher
+       processing.
+       (tree_simplify_using_condition): Handle case when cond or expr is
+       an EQ_EXPR specially.
+
 2004-11-22 Daniel Berlin  <dberlin@dberlin.org>
 
         * tree-ssa.c (verify_ssa): SSA_OP_ALL_USES should be
index 0c1a3d587c577396628d0acc3b6df2b4374e60fd..611ac145093a1702109c37f609e2b5d852a2eb87 100644 (file)
@@ -3424,13 +3424,10 @@ static int
 simple_operand_p (tree exp)
 {
   /* Strip any conversions that don't change the machine mode.  */
-  while ((TREE_CODE (exp) == NOP_EXPR
-         || TREE_CODE (exp) == CONVERT_EXPR)
-        && (TYPE_MODE (TREE_TYPE (exp))
-            == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
-    exp = TREE_OPERAND (exp, 0);
+  STRIP_NOPS (exp);
 
   return (CONSTANT_CLASS_P (exp)
+         || TREE_CODE (exp) == SSA_NAME
          || (DECL_P (exp)
              && ! TREE_ADDRESSABLE (exp)
              && ! TREE_THIS_VOLATILE (exp)
@@ -6180,6 +6177,51 @@ try_move_mult_to_index (tree type, enum tree_code code, tree addr, tree mult)
   return build1 (ADDR_EXPR, type, ret);
 }
 
+
+/* Fold A < X && A + 1 > Y to A < X && A >= Y.  Normally A + 1 > Y
+   means A >= Y && A != MAX, but in this case we know that
+   A < X <= MAX.  INEQ is A + 1 > Y, BOUND is A < X.  */
+
+static tree
+fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
+{
+  tree a, typea, type = TREE_TYPE (ineq), a1, diff, y;
+
+  if (TREE_CODE (bound) == LT_EXPR)
+    a = TREE_OPERAND (bound, 0);
+  else if (TREE_CODE (bound) == GT_EXPR)
+    a = TREE_OPERAND (bound, 1);
+  else
+    return NULL_TREE;
+
+  typea = TREE_TYPE (a);
+  if (!INTEGRAL_TYPE_P (typea)
+      && !POINTER_TYPE_P (typea))
+    return NULL_TREE;
+
+  if (TREE_CODE (ineq) == LT_EXPR)
+    {
+      a1 = TREE_OPERAND (ineq, 1);
+      y = TREE_OPERAND (ineq, 0);
+    }
+  else if (TREE_CODE (ineq) == GT_EXPR)
+    {
+      a1 = TREE_OPERAND (ineq, 0);
+      y = TREE_OPERAND (ineq, 1);
+    }
+  else
+    return NULL_TREE;
+
+  if (TREE_TYPE (a1) != typea)
+    return NULL_TREE;
+
+  diff = fold (build2 (MINUS_EXPR, typea, a1, a));
+  if (!integer_onep (diff))
+    return NULL_TREE;
+
+  return fold (build2 (GE_EXPR, type, a, y));
+}
+
 /* Perform constant folding and related simplification of EXPR.
    The related simplifications include x*1 => x, x*0 => 0, etc.,
    and application of the associative law.
@@ -8023,6 +8065,22 @@ fold (tree expr)
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        return omit_one_operand (type, integer_zero_node, arg0);
 
+      /* A < X && A + 1 > Y ==> A < X && A >= Y.  Normally A + 1 > Y
+        means A >= Y && A != MAX, but in this case we know that
+        A < X <= MAX.  */
+
+      if (!TREE_SIDE_EFFECTS (arg0)
+         && !TREE_SIDE_EFFECTS (arg1))
+       {
+         tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1);
+         if (tem)
+           return fold (build2 (code, type, tem, arg1));
+
+         tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0);
+         if (tem)
+           return fold (build2 (code, type, arg0, tem));
+       }
+
     truth_andor:
       /* We only do these simplifications if we are optimizing.  */
       if (!optimize)
index 3d4d4c0dec4544f5f702bfc3bb334ab6867d74cc..c83113430bcd055585df32bd6ba5943f026e14c8 100644 (file)
@@ -372,12 +372,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));
            }
 
@@ -555,6 +555,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 +638,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,