re PR tree-optimization/50729 (Silent code gen fault: Value range propagation seems...
authorRichard Guenther <rguenther@suse.de>
Mon, 17 Oct 2011 12:22:54 +0000 (12:22 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 17 Oct 2011 12:22:54 +0000 (12:22 +0000)
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

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

index 557916c82bcfbc6104f68e092f885a14602babd6..f367a118c7f5496c353d18562e51217cfdcacc6d 100644 (file)
@@ -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>
 
index 1215af60e6448be961283e84f90b2c79409120e0..4dc4e786dcafffb16b4ea51b6cdc3f04ee41a774 100644 (file)
@@ -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 (file)
index 0000000..a1daa7b
--- /dev/null
@@ -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;
+}
index 604e7f0ad02aaaec8531edf6a98fcb9df0b4dea9..248bc61926f6c431e939968abe9ecd55acabcfdb 100644 (file)
@@ -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)),