diff options
author | Jeff Law <law@redhat.com> | 2006-03-21 14:01:42 -0700 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2006-03-21 14:01:42 -0700 |
commit | a3b196e342086293aabbd6f32df9ed95295c83f5 (patch) | |
tree | 8da33b4204779d57062fb867c60614ce5f2ad2a4 | |
parent | ec23ed606daa42ee11510be00add6f2a6350d565 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/vrp28.c | 32 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 56 |
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 |