aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2006-03-21 14:01:42 -0700
committerJeff Law <law@gcc.gnu.org>2006-03-21 14:01:42 -0700
commita3b196e342086293aabbd6f32df9ed95295c83f5 (patch)
tree8da33b4204779d57062fb867c60614ce5f2ad2a4
parentec23ed606daa42ee11510be00add6f2a6350d565 (diff)
downloadgcc-a3b196e342086293aabbd6f32df9ed95295c83f5.zip
gcc-a3b196e342086293aabbd6f32df9ed95295c83f5.tar.gz
gcc-a3b196e342086293aabbd6f32df9ed95295c83f5.tar.bz2
tree-vrp.c (extract_range_from_unary_expr): Derive ranges for type conversions of a VR_VARYING source to a wider type.
* tree-vrp.c (extract_range_from_unary_expr): Derive ranges for type conversions of a VR_VARYING source to a wider type. * gcc.dg/tree-ssa/vrp28.c: New test. From-SVN: r112256
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp28.c32
-rw-r--r--gcc/tree-vrp.c56
4 files changed, 81 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 176ce656..0a8feca 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
@@ -106,7 +111,6 @@
* 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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 372ab8c..4726020 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..6b2a1fd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp28.c
@@ -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" } } */
+
+
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 278347d..d3d57ed 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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