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]

[PATCH] Fix ICE in tree-vrp.c (PR middle-end/38934)


Hi!

As shown on the attached testcase, even if limit_vr's min or max isn't
overflow infinity, but just has TREE_OVERFLOW set (because TREE_OVERFLOW
leaked into the IL), set_value_range called from extract_range_from_assert
may ICE.  In this particular case min is LLONG_MIN, max is -LLONG_MAX
with TREE_OVERFLOW set and cond_code is LT_EXPR.  For LT_EXPR we subtract
one from max, so with TREE_OVERFLOW set max becomes LLONG_MIN with
TREE_OVERFLOW set, aka negative overflow infinity, and that is considered
smaller than LLONG_MIN, so the range is invalid.

I think we should just handle any TREE_OVERFLOW limits the same way as
overflow infinity.  This has been bootstrapped/regtested on x86_64-linux
and i386-linux.  Ok for trunk?

Alternatively we could just test is_overflow_infinity once again after
max = fold_build2 (MINUS_EXPR, type, max, one);
resp. min = fold_build2 (PLUS_EXPR, type, min, one); and set to varying in
that case, which would fix this too.

2009-01-27  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/38934
	* tree-vrp.c (extract_range_from_assert): For LE_EXPR and LT_EXPR
	set to varying whenever max has TREE_OVERFLOW set, similarly
	for GE_EXPR and GT_EXPR and TREE_OVERFLOW min.

	* gcc.dg/pr38934.c: New test.

--- gcc/tree-vrp.c.jj	2009-01-02 09:32:55.000000000 +0100
+++ gcc/tree-vrp.c	2009-01-27 17:40:54.000000000 +0100
@@ -1620,7 +1620,7 @@ extract_range_from_assert (value_range_t
 	 all should be optimized away above us.  */
       if ((cond_code == LT_EXPR
 	   && compare_values (max, min) == 0)
-	  || is_overflow_infinity (max))
+	  || (CONSTANT_CLASS_P (max) && TREE_OVERFLOW (max)))
 	set_value_range_to_varying (vr_p);
       else
 	{
@@ -1655,7 +1655,7 @@ extract_range_from_assert (value_range_t
 	 all should be optimized away above us.  */
       if ((cond_code == GT_EXPR
 	   && compare_values (min, max) == 0)
-	  || is_overflow_infinity (min))
+	  || (CONSTANT_CLASS_P (min) && TREE_OVERFLOW (min)))
 	set_value_range_to_varying (vr_p);
       else
 	{
--- gcc/testsuite/gcc.dg/pr38934.c.jj	2009-01-27 17:56:18.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr38934.c	2009-01-27 17:56:39.000000000 +0100
@@ -0,0 +1,18 @@
+/* PR middle-end/38934 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -std=gnu99 -w" } */
+																	    /* This variable needed only to work around earlier optimizations than VRP.  */
+unsigned char g;
+
+extern void abort ();
+
+void
+f (long long int p)
+{
+  g = 255;
+  if (p >= -9223372036854775808LL - (signed char) g)
+    p = 1;
+
+  if (p)
+    abort ();
+}

	Jakub


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