OSDN Git Service

2006-01-19 Paolo Bonzini <bonzini@gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vrp.c
index b950386..a5028b4 100644 (file)
@@ -1,5 +1,5 @@
 /* Support routines for Value Range Propagation (VRP).
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>.
 
 This file is part of GCC.
@@ -1230,6 +1230,8 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
      the operands is VR_VARYING or symbolic range.  TODO, we may be
      able to derive anti-ranges in some cases.  */
   if (code != BIT_AND_EXPR
+      && code != TRUTH_AND_EXPR
+      && code != TRUTH_OR_EXPR
       && (vr0.type == VR_VARYING
          || vr1.type == VR_VARYING
          || vr0.type != vr1.type
@@ -1277,9 +1279,47 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
       || code == TRUTH_OR_EXPR
       || code == TRUTH_XOR_EXPR)
     {
-      /* Boolean expressions cannot be folded with int_const_binop.  */
-      min = fold_binary (code, TREE_TYPE (expr), vr0.min, vr1.min);
-      max = fold_binary (code, TREE_TYPE (expr), vr0.max, vr1.max);
+      /* If one of the operands is zero, we know that the whole
+        expression evaluates zero.  */
+      if (code == TRUTH_AND_EXPR
+         && ((vr0.type == VR_RANGE
+              && integer_zerop (vr0.min)
+              && integer_zerop (vr0.max))
+             || (vr1.type == VR_RANGE
+                 && integer_zerop (vr1.min)
+                 && integer_zerop (vr1.max))))
+       {
+         type = VR_RANGE;
+         min = max = build_int_cst (TREE_TYPE (expr), 0);
+       }
+      /* If one of the operands is one, we know that the whole
+        expression evaluates one.  */
+      else if (code == TRUTH_OR_EXPR
+              && ((vr0.type == VR_RANGE
+                   && integer_onep (vr0.min)
+                   && integer_onep (vr0.max))
+                  || (vr1.type == VR_RANGE
+                      && integer_onep (vr1.min)
+                      && integer_onep (vr1.max))))
+       {
+         type = VR_RANGE;
+         min = max = build_int_cst (TREE_TYPE (expr), 1);
+       }
+      else if (vr0.type != VR_VARYING
+              && vr1.type != VR_VARYING
+              && vr0.type == vr1.type
+              && !symbolic_range_p (&vr0)
+              && !symbolic_range_p (&vr1))
+       {
+         /* Boolean expressions cannot be folded with int_const_binop.  */
+         min = fold_binary (code, TREE_TYPE (expr), vr0.min, vr1.min);
+         max = fold_binary (code, TREE_TYPE (expr), vr0.max, vr1.max);
+       }
+      else
+       {
+         set_value_range_to_varying (vr);
+         return;
+       }
     }
   else if (code == PLUS_EXPR
           || code == MIN_EXPR
@@ -1372,12 +1412,13 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
       max = val[0];
       for (i = 1; i < 4; i++)
        {
-         if (TREE_OVERFLOW (min) || TREE_OVERFLOW (max))
+         if (!is_gimple_min_invariant (min) || TREE_OVERFLOW (min)
+             || !is_gimple_min_invariant (max) || TREE_OVERFLOW (max))
            break;
 
          if (val[i])
            {
-             if (TREE_OVERFLOW (val[i]))
+             if (!is_gimple_min_invariant (val[i]) || TREE_OVERFLOW (val[i]))
                {
                  /* If we found an overflowed value, set MIN and MAX
                     to it so that we set the resulting range to
@@ -1421,7 +1462,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
          && tree_expr_nonnegative_p (vr0.max)
          && TREE_CODE (vr0.max) == INTEGER_CST)
        {
-         min = fold_convert (TREE_TYPE (expr), integer_zero_node);
+         min = build_int_cst (TREE_TYPE (expr), 0);
          max = vr0.max;
        }
       else if (vr1.type == VR_RANGE
@@ -1430,7 +1471,7 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
          && TREE_CODE (vr1.max) == INTEGER_CST)
        {
          type = VR_RANGE;
-         min = fold_convert (TREE_TYPE (expr), integer_zero_node);
+         min = build_int_cst (TREE_TYPE (expr), 0);
          max = vr1.max;
        }
       else
@@ -1444,7 +1485,8 @@ extract_range_from_binary_expr (value_range_t *vr, tree expr)
 
   /* If either MIN or MAX overflowed, then set the resulting range to
      VARYING.  */
-  if (TREE_OVERFLOW (min) || TREE_OVERFLOW (max))
+  if (!is_gimple_min_invariant (min) || TREE_OVERFLOW (min)
+      || !is_gimple_min_invariant (max) || TREE_OVERFLOW (max))
     {
       set_value_range_to_varying (vr);
       return;
@@ -3026,7 +3068,7 @@ remove_range_assertions (void)
              }
 
            /* And finally, remove the copy, it is not needed.  */
-           bsi_remove (&si);
+           bsi_remove (&si, true);
          }
        else
          bsi_next (&si);
@@ -3928,7 +3970,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
       if (cond_code == GT_EXPR)
        {
          tree one = build_int_cst (TREE_TYPE (op0), 1);
-         max = fold_build2 (PLUS_EXPR, TREE_TYPE (op0), max, one);
+         min = fold_build2 (PLUS_EXPR, TREE_TYPE (op0), min, one);
        }
     }
 
@@ -3945,10 +3987,10 @@ test_for_singularity (enum tree_code cond_code, tree op0,
       else
        max = vr->max;
 
-      /* If the new min/max values have converged to a
-        single value, then there is only one value which
-        can satisfy the condition, return that value.  */
-      if (min == max && is_gimple_min_invariant (min))
+      /* If the new min/max values have converged to a single value,
+        then there is only one value which can satisfy the condition,
+        return that value.  */
+      if (operand_equal_p (min, max, 0) && is_gimple_min_invariant (min))
        return min;
     }
   return NULL;