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 PR29446, VRP ICE


This fixes yet another VRP ICE which occours because we (again) end
up with "inconsistent" equivalence sets with symbolic ranges.

The final fix is to treat the point-of-ICE for what it is -- detecting
a neither true nor false condition.  Or better, detecting that the
value(s) we compare do not have a value at this point in the CFG.

In the end it is not important what value we return in this case
(I chose NULL_TREE, which is "don't know") - either true or false
or don't know is appropriate.  Most appropriate would be a fourth
state and fold the condition (and the true and false arms) to a
runtime trap-representation.

Anyway - here's the simple approach returning NULL_TREE.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Ok for mainline?

Thanks,
Richard.

:ADDPATCH middle-end:

2006-10-13  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/29446
	* tree-vrp.c (fix_equivalence_set): Remove.
	(extract_range_from_assert): Do not call fix_equivalence_set.
	(debug_value_range): Print a newline.
	(compare_name_with_value): For equivalence sets with
	inconsistent value ranges conservatively bail out.
	(compare_names): Likewise.

	* gcc.dg/torture/pr29446.c: New testcase.

Index: tree-vrp.c
===================================================================
*** tree-vrp.c	(revision 117684)
--- tree-vrp.c	(working copy)
*************** ssa_name_nonzero_p (tree t)
*** 724,809 ****
  }
  
  
- /* When extracting ranges from X_i = ASSERT_EXPR <Y_j, pred>, we will
-    initially consider X_i and Y_j equivalent, so the equivalence set
-    of Y_j is added to the equivalence set of X_i.  However, it is
-    possible to have a chain of ASSERT_EXPRs whose predicates are
-    actually incompatible.  This is usually the result of nesting of
-    contradictory if-then-else statements.  For instance, in PR 24670:
- 
-    	count_4 has range [-INF, 63]
- 
-    	if (count_4 != 0)
- 	  {
- 	    count_19 = ASSERT_EXPR <count_4, count_4 != 0>
- 	    if (count_19 > 63)
- 	      {
- 	        count_18 = ASSERT_EXPR <count_19, count_19 > 63>
- 		if (count_18 <= 63)
- 		  ...
- 	      }
- 	  }
- 
-    Notice that 'if (count_19 > 63)' is trivially false and will be
-    folded out at the end.  However, during propagation, the flowgraph
-    is not cleaned up and so, VRP will evaluate predicates more
-    predicates than necessary, so it must support these
-    inconsistencies.  The problem here is that because of the chaining
-    of ASSERT_EXPRs, the equivalency set for count_18 includes count_4.
-    Since count_4 has an incompatible range, we ICE when evaluating the
-    ranges in the equivalency set.  So, we need to remove count_4 from
-    it.  */
- 
- static void
- fix_equivalence_set (value_range_t *vr_p)
- {
-   bitmap_iterator bi;
-   unsigned i;
-   bitmap e = vr_p->equiv;
-   bitmap to_remove;
- 
-   /* Only detect inconsistencies on numeric ranges.  */
-   if (vr_p->type == VR_VARYING
-       || vr_p->type == VR_UNDEFINED
-       || symbolic_range_p (vr_p))
-     return;
- 
-   to_remove = BITMAP_ALLOC (NULL);
-   EXECUTE_IF_SET_IN_BITMAP (e, 0, i, bi)
-     {
-       value_range_t *equiv_vr = vr_value[i];
- 
-       if (equiv_vr->type == VR_VARYING
- 	  || equiv_vr->type == VR_UNDEFINED)
- 	continue;
- 
-       if (vr_p->type == VR_RANGE
- 	  && equiv_vr->type == VR_RANGE)
- 	{
- 	  /* Two ranges have an empty intersection if their end points
- 	     are outside of the other range.  */
- 	  if (compare_values (equiv_vr->min, vr_p->max) == 1
- 	      || compare_values (equiv_vr->max, vr_p->min) == -1)
- 	    bitmap_set_bit (to_remove, i);
- 	}
-       else if ((equiv_vr->type == VR_RANGE && vr_p->type == VR_ANTI_RANGE)
- 	       || (equiv_vr->type == VR_ANTI_RANGE && vr_p->type == VR_RANGE))
- 	{
- 	  /* A range and an anti-range have an empty intersection if
- 	     their end points are the same.  FIXME,
- 	     value_ranges_intersect_p should handle this
- 	     automatically.  */
- 	  if (compare_values (equiv_vr->min, vr_p->min) == 0
- 	      && compare_values (equiv_vr->max, vr_p->max) == 0)
- 	    bitmap_set_bit (to_remove, i);
- 	}
-     }
- 
-   bitmap_and_compl_into (vr_p->equiv, to_remove);
-   BITMAP_FREE (to_remove);
- }
- 
- 
  /* Extract value range information from an ASSERT_EXPR EXPR and store
     it in *VR_P.  */
  
--- 724,729 ----
*************** extract_range_from_assert (value_range_t
*** 1056,1062 ****
        || var_vr->type == VR_UNDEFINED
        || symbolic_range_p (vr_p)
        || symbolic_range_p (var_vr))
!     goto done;
  
    if (var_vr->type == VR_RANGE && vr_p->type == VR_RANGE)
      {
--- 976,982 ----
        || var_vr->type == VR_UNDEFINED
        || symbolic_range_p (vr_p)
        || symbolic_range_p (var_vr))
!     return;
  
    if (var_vr->type == VR_RANGE && vr_p->type == VR_RANGE)
      {
*************** extract_range_from_assert (value_range_t
*** 1191,1201 ****
  	    }
  	}
      }
- 
-   /* Remove names from the equivalence set that have ranges
-      incompatible with VR_P.  */
- done:
-   fix_equivalence_set (vr_p);
  }
  
  
--- 1111,1116 ----
*************** void
*** 2438,2443 ****
--- 2353,2359 ----
  debug_value_range (value_range_t *vr)
  {
    dump_value_range (stderr, vr);
+   fprintf (stderr, "\n");
  }
  
  
*************** compare_name_with_value (enum tree_code 
*** 3555,3562 ****
        t = compare_range_with_value (comp, &equiv_vr, val);
        if (t)
  	{
! 	  /* All the ranges should compare the same against VAL.  */
! 	  gcc_assert (retval == NULL || t == retval);
  	  retval = t;
  	}
      }
--- 3471,3486 ----
        t = compare_range_with_value (comp, &equiv_vr, val);
        if (t)
  	{
! 	  /* If we get different answers from different members
! 	     of the equivalence set this check must be in a dead
! 	     code region.  Folding it to a trap representation
! 	     would be correct here.  For now just return don't-know.  */
! 	  if (retval != NULL
! 	      && t != retval)
! 	    {
! 	      retval = NULL_TREE;
! 	      break;
! 	    }
  	  retval = t;
  	}
      }
*************** compare_names (enum tree_code comp, tree
*** 3638,3646 ****
  	  t = compare_ranges (comp, &vr1, &vr2);
  	  if (t)
  	    {
! 	      /* All the ranges in the equivalent sets should compare
! 		 the same.  */
! 	      gcc_assert (retval == NULL || t == retval);
  	      retval = t;
  	    }
  	}
--- 3562,3578 ----
  	  t = compare_ranges (comp, &vr1, &vr2);
  	  if (t)
  	    {
! 	      /* If we get different answers from different members
! 		 of the equivalence set this check must be in a dead
! 		 code region.  Folding it to a trap representation
! 		 would be correct here.  For now just return don't-know.  */
! 	      if (retval != NULL
! 		  && t != retval)
! 		{
! 		  bitmap_clear_bit (e1, SSA_NAME_VERSION (n1));
! 		  bitmap_clear_bit (e2, SSA_NAME_VERSION (n2));
! 		  return NULL_TREE;
! 		}
  	      retval = t;
  	    }
  	}

/* { dg-do compile } */

void f(_Bool D917, int j0, int ubound1, int ubound5)
{
  int i, j = j0;
  int (*abc)[3];
  i = 1;
  while (1)
    {
       if (j <= 3)
         while (1)
           {
              if (i != j)
                {
                  if (ubound1 <= 0)
                    return;
                  (*abc)[1] = 0;
                }
               else
                 {
                    if (j > ubound1)
                      return;
                    if (ubound5 <= 0)
                      return;
                  }
               j = j + 1;
               if (D917)
                 break;
           }
    i = i + 1;
  }
}


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