Hello,

when I adapted VRP PLUS_EXPR handling for __int128, I missed one place where double_int can overflow. Note that I have no idea if that helps for bug 54317, but that's where I noticed the issue.

2012-08-21  Marc Glisse  <marc.gli...@inria.fr>

        PR tree-optimization/54317

gcc/
        * tree-vrp.c (extract_range_from_binary_expr_1): Test for
        double_int overflow.
        Remove dead tests.

gcc/testsuite/
        * gcc.dg/tree-ssa/vrp79.c: New testcase.

--
Marc Glisse
Index: testsuite/gcc.dg/tree-ssa/vrp79.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/vrp79.c   (revision 0)
+++ testsuite/gcc.dg/tree-ssa/vrp79.c   (revision 0)
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#ifdef __SIZEOF_INT128__
+typedef unsigned __int128 NT;
+#else
+typedef unsigned long long NT;
+#endif
+
+extern void do_not_go_away ();
+
+void f (NT x, NT y)
+{
+  NT n = 1;
+  n <<= (8 * sizeof (NT) - 1);
+  if (x > n) return;
+  if (y > n) return;
+  NT z = x + y;
+  if (z == 42) do_not_go_away ();
+}
+
+/* { dg-final { scan-tree-dump "do_not_go_away" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */

Property changes on: testsuite/gcc.dg/tree-ssa/vrp79.c
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision URL
Added: svn:eol-style
   + native

Index: tree-vrp.c
===================================================================
--- tree-vrp.c  (revision 190590)
+++ tree-vrp.c  (working copy)
@@ -2467,32 +2467,35 @@ extract_range_from_binary_expr_1 (value_
                       && max_ovf == 1)
                {
                  /* Underflow and overflow, drop to VR_VARYING.  */
                  set_value_range_to_varying (vr);
                  return;
                }
              else
                {
                  /* Min underflow or max overflow.  The range kind
                     changes to VR_ANTI_RANGE.  */
+                 bool covers = false;
                  double_int tem = tmin;
                  gcc_assert ((min_ovf == -1 && max_ovf == 0)
                              || (max_ovf == 1 && min_ovf == 0));
                  type = VR_ANTI_RANGE;
                  tmin = double_int_add (tmax, double_int_one);
+                 if (double_int_cmp (tmin, tmax, uns) < 0)
+                   covers = true;
                  tmax = double_int_add (tem, double_int_minus_one);
+                 if (double_int_cmp (tmax, tem, uns) > 0)
+                   covers = true;
                  /* If the anti-range would cover nothing, drop to varying.
                     Likewise if the anti-range bounds are outside of the
                     types values.  */
-                 if (double_int_cmp (tmin, tmax, uns) > 0
-                     || double_int_cmp (tmin, type_min, uns) < 0
-                     || double_int_cmp (tmax, type_max, uns) > 0)
+                 if (covers || double_int_cmp (tmin, tmax, uns) > 0)
                    {
                      set_value_range_to_varying (vr);
                      return;
                    }
                  min = double_int_to_tree (expr_type, tmin);
                  max = double_int_to_tree (expr_type, tmax);
                }
            }
          else
            {

Reply via email to