[PATCH] Fix PR31115, wrong code with VRP and shifts

Richard Guenther rguenther@suse.de
Sun Mar 11 12:08:00 GMT 2007


This fixes PR31115, some oversights with my last patch introducing
support for RSHIFT_EXPR in VRP and a bad interaction with the overflow
handling changes.  Basically the problem is that -[-INF, -1] is now
[1, +INF(OVL)] and we now "overflow" right shifting of that even if
right shifting (by a positive shift) never overflows.  This does I
believe cause some optimiation regressions :/

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to mainline.

Richard.

2007-03-11  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/31115
	* tree-vrp.c (extract_range_from_binary_expr): Make sure
	the shift count is positive and non-anti-range for RSHIFT_EXPR.
	A shift count of zero is not special as with *_DIV_EXPR.
	(vrp_int_const_binop): Handle RSHIFT_EXPR for determining overflow
	direction.

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

Index: tree-vrp.c
===================================================================
*** tree-vrp.c	(revision 122805)
--- tree-vrp.c	(working copy)
*************** vrp_int_const_binop (enum tree_code code
*** 1554,1559 ****
--- 1554,1565 ----
  	      && (sgn1 >= 0
  		  ? !is_positive_overflow_infinity (val2)
  		  : is_negative_overflow_infinity (val2)))
+ 	  /* We only get in here with positive shift count, so the
+ 	     overflow direction is the same as the sign of val1.
+ 	     Actually rshift does not overflow at all, but we only
+ 	     handle the case of shifting overflowed -INF and +INF.  */
+ 	  || (code == RSHIFT_EXPR
+ 	      && sgn1 >= 0)
  	  /* For division, the only case is -INF / -1 = +INF.  */
  	  || code == TRUNC_DIV_EXPR
  	  || code == FLOOR_DIV_EXPR
*************** extract_range_from_binary_expr (value_ra
*** 1787,1792 ****
--- 1793,1809 ----
  	  return;
  	}
  
+       /* If we have a RSHIFT_EXPR with a possibly negative shift
+ 	 count or an anti-range shift count drop to VR_VARYING.
+ 	 We currently cannot handle the overflow cases correctly.  */
+       if (code == RSHIFT_EXPR
+ 	  && (vr1.type == VR_ANTI_RANGE
+ 	      || !vrp_expr_computes_nonnegative (op1, &sop)))
+ 	{
+ 	  set_value_range_to_varying (vr);
+ 	  return;
+ 	}
+ 
        /* Multiplications and divisions are a bit tricky to handle,
  	 depending on the mix of signs we have in the two ranges, we
  	 need to operate on different values to get the minimum and
*************** extract_range_from_binary_expr (value_ra
*** 1801,1807 ****
  	 the new range.  */
  
        /* Divisions by zero result in a VARYING value.  */
!       if (code != MULT_EXPR
  	  && (vr0.type == VR_ANTI_RANGE || range_includes_zero_p (&vr1)))
  	{
  	  set_value_range_to_varying (vr);
--- 1818,1825 ----
  	 the new range.  */
  
        /* Divisions by zero result in a VARYING value.  */
!       if ((code != MULT_EXPR
! 	   && code != RSHIFT_EXPR)
  	  && (vr0.type == VR_ANTI_RANGE || range_includes_zero_p (&vr1)))
  	{
  	  set_value_range_to_varying (vr);
Index: testsuite/gcc.dg/torture/pr31115.c
===================================================================
*** testsuite/gcc.dg/torture/pr31115.c	(revision 0)
--- testsuite/gcc.dg/torture/pr31115.c	(revision 0)
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do run } */
+ 
+ extern void exit(int);
+ extern void abort();
+ void foo (int e1)
+ {
+   if (e1 < 0)
+     {
+       e1 = -e1;
+       if (e1 >>= 4)
+         {
+           if (e1 >= 1 << 5)
+             exit(0);
+         }
+     }
+ }
+ 
+ int main()
+ {
+   foo(-(1<<9));
+   abort();
+ }



More information about the Gcc-patches mailing list