[RFA][PR tree-optimization/79095] [PATCH 1/4] Improve ranges for MINUS_EXPR and EXACT_DIV_EXPR

Jeff Law law@redhat.com
Sat Feb 4 14:52:00 GMT 2017


This is the first of a 4 part series to address the issues around 79095.

This patch addresses improvements in determining ranges of binary 
expressions in three ways.

First if we are otherwise unable to find a range for the result of a 
MINUS_EXPR, if we know the arguments are not equal, then we know the 
resultant range is ~[0,0].

Second, for EXACT_DIV_EXPR, if the numerator has the range ~[0,0], then 
resultant range is currently [TYPE_MIN/DENOM,TYPE_MAX/DENOM].  That is 
rarely a useful range.   A resultant range of ~[0,0] is actually more 
useful since it often tells us something important about the difference 
of two pointers.

Finally, when vrp2 discovers an updated range for an object that had a 
range discovered by vrp1, if the new range is ~[0,0], prefer that new 
range in some cases.  This is needed to avoid losing the newly 
discovered ~[0,0] range for EXACT_DIV_EXPR.

Bootstrapped and regression tested with the other patches in this 
series.  OK for the trunk?

Jeff
-------------- next part --------------
	* tree-vrp.c (extract_range_from_binary_expr): For EXACT_DIV_EXPR,
	if the numerator has the range ~[0,0] make the resultant range
	~[0,0].  For MINUS_EXPR with no derived range, if the operands are
	known to be not equal, then the resulting range is ~[0,0].
	(intersect_ranges): In some cases prefer ~[0,0].

commit b7baf46ab62e28d2dbc22e9dcd4404926d59df18
Author: Jeff Law <law@torsion.usersys.redhat.com>
Date:   Fri Feb 3 15:45:58 2017 -0500

    Improved ranges

diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index b429217..3338d8b 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3298,6 +3298,37 @@ extract_range_from_binary_expr (value_range *vr,
 
       extract_range_from_binary_expr_1 (vr, code, expr_type, &n_vr0, &vr1);
     }
+
+  /* EXACT_DIV_EXPR is typically used for pointer subtraction;
+     as a result a ~[0,0] may be better than what has already
+     been computed.
+
+     In particular if numerator has the range ~[0,0], then the
+     result range is going to be something like
+     [MININT/DIVISOR,MAXINT/DIVISOR], which is rarely useful.
+
+     So instead make the result range ~[0,0].  */
+  if (code == EXACT_DIV_EXPR
+      && TREE_CODE (op0) == SSA_NAME
+      && vr0.type == VR_ANTI_RANGE
+      && vr0.min == vr0.max
+      && integer_zerop (vr0.min))
+    set_value_range_to_nonnull (vr, TREE_TYPE (op0));
+
+  /* If we didn't derive a range for MINUS_EXPR, and
+     op1's range is ~[op0,op0] or vice-versa, then we
+     can derive a non-null range.  This happens often for
+     pointer subtraction.  */
+  if (vr->type == VR_VARYING
+      && code == MINUS_EXPR
+      && TREE_CODE (op0) == SSA_NAME
+      && ((vr0.type == VR_ANTI_RANGE
+	   && symbolic_range_based_on_p (&vr0, op1)
+	   && vr0.min == vr0.max)
+	  || (vr1.type == VR_ANTI_RANGE
+	      && symbolic_range_based_on_p (&vr1, op0)
+	      && vr1.min == vr1.max)))
+      set_value_range_to_nonnull (vr, TREE_TYPE (op0));
 }
 
 /* Extract range information from a unary operation CODE based on
@@ -8620,6 +8651,12 @@ intersect_ranges (enum value_range_type *vr0type,
 	  else if (vrp_val_is_min (vr1min)
 		   && vrp_val_is_max (vr1max))
 	    ;
+	  /* Choose the anti-range if it is ~[0,0], that range is special
+	     enough to special case.  */
+	  else if (*vr0type == VR_ANTI_RANGE
+		   && *vr0min == *vr0max
+		   && integer_zerop (*vr0min))
+	    ;
 	  /* Else choose the range.  */
 	  else
 	    {


More information about the Gcc-patches mailing list