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 PR53922


This fixes PR53922 - we failed to handle "don't know" return
from value_inside_range inside range_includes_zero_p.  Fixed
and re-structured the code to not have the strage range/anti-range
issue.

Bootstrapped and tested on x86_64-unknown-linxu-gnu, applied.

Richard.

2012-07-13  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/53922
	* tree-vrp.c (value_inside_range): Change prototype to take
	min/max instead of value-range.
	(range_includes_zero_p): Likewise.  Return the result from
	value_inside_range.
	(extract_range_from_binary_expr_1): Adjust to handle dont-know
	return value from range_includes_zero_p.
	(extract_range_from_unary_expr_1): Likewise.
	(compare_range_with_value): Likewise.
	(vrp_meet_1): Likewise.

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

Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c	(revision 189451)
--- gcc/tree-vrp.c	(working copy)
*************** compare_values (tree val1, tree val2)
*** 1339,1379 ****
  }
  
  
! /* Return 1 if VAL is inside value range VR (VR->MIN <= VAL <= VR->MAX),
!           0 if VAL is not inside VR,
  	 -2 if we cannot tell either way.
  
-    FIXME, the current semantics of this functions are a bit quirky
- 	  when taken in the context of VRP.  In here we do not care
- 	  about VR's type.  If VR is the anti-range ~[3, 5] the call
- 	  value_inside_range (4, VR) will return 1.
- 
- 	  This is counter-intuitive in a strict sense, but the callers
- 	  currently expect this.  They are calling the function
- 	  merely to determine whether VR->MIN <= VAL <= VR->MAX.  The
- 	  callers are applying the VR_RANGE/VR_ANTI_RANGE semantics
- 	  themselves.
- 
- 	  This also applies to value_ranges_intersect_p and
- 	  range_includes_zero_p.  The semantics of VR_RANGE and
- 	  VR_ANTI_RANGE should be encoded here, but that also means
- 	  adapting the users of these functions to the new semantics.
- 
     Benchmark compile/20001226-1.c compilation time after changing this
     function.  */
  
  static inline int
! value_inside_range (tree val, value_range_t * vr)
  {
    int cmp1, cmp2;
  
!   cmp1 = operand_less_p (val, vr->min);
    if (cmp1 == -2)
      return -2;
    if (cmp1 == 1)
      return 0;
  
!   cmp2 = operand_less_p (vr->max, val);
    if (cmp2 == -2)
      return -2;
  
--- 1339,1363 ----
  }
  
  
! /* Return 1 if VAL is inside value range MIN <= VAL <= MAX,
!           0 if VAL is not inside [MIN, MAX],
  	 -2 if we cannot tell either way.
  
     Benchmark compile/20001226-1.c compilation time after changing this
     function.  */
  
  static inline int
! value_inside_range (tree val, tree min, tree max)
  {
    int cmp1, cmp2;
  
!   cmp1 = operand_less_p (val, min);
    if (cmp1 == -2)
      return -2;
    if (cmp1 == 1)
      return 0;
  
!   cmp2 = operand_less_p (max, val);
    if (cmp2 == -2)
      return -2;
  
*************** value_ranges_intersect_p (value_range_t
*** 1402,1424 ****
  }
  
  
! /* Return true if VR includes the value zero, false otherwise.  FIXME,
!    currently this will return false for an anti-range like ~[-4, 3].
!    This will be wrong when the semantics of value_inside_range are
!    modified (currently the users of this function expect these
!    semantics).  */
  
! static inline bool
! range_includes_zero_p (value_range_t *vr)
  {
!   tree zero;
! 
!   gcc_assert (vr->type != VR_UNDEFINED
!               && vr->type != VR_VARYING
! 	      && !symbolic_range_p (vr));
! 
!   zero = build_int_cst (TREE_TYPE (vr->min), 0);
!   return (value_inside_range (zero, vr) == 1);
  }
  
  /* Return true if *VR is know to only contain nonnegative values.  */
--- 1386,1399 ----
  }
  
  
! /* Return 1 if [MIN, MAX] includes the value zero, 0 if it does not
!    include the value zero, -2 if we cannot tell.  */
  
! static inline int
! range_includes_zero_p (tree min, tree max)
  {
!   tree zero = build_int_cst (TREE_TYPE (min), 0);
!   return value_inside_range (zero, min, max);
  }
  
  /* Return true if *VR is know to only contain nonnegative values.  */
*************** extract_range_from_binary_expr_1 (value_
*** 2641,2647 ****
  	     gives [min / 4, max / 4] range.  */
  	  if (vr1.type == VR_RANGE
  	      && !symbolic_range_p (&vr1)
! 	      && !range_includes_zero_p (&vr1))
  	    {
  	      vr0.type = type = VR_RANGE;
  	      vr0.min = vrp_val_min (expr_type);
--- 2616,2622 ----
  	     gives [min / 4, max / 4] range.  */
  	  if (vr1.type == VR_RANGE
  	      && !symbolic_range_p (&vr1)
! 	      && range_includes_zero_p (vr1.min, vr1.max) == 0)
  	    {
  	      vr0.type = type = VR_RANGE;
  	      vr0.min = vrp_val_min (expr_type);
*************** extract_range_from_binary_expr_1 (value_
*** 2658,2665 ****
  	 not eliminate a division by zero.  */
        if (cfun->can_throw_non_call_exceptions
  	  && (vr1.type != VR_RANGE
! 	      || symbolic_range_p (&vr1)
! 	      || range_includes_zero_p (&vr1)))
  	{
  	  set_value_range_to_varying (vr);
  	  return;
--- 2633,2639 ----
  	 not eliminate a division by zero.  */
        if (cfun->can_throw_non_call_exceptions
  	  && (vr1.type != VR_RANGE
! 	      || range_includes_zero_p (vr1.min, vr1.max) != 0))
  	{
  	  set_value_range_to_varying (vr);
  	  return;
*************** extract_range_from_binary_expr_1 (value_
*** 2670,2677 ****
  	 include 0.  */
        if (vr0.type == VR_RANGE
  	  && (vr1.type != VR_RANGE
! 	      || symbolic_range_p (&vr1)
! 	      || range_includes_zero_p (&vr1)))
  	{
  	  tree zero = build_int_cst (TREE_TYPE (vr0.min), 0);
  	  int cmp;
--- 2644,2650 ----
  	 include 0.  */
        if (vr0.type == VR_RANGE
  	  && (vr1.type != VR_RANGE
! 	      || range_includes_zero_p (vr1.min, vr1.max) != 0))
  	{
  	  tree zero = build_int_cst (TREE_TYPE (vr0.min), 0);
  	  int cmp;
*************** extract_range_from_binary_expr_1 (value_
*** 2723,2730 ****
    else if (code == TRUNC_MOD_EXPR)
      {
        if (vr1.type != VR_RANGE
! 	  || symbolic_range_p (&vr1)
! 	  || range_includes_zero_p (&vr1)
  	  || vrp_val_is_min (vr1.min))
  	{
  	  set_value_range_to_varying (vr);
--- 2696,2702 ----
    else if (code == TRUNC_MOD_EXPR)
      {
        if (vr1.type != VR_RANGE
! 	  || range_includes_zero_p (vr1.min, vr1.max) != 0
  	  || vrp_val_is_min (vr1.min))
  	{
  	  set_value_range_to_varying (vr);
*************** extract_range_from_unary_expr_1 (value_r
*** 3159,3165 ****
  	 ~[-INF, min(MIN, MAX)].  */
        if (vr0.type == VR_ANTI_RANGE)
  	{
! 	  if (range_includes_zero_p (&vr0))
  	    {
  	      /* Take the lower of the two values.  */
  	      if (cmp != 1)
--- 3131,3137 ----
  	 ~[-INF, min(MIN, MAX)].  */
        if (vr0.type == VR_ANTI_RANGE)
  	{
! 	  if (range_includes_zero_p (vr0.min, vr0.max) == 1)
  	    {
  	      /* Take the lower of the two values.  */
  	      if (cmp != 1)
*************** extract_range_from_unary_expr_1 (value_r
*** 3210,3216 ****
  
        /* If the range contains zero then we know that the minimum value in the
           range will be zero.  */
!       else if (range_includes_zero_p (&vr0))
  	{
  	  if (cmp == 1)
  	    max = min;
--- 3182,3188 ----
  
        /* If the range contains zero then we know that the minimum value in the
           range will be zero.  */
!       else if (range_includes_zero_p (vr0.min, vr0.max) == 1)
  	{
  	  if (cmp == 1)
  	    max = min;
*************** compare_range_with_value (enum tree_code
*** 3812,3818 ****
  	return NULL_TREE;
  
        /* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2.  */
!       if (value_inside_range (val, vr) == 1)
  	return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node;
  
        return NULL_TREE;
--- 3784,3790 ----
  	return NULL_TREE;
  
        /* ~[VAL_1, VAL_2] OP VAL is known if VAL_1 <= VAL <= VAL_2.  */
!       if (value_inside_range (val, vr->min, vr->max) == 1)
  	return (comp == NE_EXPR) ? boolean_true_node : boolean_false_node;
  
        return NULL_TREE;
*************** vrp_meet_1 (value_range_t *vr0, value_ra
*** 7548,7559 ****
  	 anti-range.  FIXME, all this nonsense about distinguishing
  	 anti-ranges from ranges is necessary because of the odd
  	 semantics of range_includes_zero_p and friends.  */
!       if (!symbolic_range_p (&saved)
! 	  && ((saved.type == VR_RANGE && !range_includes_zero_p (&saved))
! 	      || (saved.type == VR_ANTI_RANGE && range_includes_zero_p (&saved)))
! 	  && !symbolic_range_p (vr1)
! 	  && ((vr1->type == VR_RANGE && !range_includes_zero_p (vr1))
! 	      || (vr1->type == VR_ANTI_RANGE && range_includes_zero_p (vr1))))
  	{
  	  set_value_range_to_nonnull (vr0, TREE_TYPE (saved.min));
  
--- 7520,7533 ----
  	 anti-range.  FIXME, all this nonsense about distinguishing
  	 anti-ranges from ranges is necessary because of the odd
  	 semantics of range_includes_zero_p and friends.  */
!       if (((saved.type == VR_RANGE
! 	    && range_includes_zero_p (saved.min, saved.max) == 0)
! 	   || (saved.type == VR_ANTI_RANGE
! 	       && range_includes_zero_p (saved.min, saved.max) == 1))
! 	  && ((vr1->type == VR_RANGE
! 	       && range_includes_zero_p (vr1->min, vr1->max) == 0)
! 	      || (vr1->type == VR_ANTI_RANGE
! 		  && range_includes_zero_p (vr1->min, vr1->max) == 1)))
  	{
  	  set_value_range_to_nonnull (vr0, TREE_TYPE (saved.min));
  
Index: gcc/testsuite/gcc.dg/torture/pr53922.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr53922.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr53922.c	(working copy)
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do run } */
+ /* { dg-require-weak "" } */
+ 
+ int x(int a)
+ {
+   return a;
+ }
+ int y(int a) __attribute__ ((weak));
+ int g = 0;
+ int main()
+ {
+   int (*scan_func)(int);
+   if (g)
+     scan_func = x;
+   else
+     scan_func = y;
+ 
+   if (scan_func)
+     g = scan_func(10);
+ 
+   return 0;
+ }


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