aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2011-10-17 12:22:54 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2011-10-17 12:22:54 +0000
commit7d5a0f1b4e54f83337d5a0b093b0a40ae8cf27d6 (patch)
treec4d0d2f384a38c365c5371e2b67503ad50a6fb57 /gcc
parentb9bd6f743843a53de1396c43d1e308e51d40c5c4 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50729.c20
-rw-r--r--gcc/tree-vrp.c26
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)),