diff mbox

[RFC,1/3] Free a bit in SSA_NAME to save wrapped information

Message ID 54B9C3C2.2020402@linaro.org
State New
Headers show

Commit Message

Kugan Vivekanandarajah Jan. 17, 2015, 2:06 a.m. UTC
Freeing a spare-bit to store wrapped attribute by going back to
representing VR_ANTI_RANGE as [max + 1, min - 1] in SSA_NAME.

Thanks,
Kugan

gcc/ChangeLog:

2015-01-16  Kugan Vivekanandarajah  <kuganv@linaro.org>

	* tree-ssanames.c (set_range_info): Change range info representation
	  and represent VR_ANTI_RANGE as [max + 1, min - 1].
	(get_range_info): Likewise.
	(set_nonzero_bits): Likewise.
	(duplicate_ssa_name_range_info): Likewise.
	* tree-ssanames.h (set_range_info): Change prototype.
	(get_range_info): Likewise.
	(set_nonzero_bits): Likewise.
	(duplicate_ssa_name_range_info): Likewise.
	* tree-vrp.c (remove_range_assertions): Use new representation.
	(vrp_finalize): Likewise.
diff mbox

Patch

diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 9c39f65..744dc43 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -200,11 +200,10 @@  make_ssa_name_fn (struct function *fn, tree var, gimple stmt)
 /* Store range information RANGE_TYPE, MIN, and MAX to tree ssa_name NAME.  */
 
 void
-set_range_info (tree name, enum value_range_type range_type,
+set_range_info (tree name,
 		const wide_int_ref &min, const wide_int_ref &max)
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
-  gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
   unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
 
@@ -219,16 +218,12 @@  set_range_info (tree name, enum value_range_type range_type,
       ri->set_nonzero_bits (wi::shwi (-1, precision));
     }
 
-  /* Record the range type.  */
-  if (SSA_NAME_RANGE_TYPE (name) != range_type)
-    SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);
-
   /* Set the values.  */
   ri->set_min (min);
   ri->set_max (max);
 
   /* If it is a range, try to improve nonzero_bits from the min/max.  */
-  if (range_type == VR_RANGE)
+  if (wi::cmp (min, max, TYPE_SIGN (TREE_TYPE (name))) < 0)
     {
       wide_int xorv = ri->get_min () ^ ri->get_max ();
       if (xorv != 0)
@@ -248,6 +243,7 @@  get_range_info (const_tree name, wide_int *min, wide_int *max)
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   gcc_assert (min && max);
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
+  value_range_type range_type;
 
   /* Return VR_VARYING for SSA_NAMEs with NULL RANGE_INFO or SSA_NAMEs
      with integral types width > 2 * HOST_BITS_PER_WIDE_INT precision.  */
@@ -255,9 +251,22 @@  get_range_info (const_tree name, wide_int *min, wide_int *max)
 	      > 2 * HOST_BITS_PER_WIDE_INT))
     return VR_VARYING;
 
-  *min = ri->get_min ();
-  *max = ri->get_max ();
-  return SSA_NAME_RANGE_TYPE (name);
+   /* If max < min, it is VR_ANTI_RANGE.  */
+  if (wi::cmp (ri->get_max (), ri->get_min (), TYPE_SIGN (TREE_TYPE (name))) < 0)
+    {
+      /* VR_ANTI_RANGE ~[min, max] is encoded as [max + 1, min - 1].  */
+      range_type = VR_ANTI_RANGE;
+      *min = wi::add (ri->get_max (), 1);
+      *max = wi::sub (ri->get_min (), 1);
+    }
+  else
+    {
+      /* Otherwise (when min <= max), it is VR_RANGE.  */
+      range_type = VR_RANGE;
+      *min = ri->get_min ();
+      *max = ri->get_max ();
+    }
+  return range_type;
 }
 
 /* Change non-zero bits bitmask of NAME.  */
@@ -267,7 +276,7 @@  set_nonzero_bits (tree name, const wide_int_ref &mask)
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   if (SSA_NAME_RANGE_INFO (name) == NULL)
-    set_range_info (name, VR_RANGE,
+    set_range_info (name,
 		    TYPE_MIN_VALUE (TREE_TYPE (name)),
 		    TYPE_MAX_VALUE (TREE_TYPE (name)));
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
@@ -495,7 +504,8 @@  duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
 /* Creates a duplicate of the range_info_def at RANGE_INFO of type
    RANGE_TYPE for use by the SSA name NAME.  */
 void
-duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
+duplicate_ssa_name_range_info (tree name,
+			       enum value_range_type range_type ATTRIBUTE_UNUSED,
 			       struct range_info_def *range_info)
 {
   struct range_info_def *new_range_info;
@@ -513,8 +523,6 @@  duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
   new_range_info = static_cast<range_info_def *> (ggc_internal_alloc (size));
   memcpy (new_range_info, range_info, size);
 
-  gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
-  SSA_NAME_ANTI_RANGE_P (name) = (range_type == VR_ANTI_RANGE);
   SSA_NAME_RANGE_INFO (name) = new_range_info;
 }
 
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index a7eeb8f..0d4b212 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -68,7 +68,7 @@  struct GTY ((variable_size)) range_info_def {
 enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
 
 /* Sets the value range to SSA.  */
-extern void set_range_info (tree, enum value_range_type, const wide_int_ref &,
+extern void set_range_info (tree, const wide_int_ref &,
 			    const wide_int_ref &);
 /* Gets the value range from SSA.  */
 extern enum value_range_type get_range_info (const_tree, wide_int *,
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 2e0b158..9b7695d 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -6915,7 +6915,7 @@  remove_range_assertions (void)
 		    && all_imm_uses_in_stmt_or_feed_cond (var, stmt,
 							  single_pred (bb)))
 		  {
-		    set_range_info (var, SSA_NAME_RANGE_TYPE (lhs),
+		    set_range_info (var,
 				    SSA_NAME_RANGE_INFO (lhs)->get_min (),
 				    SSA_NAME_RANGE_INFO (lhs)->get_max ());
 		    maybe_set_nonzero_bits (bb, var);
@@ -10238,12 +10238,35 @@  vrp_finalize (void)
 	  || (vr_value[i]->type == VR_UNDEFINED))
 	continue;
 
-	if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
-	    && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
-	    && (vr_value[i]->type == VR_RANGE
-		|| vr_value[i]->type == VR_ANTI_RANGE))
-	  set_range_info (name, vr_value[i]->type, vr_value[i]->min,
-			  vr_value[i]->max);
+      if ((TREE_CODE (vr_value[i]->min) == INTEGER_CST)
+	  && (TREE_CODE (vr_value[i]->max) == INTEGER_CST)
+	  && (vr_value[i]->type == VR_RANGE
+	      || vr_value[i]->type == VR_ANTI_RANGE))
+	{
+	  if (vr_value[i]->type == VR_RANGE)
+	   set_range_info (name, vr_value[i]->min, vr_value[i]->max);
+	  else if (vr_value[i]->type == VR_ANTI_RANGE)
+	    {
+	      /* VR_ANTI_RANGE
+		 ~[min, max] is encoded compactly as
+		 [max + 1, min - 1] without additional attributes.
+		 When min value > max value, we know that it is
+		 VR_ANTI_RANGE; it is VR_RANGE otherwise.  */
+
+	      if (TYPE_UNSIGNED (TREE_TYPE (name))
+		  && integer_zerop (vr_value[i]->min)
+		  && integer_zerop (vr_value[i]->max))
+		/* ~[0,0] anti-range is represented as range.  */
+		set_range_info (name,
+				build_int_cst (TREE_TYPE (name), 1),
+				TYPE_MAXVAL (TREE_TYPE (name)));
+	      else
+		set_range_info (name,
+				wi::add (vr_value[i]->max, 1),
+				wi::sub (vr_value[i]->min, 1));
+	    }
+	}
+
       }
 
   /* Free allocated memory.  */