diff options
author | Richard Guenther <rguenther@suse.de> | 2011-10-17 12:22:54 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2011-10-17 12:22:54 +0000 |
commit | 7d5a0f1b4e54f83337d5a0b093b0a40ae8cf27d6 (patch) | |
tree | c4d0d2f384a38c365c5371e2b67503ad50a6fb57 /gcc | |
parent | b9bd6f743843a53de1396c43d1e308e51d40c5c4 (diff) | |
download | gcc-7d5a0f1b4e54f83337d5a0b093b0a40ae8cf27d6.zip gcc-7d5a0f1b4e54f83337d5a0b093b0a40ae8cf27d6.tar.gz gcc-7d5a0f1b4e54f83337d5a0b093b0a40ae8cf27d6.tar.bz2 |
re PR tree-optimization/50729 (Silent code gen fault: Value range propagation seems to propagate values across narrowing/widening)
2011-10-17 Richard Guenther <rguenther@suse.de>
PR tree-optimization/50729
* tree-vrp.c (extract_range_from_unary_expr_1): Remove
redundant test.
(simplify_conversion_using_ranges): Properly test the
intermediate result.
* gcc.dg/torture/pr50729.c: New testcase.
From-SVN: r180087
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr50729.c | 20 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 26 |
4 files changed, 47 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 557916c..f367a11 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2011-10-17 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/50729 + * tree-vrp.c (extract_range_from_unary_expr_1): Remove + redundant test. + (simplify_conversion_using_ranges): Properly test the + intermediate result. + 2011-10-15 Tom Tromey <tromey@redhat.com> Dodji Seketeli <dodji@redhat.com> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1215af6..4dc4e78 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-10-17 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/50729 + * gcc.dg/torture/pr50729.c: New testcase. + 2011-10-15 Tom Tromey <tromey@redhat.com> Dodji Seketeli <dodji@redhat.com> diff --git a/gcc/testsuite/gcc.dg/torture/pr50729.c b/gcc/testsuite/gcc.dg/torture/pr50729.c new file mode 100644 index 0000000..a1daa7b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr50729.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int32plus } */ + +extern void abort (void); +unsigned short __attribute__((noinline)) +foo (int i) +{ + if (i >= 0 + && i <= 0x400000) + return (unsigned short)(signed char)i; + return i; +} +int main() +{ + int i; + for (i = 0; i < 0xffff; ++i) + if (foo(i) != (unsigned short)(signed char) i) + abort (); + return 0; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 604e7f0..248bc61 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2913,15 +2913,10 @@ extract_range_from_unary_expr_1 (value_range_t *vr, determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]). */ if (POINTER_TYPE_P (type)) { - if (CONVERT_EXPR_CODE_P (code)) - { - if (range_is_nonnull (&vr0)) - set_value_range_to_nonnull (vr, type); - else if (range_is_null (&vr0)) - set_value_range_to_null (vr, type); - else - set_value_range_to_varying (vr); - } + if (range_is_nonnull (&vr0)) + set_value_range_to_nonnull (vr, type); + else if (range_is_null (&vr0)) + set_value_range_to_null (vr, type); else set_value_range_to_varying (vr); return; @@ -7288,10 +7283,17 @@ simplify_conversion_using_ranges (gimple stmt) TYPE_UNSIGNED (TREE_TYPE (middleop))); middlemax = double_int_ext (innermax, TYPE_PRECISION (TREE_TYPE (middleop)), TYPE_UNSIGNED (TREE_TYPE (middleop))); - /* If the middle values do not represent a proper range fail. */ - if (double_int_cmp (middlemin, middlemax, - TYPE_UNSIGNED (TREE_TYPE (middleop))) > 0) + /* If the middle values are not equal to the original values fail. + But only if the inner cast truncates (thus we ignore differences + in extension to handle the case going from a range to an anti-range + and back). */ + if ((TYPE_PRECISION (TREE_TYPE (innerop)) + > TYPE_PRECISION (TREE_TYPE (middleop))) + && (!double_int_equal_p (innermin, middlemin) + || !double_int_equal_p (innermax, middlemax))) return false; + /* Require that the final conversion applied to both the original + and the intermediate range produces the same result. */ if (!double_int_equal_p (double_int_ext (middlemin, TYPE_PRECISION (finaltype), TYPE_UNSIGNED (finaltype)), |