OSDN Git Service

* tree-vrp.c (extract_range_from_unary_expr): Derive ranges for
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 21 Mar 2006 21:01:42 +0000 (21:01 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 21 Mar 2006 21:01:42 +0000 (21:01 +0000)
type conversions of a VR_VARYING source to a wider type.

* gcc.dg/tree-ssa/vrp28.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@112256 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/vrp28.c [new file with mode: 0644]
gcc/tree-vrp.c

index 176ce65..0a8feca 100644 (file)
@@ -1,3 +1,8 @@
+2006-03-21  Jeff Law  <law@redhat.com>
+
+       * tree-vrp.c (extract_range_from_unary_expr): Derive ranges for
+       type conversions of a VR_VARYING source to a wider type.
+
 2006-03-21  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * config.gcc (i[34567]86-*-solaris2*): Add config/sol2-10.h to
        * tree-ssa-structalias.c (intra_create_variable_infos): Fortran
        alias semantics is specified by flag_argument_noalias > 2.
 
-2006-03-20  Jeff Law  <law@redhat.com>
 
        * tree-pass.h (pass_phi_only_copy_prop): Delete.
        (pass_phi_only_cprop): Declare.
index 372ab8c..4726020 100644 (file)
@@ -1,3 +1,7 @@
+2006-03-21  Jeff Law  <law@redhat.com>
+
+       * gcc.dg/tree-ssa/vrp28.c: New test.
+
 2006-03-21  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * gcc.dg/builtins-config.h (Solaris case): Define HAVE_C99_RUNTIME
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp28.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp28.c
new file mode 100644 (file)
index 0000000..6b2a1fd
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+int f(_Bool a)
+{
+  int t = a;
+  if (t != 2)
+   return 0;
+  return 1;
+}
+
+int f1(unsigned char a)
+{
+  int t = a;
+  if (t != 256)
+   return 0;
+  return 1;
+}
+
+int f3 (unsigned char c)
+{
+  int i = c;
+  if (i < 0 || i > 255)
+    return -1;
+  else
+    return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "if " 0 "vrp1" } } * /
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
+
+
index 278347d..d3d57ed 100644 (file)
@@ -1641,14 +1641,12 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
       return;
     }
 
-  /* Refuse to operate on varying and symbolic ranges.  Also, if the
-     operand is neither a pointer nor an integral type, set the
-     resulting range to VARYING.  TODO, in some cases we may be able
-     to derive anti-ranges (like nonzero values).  */
-  if (vr0.type == VR_VARYING
-      || (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
-         && !POINTER_TYPE_P (TREE_TYPE (op0)))
-      || symbolic_range_p (&vr0))
+  /* Refuse to operate on symbolic ranges, or if neither operand is
+     a pointer or integral type.  */
+  if ((!INTEGRAL_TYPE_P (TREE_TYPE (op0))
+       && !POINTER_TYPE_P (TREE_TYPE (op0)))
+      || (vr0.type != VR_VARYING
+         && symbolic_range_p (&vr0)))
     {
       set_value_range_to_varying (vr);
       return;
@@ -1681,20 +1679,36 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
         or equal to the new max, then we can safely use the newly
         computed range for EXPR.  This allows us to compute
         accurate ranges through many casts.  */
-      if (vr0.type == VR_RANGE)
+      if (vr0.type == VR_RANGE
+         || (vr0.type == VR_VARYING
+             && TYPE_PRECISION (outer_type) > TYPE_PRECISION (inner_type)))
        {
-         tree new_min, new_max;
+         tree new_min, new_max, orig_min, orig_max;
 
-         /* Convert VR0's min/max to OUTER_TYPE.  */
-         new_min = fold_convert (outer_type, vr0.min);
-         new_max = fold_convert (outer_type, vr0.max);
+         /* Convert the input operand min/max to OUTER_TYPE.   If
+            the input has no range information, then use the min/max
+            for the input's type.  */
+         if (vr0.type == VR_RANGE)
+           {
+             orig_min = vr0.min;
+             orig_max = vr0.max;
+           }
+         else
+           {
+             orig_min = TYPE_MIN_VALUE (inner_type);
+             orig_max = TYPE_MAX_VALUE (inner_type);
+           }
+
+         new_min = fold_convert (outer_type, orig_min);
+         new_max = fold_convert (outer_type, orig_max);
 
          /* Verify the new min/max values are gimple values and
-            that they compare equal to VR0's min/max values.  */
+            that they compare equal to the orignal input's
+            min/max values.  */
          if (is_gimple_val (new_min)
              && is_gimple_val (new_max)
-             && tree_int_cst_equal (new_min, vr0.min)
-             && tree_int_cst_equal (new_max, vr0.max)
+             && tree_int_cst_equal (new_min, orig_min)
+             && tree_int_cst_equal (new_max, orig_max)
              && compare_values (new_min, new_max) <= 0
              && compare_values (new_min, new_max) >= -1)
            {
@@ -1717,6 +1731,16 @@ extract_range_from_unary_expr (value_range_t *vr, tree expr)
        }
     }
 
+  /* Conversion of a VR_VARYING value to a wider type can result
+     in a usable range.  So wait until after we've handled conversions
+     before dropping the result to VR_VARYING if we had a source
+     operand that is VR_VARYING.  */
+  if (vr0.type == VR_VARYING)
+    {
+      set_value_range_to_varying (vr);
+      return;
+    }
+
   /* Apply the operation to each end of the range and see what we end
      up with.  */
   if (code == NEGATE_EXPR