This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix ICE in tree-vrp.c (PR middle-end/38934)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 27 Jan 2009 23:25:42 +0100
- Subject: [PATCH] Fix ICE in tree-vrp.c (PR middle-end/38934)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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