Patchwork VRP TLC

login
register
mail settings
Submitter Richard Guenther
Date Aug. 15, 2011, 2:29 p.m.
Message ID <alpine.LNX.2.00.1108151629070.810@zhemvz.fhfr.qr>
Download mbox | patch
Permalink /patch/110039/
State New
Headers show

Comments

Richard Guenther - Aug. 15, 2011, 2:29 p.m.
This restructures extract_range_from_unary_expr_1 so it is easier
to follow.

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

Richard.

2011-08-15  Richard Guenther  <rguenther@suse.de>

	* tree-vrp.c (value_range_nonnegative_p): Fix anti-range case.
	(extract_range_from_unary_expr_1): Restructure.

Patch

Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	(revision 177759)
+++ gcc/tree-vrp.c	(working copy)
@@ -1398,16 +1398,14 @@  range_includes_zero_p (value_range_t *vr
 static inline bool
 value_range_nonnegative_p (value_range_t *vr)
 {
+  /* Testing for VR_ANTI_RANGE is not useful here as any anti-range
+     which would return a useful value should be encoded as a 
+     VR_RANGE.  */
   if (vr->type == VR_RANGE)
     {
       int result = compare_values (vr->min, integer_zero_node);
       return (result == 0 || result == 1);
     }
-  else if (vr->type == VR_ANTI_RANGE)
-    {
-      int result = compare_values (vr->max, integer_zero_node);
-      return result == -1;
-    }
 
   return false;
 }
@@ -2826,61 +2886,51 @@  extract_range_from_unary_expr_1 (value_r
 				 value_range_t *vr0_, tree op0_type)
 {
   value_range_t vr0 = *vr0_;
-  tree min, max;
-  int cmp;
-
-  /* If VR0 is UNDEFINED, so is the result.  */
-  if (vr0.type == VR_UNDEFINED)
-    {
-      set_value_range_to_undefined (vr);
-      return;
-    }
 
-  /* Refuse to operate on certain unary expressions for which we
-     cannot easily determine a resulting range.  */
-  if (code == FIX_TRUNC_EXPR
-      || code == FLOAT_EXPR
-      || code == CONJ_EXPR)
+  /* VRP only operates on integral and pointer types.  */
+  if (!(INTEGRAL_TYPE_P (op0_type)
+	|| POINTER_TYPE_P (op0_type))
+      || !(INTEGRAL_TYPE_P (type)
+	   || POINTER_TYPE_P (type)))
     {
       set_value_range_to_varying (vr);
       return;
     }
 
-  /* Refuse to operate on symbolic ranges, or if neither operand is
-     a pointer or integral type.  */
-  if ((!INTEGRAL_TYPE_P (op0_type)
-       && !POINTER_TYPE_P (op0_type))
-      || (vr0.type != VR_VARYING
-	  && symbolic_range_p (&vr0)))
+  /* If VR0 is UNDEFINED, so is the result.  */
+  if (vr0.type == VR_UNDEFINED)
     {
-      set_value_range_to_varying (vr);
-      return;
-    }
-
-  /* If the expression involves pointers, we are only interested in
-     determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]).  */
-  if (POINTER_TYPE_P (type) || POINTER_TYPE_P (op0_type))
-    {
-      if (range_is_nonnull (&vr0))
-	set_value_range_to_nonnull (vr, type);
-      else if (range_is_null (&vr0))
-	set_value_range_to_null (vr, type);
-      else
-	set_value_range_to_varying (vr);
+      set_value_range_to_undefined (vr);
       return;
     }
 
-  /* Handle unary expressions on integer ranges.  */
-  if (CONVERT_EXPR_CODE_P (code)
-      && INTEGRAL_TYPE_P (type)
-      && INTEGRAL_TYPE_P (op0_type))
+  if (CONVERT_EXPR_CODE_P (code))
     {
       tree inner_type = op0_type;
       tree outer_type = type;
 
+      /* If the expression evaluates to a pointer, we are only interested in
+	 determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]).  */
+      if (POINTER_TYPE_P (type))
+	{
+	  if (CONVERT_EXPR_CODE_P (code))
+	    {
+	      if (range_is_nonnull (&vr0))
+		set_value_range_to_nonnull (vr, type);
+	      else if (range_is_null (&vr0))
+		set_value_range_to_null (vr, type);
+	      else
+		set_value_range_to_varying (vr);
+	    }
+	  else
+	    set_value_range_to_varying (vr);
+	  return;
+	}
+
       /* If VR0 is varying and we increase the type precision, assume
 	 a full range for the following transformation.  */
       if (vr0.type == VR_VARYING
+	  && INTEGRAL_TYPE_P (inner_type)
 	  && TYPE_PRECISION (inner_type) < TYPE_PRECISION (outer_type))
 	{
 	  vr0.type = VR_RANGE;
@@ -2933,20 +2983,7 @@  extract_range_from_unary_expr_1 (value_r
       set_value_range_to_varying (vr);
       return;
     }
-
-  /* Conversion of a VR_VARYING value to a wider type can result
-     in a usable range.  So wait until after we've handled conversions
-     before dropping the result to VR_VARYING if we had a source
-     operand that is VR_VARYING.  */
-  if (vr0.type == VR_VARYING)
-    {
-      set_value_range_to_varying (vr);
-      return;
-    }
-
-  /* Apply the operation to each end of the range and see what we end
-     up with.  */
-  if (code == NEGATE_EXPR)
+  else if (code == NEGATE_EXPR)
     {
       /* -X is simply 0 - X, so re-use existing code that also handles
          anti-ranges fine.  */
@@ -2955,17 +2992,35 @@  extract_range_from_unary_expr_1 (value_r
       extract_range_from_binary_expr_1 (vr, MINUS_EXPR, type, &zero, &vr0);
       return;
     }
-  else if (code == ABS_EXPR
-           && !TYPE_UNSIGNED (type))
+  else if (code == ABS_EXPR)
     {
+      tree min, max;
+      int cmp;
+
+      /* Pass through vr0 in the easy cases.  */
+      if (TYPE_UNSIGNED (type)
+	  || value_range_nonnegative_p (&vr0))
+	{
+	  copy_value_range (vr, &vr0);
+	  return;
+	}
+
+      /* For the remaining varying or symbolic ranges we can't do anything
+	 useful.  */
+      if (vr0.type == VR_VARYING
+	  || symbolic_range_p (&vr0))
+	{
+	  set_value_range_to_varying (vr);
+	  return;
+	}
+
       /* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
          useful range.  */
       if (!TYPE_OVERFLOW_UNDEFINED (type)
 	  && ((vr0.type == VR_RANGE
 	       && vrp_val_is_min (vr0.min))
 	      || (vr0.type == VR_ANTI_RANGE
-		  && !vrp_val_is_min (vr0.min)
-		  && !range_includes_zero_p (&vr0))))
+		  && !vrp_val_is_min (vr0.min))))
 	{
 	  set_value_range_to_varying (vr);
 	  return;
@@ -3077,6 +3132,18 @@  extract_range_from_unary_expr_1 (value_r
 	      max = t;
 	    }
 	}
+
+      cmp = compare_values (min, max);
+      if (cmp == -2 || cmp == 1)
+	{
+	  /* If the new range has its limits swapped around (MIN > MAX),
+	     then the operation caused one of them to wrap around, mark
+	     the new range VARYING.  */
+	  set_value_range_to_varying (vr);
+	}
+      else
+	set_value_range (vr, vr0.type, min, max, NULL);
+      return;
     }
   else if (code == BIT_NOT_EXPR)
     {
@@ -3088,69 +3155,15 @@  extract_range_from_unary_expr_1 (value_r
 					type, &minusone, &vr0);
       return;
     }
-  else
+  else if (code == PAREN_EXPR)
     {
-      /* Otherwise, operate on each end of the range.  */
-      min = fold_unary_to_constant (code, type, vr0.min);
-      max = fold_unary_to_constant (code, type, vr0.max);
-
-      if (needs_overflow_infinity (type))
-	{
-	  gcc_assert (code != NEGATE_EXPR && code != ABS_EXPR);
-
-	  /* If both sides have overflowed, we don't know
-	     anything.  */
-	  if ((is_overflow_infinity (vr0.min)
-	       || TREE_OVERFLOW (min))
-	      && (is_overflow_infinity (vr0.max)
-		  || TREE_OVERFLOW (max)))
-	    {
-	      set_value_range_to_varying (vr);
-	      return;
-	    }
-
-	  if (is_overflow_infinity (vr0.min))
-	    min = vr0.min;
-	  else if (TREE_OVERFLOW (min))
-	    {
-	      if (supports_overflow_infinity (type))
-		min = (tree_int_cst_sgn (min) >= 0
-		       ? positive_overflow_infinity (TREE_TYPE (min))
-		       : negative_overflow_infinity (TREE_TYPE (min)));
-	      else
-		{
-		  set_value_range_to_varying (vr);
-		  return;
-		}
-	    }
-
-	  if (is_overflow_infinity (vr0.max))
-	    max = vr0.max;
-	  else if (TREE_OVERFLOW (max))
-	    {
-	      if (supports_overflow_infinity (type))
-		max = (tree_int_cst_sgn (max) >= 0
-		       ? positive_overflow_infinity (TREE_TYPE (max))
-		       : negative_overflow_infinity (TREE_TYPE (max)));
-	      else
-		{
-		  set_value_range_to_varying (vr);
-		  return;
-		}
-	    }
-	}
+      copy_value_range (vr, &vr0);
+      return;
     }
 
-  cmp = compare_values (min, max);
-  if (cmp == -2 || cmp == 1)
-    {
-      /* If the new range has its limits swapped around (MIN > MAX),
-	 then the operation caused one of them to wrap around, mark
-	 the new range VARYING.  */
-      set_value_range_to_varying (vr);
-    }
-  else
-    set_value_range (vr, vr0.type, min, max, NULL);
+  /* For unhandled operations fall back to varying.  */
+  set_value_range_to_varying (vr);
+  return;
 }