This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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
 	    {

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]