This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix double_int overflow in VRP PLUS_EXPR
- From: Marc Glisse <marc dot glisse at inria dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 22 Aug 2012 13:55:48 +0200 (CEST)
- Subject: Fix double_int overflow in VRP PLUS_EXPR
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.glisse@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
{