abstract ABS_EXPR code for ranges into separate function
diff mbox series

Message ID 10061ca8-17c2-4ffe-ed44-d7a06db8bfb4@redhat.com
State New
Headers show
Series
  • abstract ABS_EXPR code for ranges into separate function
Related show

Commit Message

Aldy Hernandez July 1, 2018, 8:05 a.m. UTC
Boy those extract_range_from_*_expr functions are huge.

OK to move the ABS_EXPR code into its own function?

Tested on x86-64 Linux.

Aldy

Comments

Richard Biener July 2, 2018, 7:25 a.m. UTC | #1
On Sun, Jul 1, 2018 at 10:05 AM Aldy Hernandez <aldyh@redhat.com> wrote:
>
> Boy those extract_range_from_*_expr functions are huge.
>
> OK to move the ABS_EXPR code into its own function?

OK.

Richard.

> Tested on x86-64 Linux.
>
> Aldy

Patch
diff mbox series

commit 1e0dd52b909722e9387a34ef546fc308c68dac23
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Fri Jun 29 20:12:36 2018 +0200

            * tree-vrp.c (extract_range_from_unary_expr): Abstract ABS_EXPR
            code...
            (extract_range_from_abs_expr): ...here.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d1bb6f54d4a..ddbbdd1253e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@ 
+2018-06-29  Aldy Hernandez  <aldyh@redhat.com>
+
+	* tree-vrp.c (extract_range_from_unary_expr): Abstract ABS_EXPR
+	code...
+	(extract_range_from_abs_expr): ...here.
+
 2018-06-29  Aldy Hernandez  <aldyh@redhat.com>
 
 	* tree-vrp.c (extract_range_from_binary_expr_1): Abstract a lot of the
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index ee112bb1826..c966334acbc 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -2365,6 +2365,85 @@  extract_range_from_binary_expr_1 (value_range *vr,
     set_value_range (vr, type, min, max, NULL);
 }
 
+/* Calculates the absolute value of a range and puts the result in VR.
+   VR0 is the input range.  TYPE is the type of the resulting
+   range.  */
+
+static void
+extract_range_from_abs_expr (value_range &vr, tree type, value_range &vr0)
+{
+  /* 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))))
+    {
+      set_value_range_to_varying (&vr);
+      return;
+    }
+
+  /* ABS_EXPR may flip the range around, if the original range
+     included negative values.  */
+  tree min, max;
+  if (!vrp_val_is_min (vr0.min))
+    min = fold_unary_to_constant (ABS_EXPR, type, vr0.min);
+  else
+    min = TYPE_MAX_VALUE (type);
+
+  if (!vrp_val_is_min (vr0.max))
+    max = fold_unary_to_constant (ABS_EXPR, type, vr0.max);
+  else
+    max = TYPE_MAX_VALUE (type);
+
+  int cmp = compare_values (min, max);
+  gcc_assert (vr0.type != VR_ANTI_RANGE);
+
+  /* If the range contains zero then we know that the minimum value in the
+     range will be zero.  */
+  if (range_includes_zero_p (vr0.min, vr0.max) == 1)
+    {
+      if (cmp == 1)
+	max = min;
+      min = build_int_cst (type, 0);
+    }
+  else
+    {
+      /* If the range was reversed, swap MIN and MAX.  */
+      if (cmp == 1)
+	std::swap (min, max);
+    }
+
+  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);
+}
+
 /* Extract range information from a unary operation CODE based on
    the range of its operand *VR0 with type OP0_TYPE with resulting type TYPE.
    The resulting range is stored in *VR.  */
@@ -2495,117 +2574,7 @@  extract_range_from_unary_expr (value_range *vr,
       return;
     }
   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))))
-	{
-	  set_value_range_to_varying (vr);
-	  return;
-	}
-
-      /* ABS_EXPR may flip the range around, if the original range
-	 included negative values.  */
-      if (!vrp_val_is_min (vr0.min))
-	min = fold_unary_to_constant (code, type, vr0.min);
-      else
-	min = TYPE_MAX_VALUE (type);
-
-      if (!vrp_val_is_min (vr0.max))
-	max = fold_unary_to_constant (code, type, vr0.max);
-      else
-	max = TYPE_MAX_VALUE (type);
-
-      cmp = compare_values (min, max);
-
-      /* If a VR_ANTI_RANGEs contains zero, then we have
-	 ~[-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)
-		max = min;
-
-	      /* Create ~[-INF, min (abs(MIN), abs(MAX))]
-	         or ~[-INF + 1, min (abs(MIN), abs(MAX))] when
-		 flag_wrapv is set and the original anti-range doesn't include
-	         TYPE_MIN_VALUE, remember -TYPE_MIN_VALUE = TYPE_MIN_VALUE.  */
-	      if (TYPE_OVERFLOW_WRAPS (type))
-		{
-		  tree type_min_value = TYPE_MIN_VALUE (type);
-
-		  min = (vr0.min != type_min_value
-			 ? int_const_binop (PLUS_EXPR, type_min_value,
-					    build_int_cst (TREE_TYPE (type_min_value), 1))
-			 : type_min_value);
-		}
-	      else
-		min = TYPE_MIN_VALUE (type);
-	    }
-	  else
-	    {
-	      /* All else has failed, so create the range [0, INF], even for
-	         flag_wrapv since TYPE_MIN_VALUE is in the original
-	         anti-range.  */
-	      vr0.type = VR_RANGE;
-	      min = build_int_cst (type, 0);
-	      max = TYPE_MAX_VALUE (type);
-	    }
-	}
-
-      /* 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;
-	  min = build_int_cst (type, 0);
-	}
-      else
-	{
-          /* If the range was reversed, swap MIN and MAX.  */
-	  if (cmp == 1)
-	    std::swap (min, max);
-	}
-
-      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;
-    }
+    return extract_range_from_abs_expr (*vr, type, vr0);
 
   /* For unhandled operations fall back to varying.  */
   set_value_range_to_varying (vr);