This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [range-ops] patch 01/04: types for VR_UNDEFINED and VR_VARYING




On 7/4/19 6:33 AM, Richard Biener wrote:
On Wed, Jul 3, 2019 at 2:17 PM Aldy Hernandez <aldyh@redhat.com> wrote:

On 7/3/19 7:08 AM, Richard Biener wrote:
On Wed, Jul 3, 2019 at 11:19 AM Aldy Hernandez <aldyh@redhat.com> wrote:

How about we keep VARYING and UNDEFINED typeless until right before we
call into the ranger.  At which point, we have can populate min/max
because we have the tree_code and the type handy.  So right before we
call into the ranger do:

         if (varying_p ())
           foo->set_varying(TYPE);

This would avoid the type cache, and keep the ranger happy.

you cannot do set_varying on the static const range but instead you'd do

   value_range tem (*foo);
   if (varying_p ())
    tem->set_full_range (TYPE);

which I think we already do in some places.  Thus my question _where_
you actually need this.

Basically, everywhere. By having a type for varying/undefined, we don't have to special case anything. Sure, we could for example, special case the invert operation for undefined / varying. And we could special case everything dealing with ranges to handle varying and undefined, but why? We could also pass a type argument everywhere, but that's just ugly. However, I do understand your objection to the type cache.

How about the attached approach? Set the type for varying/undefined when we know it, while avoiding touching the CONST varying. Then right before calling the ranger, pass down a new varying node with min/max for any varyings that were still typeless until that point.

I have taken care of never adding a set_varying() that was not already there. Would this keep the const happy?

Technically we don't need to set varying/undef types for every instance in VRP, but we need it at least for the code that will be shared with range-ops (extract_range_from_multiplicative_op, union, intersect, etc). I just figured if we have the information, might as well set it for consistency.

If you like this approach, I can rebase the other patches that depend on this one.

Aldy
commit 9ad503e1d6a2edd8b74b1d8cc9a8d9d4ee31386e
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Mon Jul 8 12:45:40 2019 +0200

    Allow min/max in VR_VARYING and VR_UNDEFINED ranges.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b0d78ee6871..2cb308bb568 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,62 @@
+2019-07-01  Aldy Hernandez  <aldyh@redhat.com>
+
+	* gimple-ssa-evrp-analyze.c (record_ranges_from_phis): Skip PHIs
+	who's result are not valid for a value_range.
+	Set type for varying value_range.
+	* tree-ssa-threadedge.c (record_temporary_equivalences_from_phis):
+	Same.
+	* tree-ssanames.c (get_range_info): Same.
+	* tree-vrp.c (value_range_base::value_range_base): New constructor.
+	(value_range_base::check): Remove assert for empty min/max.
+	(value_range_base::equal_p): Allow comparison of typeless undefs.
+	(value_range_base::set_undefined): Add type.
+	(value_range::set_undefined): Same.
+	(value_range_base::set_varying): Same.
+	(value_range::set_varying): Same.
+	(value_range_base::type): Remove assert.
+	(value_range_base::dump): Display type for varying/undef.
+	(value_range_base::dump): Add argument-less overload.
+	(value_range::dump): Same.
+	(vrp_val_max): Add handle_pointers argument.
+	(vrp_val_min): Same.
+	(vrp_val_is_max): Same.
+	(vrp_val_is_min): Same.
+	(value_range_base::set_and_canonicalize): Adjust so type is
+	allowed for varying/undef.
+	(ranges_from_anti_range): Same.
+	(extract_range_from_muliplicative_op): Same.
+	(extract_range_from_binary_expr): Same.
+	(extract_range_from_unary_expr): Same.
+	(vrp_prop::vrp_initialize): Same.
+	(vrp_prop::visit_stmt): Same.
+	(value_range_base::union_helper): Same.
+	(value_range_base::normalize_symbolics): Same.
+	(determine_value_range_1): Same.
+	* tree-vrp.h (value_range_base): Add value_range_base(tree type)
+	constructor.
+	Add dump (), supports_type_p,
+	value_range_base_normalize_symbolics, set_varying, and
+	set_undefined.
+	(value_range): Add set_varying, set_undefined, and dump().
+	(vrp_val_is_min): Add argument.
+	(vrp_val_is_max): Same.
+	(vrp_val_min): Same.
+	(vrp_val_max): Same.
+	(range_includes_zero_p): Adjust for varying/undef with types.
+	* vr-values.c (set_value_range_to_truthvalue): Adjust for
+	varying/undef with types.
+	(get_value_range): Same.
+	(vr_values::set_defs_to_varying): Same.
+	(vr_values::update_value_range): Same.
+	(extract_range_for_var_from_comparison_expr): Same.
+	(extract_range_from_binary_expr): Same.
+	(extract_range_from_cond_expr): Same.
+	(check_for_binary_op_overflow): Same.
+	(extract_range_basic): Same.
+	(extract_range_from_assignment): Same.
+	(extract_range_from_phi_node): Adjust for varying/undef with
+	types.
+
 2019-07-01  Aldy Hernandez  <aldyh@redhat.com>
 
 	* tree-vrp.c (intersect_ranges): If we know the intersection is
diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index 4c68af847e1..467ca57061f 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -251,6 +251,11 @@ evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
       if (virtual_operand_p (lhs))
 	continue;
 
+      /* Skips floats and other things we can't represent in a
+	 range.  */
+      if (!value_range_base::supports_type_p (TREE_TYPE (lhs)))
+	continue;
+
       value_range vr_result;
       bool interesting = stmt_interesting_for_vrp (phi);
       if (!has_unvisited_preds && interesting)
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 785227df690..781f802f365 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -183,7 +183,7 @@ record_temporary_equivalences_from_phis (edge e,
 	  else if (TREE_CODE (src) == INTEGER_CST)
 	    new_vr->set (src);
 	  else
-	    new_vr->set_varying ();
+	    new_vr->set_varying (TREE_TYPE (src));
 
 	  /* This is a temporary range for DST, so push it.  */
 	  evrp_range_analyzer->push_value_range (dst, new_vr);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 8b80bce8945..343e98488a9 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -440,14 +440,16 @@ get_range_info (const_tree name, value_range_base &vr)
   wide_int wmin, wmax;
   enum value_range_kind kind = get_range_info (name, &wmin, &wmax);
 
-  if (kind == VR_VARYING || kind == VR_UNDEFINED)
-    min = max = NULL;
+  if (kind == VR_VARYING)
+    vr.set_varying (TREE_TYPE (name));
+  else if (kind == VR_UNDEFINED)
+    vr.set_undefined (TREE_TYPE (name));
   else
     {
       min = wide_int_to_tree (TREE_TYPE (name), wmin);
       max = wide_int_to_tree (TREE_TYPE (name), wmax);
+      vr.set (kind, min, max);
     }
-  vr.set (kind, min, max);
   return kind;
 }
 
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 594ee9adc17..c5a18686909 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -134,6 +134,11 @@ value_range::value_range (const value_range_base &other)
   set (other.kind (), other.min(), other.max (), NULL);
 }
 
+value_range_base::value_range_base (tree type)
+{
+  set_varying (type);
+}
+
 /* Like set, but keep the equivalences in place.  */
 
 void
@@ -190,7 +195,6 @@ value_range_base::check ()
       }
     case VR_UNDEFINED:
     case VR_VARYING:
-      gcc_assert (!min () && !max ());
       break;
     default:
       gcc_unreachable ();
@@ -217,6 +221,10 @@ value_range::check ()
 bool
 value_range_base::equal_p (const value_range_base &other) const
 {
+  /* Ignore types for undefined.  All undefines are equal.  */
+  if (undefined_p ())
+    return m_kind == other.m_kind;
+
   return (m_kind == other.m_kind
 	  && vrp_operand_equal_p (m_min, other.m_min)
 	  && vrp_operand_equal_p (m_max, other.m_max));
@@ -259,27 +267,43 @@ value_range_base::constant_p () const
 }
 
 void
-value_range_base::set_undefined ()
+value_range_base::set_undefined (tree type)
 {
-  set (VR_UNDEFINED, NULL, NULL);
+  m_kind = VR_UNDEFINED;
+  if (type)
+    {
+      m_min = vrp_val_min (type, true);
+      m_max = vrp_val_max (type, true);
+    }
+  else
+    m_min = m_max = NULL;
 }
 
 void
-value_range::set_undefined ()
+value_range::set_undefined (tree type)
 {
-  set (VR_UNDEFINED, NULL, NULL, NULL);
+  value_range_base::set_undefined (type);
+  equiv_clear ();
 }
 
 void
-value_range_base::set_varying ()
+value_range_base::set_varying (tree type)
 {
-  set (VR_VARYING, NULL, NULL);
+  m_kind = VR_VARYING;
+  if (type)
+    {
+      m_min = vrp_val_min (type, true);
+      m_max = vrp_val_max (type, true);
+    }
+  else
+    m_min = m_max = NULL;
 }
 
 void
-value_range::set_varying ()
+value_range::set_varying (tree type)
 {
-  set (VR_VARYING, NULL, NULL, NULL);
+  value_range_base::set_varying (type);
+  equiv_clear ();
 }
 
 /* Return TRUE if it is possible that range contains VAL.  */
@@ -338,21 +362,29 @@ value_range_base::singleton_p (tree *result) const
 tree
 value_range_base::type () const
 {
-  /* Types are only valid for VR_RANGE and VR_ANTI_RANGE, which are
-     known to have non-zero min/max.  */
-  gcc_assert (min ());
   return TREE_TYPE (min ());
 }
 
 void
 value_range_base::dump (FILE *file) const
 {
+  tree ttype;
+  if (m_min)
+    ttype = TREE_TYPE (m_min);
+  else
+    ttype = NULL;
+
   if (undefined_p ())
-    fprintf (file, "UNDEFINED");
+    {
+      if (ttype)
+	{
+	  print_generic_expr (file, ttype);
+	  fprintf (file, " ");
+	}
+      fprintf (file, "UNDEFINED");
+    }
   else if (m_kind == VR_RANGE || m_kind == VR_ANTI_RANGE)
     {
-      tree ttype = type ();
-
       print_generic_expr (file, ttype);
       fprintf (file, " ");
 
@@ -378,11 +410,24 @@ value_range_base::dump (FILE *file) const
       fprintf (file, "]");
     }
   else if (varying_p ())
-    fprintf (file, "VARYING");
+    {
+      if (ttype)
+	{
+	  print_generic_expr (file, ttype);
+	  fprintf (file, " ");
+	}
+      fprintf (file, "VARYING");
+    }
   else
     gcc_unreachable ();
 }
 
+void
+value_range_base::dump () const
+{
+  dump (stderr);
+}
+
 void
 value_range::dump (FILE *file) const
 {
@@ -406,6 +451,12 @@ value_range::dump (FILE *file) const
     }
 }
 
+void
+value_range::dump () const
+{
+  dump (stderr);
+}
+
 void
 dump_value_range (FILE *file, const value_range *vr)
 {
@@ -499,10 +550,18 @@ static assert_locus **asserts_for;
 /* Return the maximum value for TYPE.  */
 
 tree
-vrp_val_max (const_tree type)
+vrp_val_max (const_tree type, bool handle_pointers)
 {
   if (!INTEGRAL_TYPE_P (type))
-    return NULL_TREE;
+    {
+      if (POINTER_TYPE_P (type) && handle_pointers)
+	{
+	  wide_int max = wi::max_value (TYPE_PRECISION (type),
+					TYPE_SIGN (type));
+	  return wide_int_to_tree (const_cast<tree> (type), max);
+	}
+      return NULL_TREE;
+    }
 
   return TYPE_MAX_VALUE (type);
 }
@@ -510,23 +569,22 @@ vrp_val_max (const_tree type)
 /* Return the minimum value for TYPE.  */
 
 tree
-vrp_val_min (const_tree type)
+vrp_val_min (const_tree type, bool handle_pointers)
 {
   if (!INTEGRAL_TYPE_P (type))
-    return NULL_TREE;
+    {
+      if (POINTER_TYPE_P (type) && handle_pointers)
+	return build_zero_cst (const_cast<tree> (type));
+      return NULL_TREE;
+    }
 
   return TYPE_MIN_VALUE (type);
 }
 
-/* Return whether VAL is equal to the maximum value of its type.
-   We can't do a simple equality comparison with TYPE_MAX_VALUE because
-   C typedefs and Ada subtypes can produce types whose TYPE_MAX_VALUE
-   is not == to the integer constant with the same value in the type.  */
-
 bool
-vrp_val_is_max (const_tree val)
+vrp_val_is_max (const_tree val, bool handle_pointers)
 {
-  tree type_max = vrp_val_max (TREE_TYPE (val));
+  tree type_max = vrp_val_max (TREE_TYPE (val), handle_pointers);
   return (val == type_max
 	  || (type_max != NULL_TREE
 	      && operand_equal_p (val, type_max, 0)));
@@ -535,9 +593,9 @@ vrp_val_is_max (const_tree val)
 /* Return whether VAL is equal to the minimum value of its type.  */
 
 bool
-vrp_val_is_min (const_tree val)
+vrp_val_is_min (const_tree val, bool handle_pointers)
 {
-  tree type_min = vrp_val_min (TREE_TYPE (val));
+  tree type_min = vrp_val_min (TREE_TYPE (val), handle_pointers);
   return (val == type_min
 	  || (type_min != NULL_TREE
 	      && operand_equal_p (val, type_min, 0)));
@@ -629,15 +687,20 @@ void
 value_range_base::set_and_canonicalize (enum value_range_kind kind,
 					tree min, tree max)
 {
-  /* Use the canonical setters for VR_UNDEFINED and VR_VARYING.  */
   if (kind == VR_UNDEFINED)
     {
-      set_undefined ();
+      if (min)
+	set_undefined (TREE_TYPE (min));
+      else
+	set_undefined ();
       return;
     }
   else if (kind == VR_VARYING)
     {
-      set_varying ();
+      if (min)
+	set_varying (TREE_TYPE (min));
+      else
+	set_varying ();
       return;
     }
 
@@ -660,7 +723,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
 	 for VR_ANTI_RANGE empty range, so drop to varying as well.  */
       if (TYPE_PRECISION (TREE_TYPE (min)) == 1)
 	{
-	  set_varying ();
+	  set_varying (TREE_TYPE (min));
 	  return;
 	}
 
@@ -674,7 +737,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
 	 to varying in this case.  */
       if (tree_int_cst_lt (max, min))
 	{
-	  set_varying ();
+	  set_varying (TREE_TYPE (min));
 	  return;
 	}
 
@@ -696,7 +759,7 @@ value_range_base::set_and_canonicalize (enum value_range_kind kind,
 	{
 	  /* We cannot deal with empty ranges, drop to varying.
 	     ???  This could be VR_UNDEFINED instead.  */
-	  set_varying ();
+	  set_varying (type);
 	  return;
 	}
       else if (TYPE_PRECISION (TREE_TYPE (min)) == 1
@@ -1178,8 +1241,8 @@ ranges_from_anti_range (const value_range_base *ar,
 {
   tree type = ar->type ();
 
-  vr0->set_undefined ();
-  vr1->set_undefined ();
+  vr0->set_undefined (type);
+  vr1->set_undefined (type);
 
   /* As a future improvement, we could handle ~[0, A] as: [-INF, -1] U
      [A+1, +INF].  Not sure if this helps in practice, though.  */
@@ -1202,7 +1265,7 @@ ranges_from_anti_range (const value_range_base *ar,
   if (vr0->undefined_p ())
     {
       *vr0 = *vr1;
-      vr1->set_undefined ();
+      vr1->set_undefined (type);
     }
 
   return !vr0->undefined_p ();
@@ -1240,7 +1303,8 @@ static void
 extract_range_from_multiplicative_op (value_range_base *vr,
 				      enum tree_code code,
 				      const value_range_base *vr0,
-				      const value_range_base *vr1)
+				      const value_range_base *vr1,
+				      tree type)
 {
   gcc_assert (code == MULT_EXPR
 	      || code == TRUNC_DIV_EXPR
@@ -1250,13 +1314,31 @@ extract_range_from_multiplicative_op (value_range_base *vr,
 	      || code == ROUND_DIV_EXPR
 	      || code == RSHIFT_EXPR
 	      || code == LSHIFT_EXPR);
-  gcc_assert (vr0->kind () == VR_RANGE
-	      && vr0->kind () == vr1->kind ());
+  if (!range_int_cst_p (vr1))
+    {
+      vr->set_varying (type);
+      return;
+    }
+
+  /* Even if vr0 is VARYING or otherwise not usable, we can derive
+     useful ranges just from the shift count.  E.g.
+     x >> 63 for signed 64-bit x is always [-1, 0].  */
+  value_range_base tem = vr0->normalize_symbolics (type);
+  tree vr0_min, vr0_max;
+  if (tem.kind () == VR_RANGE)
+    {
+      vr0_min = tem.min ();
+      vr0_max = tem.max ();
+    }
+  else
+    {
+      vr0_min = vrp_val_min (type);
+      vr0_max = vrp_val_max (type);
+    }
 
-  tree type = vr0->type ();
   wide_int res_lb, res_ub;
-  wide_int vr0_lb = wi::to_wide (vr0->min ());
-  wide_int vr0_ub = wi::to_wide (vr0->max ());
+  wide_int vr0_lb = wi::to_wide (vr0_min);
+  wide_int vr0_ub = wi::to_wide (vr0_max);
   wide_int vr1_lb = wi::to_wide (vr1->min ());
   wide_int vr1_ub = wi::to_wide (vr1->max ());
   bool overflow_undefined = TYPE_OVERFLOW_UNDEFINED (type);
@@ -1270,7 +1352,7 @@ extract_range_from_multiplicative_op (value_range_base *vr,
 			      wide_int_to_tree (type, res_lb),
 			      wide_int_to_tree (type, res_ub));
   else
-    vr->set_varying ();
+    vr->set_varying (type);
 }
 
 /* If BOUND will include a symbolic bound, adjust it accordingly,
@@ -1479,7 +1561,7 @@ extract_range_from_binary_expr (value_range_base *vr,
   if (!INTEGRAL_TYPE_P (expr_type)
       && !POINTER_TYPE_P (expr_type))
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -1503,14 +1585,14 @@ extract_range_from_binary_expr (value_range_base *vr,
       && code != BIT_IOR_EXPR
       && code != BIT_XOR_EXPR)
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
   /* If both ranges are UNDEFINED, so is the result.  */
   if (vr0.undefined_p () && vr1.undefined_p ())
     {
-      vr->set_undefined ();
+      vr->set_undefined (expr_type);
       return;
     }
   /* If one of the ranges is UNDEFINED drop it to VARYING for the following
@@ -1518,9 +1600,9 @@ extract_range_from_binary_expr (value_range_base *vr,
      have UNDEFINED result for all or some value-ranges of the not UNDEFINED
      operand.  */
   else if (vr0.undefined_p ())
-    vr0.set_varying ();
+    vr0.set_varying (expr_type);
   else if (vr1.undefined_p ())
-    vr1.set_varying ();
+    vr1.set_varying (expr_type);
 
   /* We get imprecise results from ranges_from_anti_range when
      code is EXACT_DIV_EXPR.  We could mask out bits in the resulting
@@ -1592,7 +1674,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	  || vr0.symbolic_p ()
 	  || vr1.symbolic_p ()))
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -1610,7 +1692,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	  else if (vr0.zero_p () && vr1.zero_p ())
 	    vr->set_zero (expr_type);
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	}
       else if (code == POINTER_PLUS_EXPR)
 	{
@@ -1639,7 +1721,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	  else if (vr0.zero_p () && vr1.zero_p ())
 	    vr->set_zero (expr_type);
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	}
       else if (code == BIT_AND_EXPR)
 	{
@@ -1650,10 +1732,10 @@ extract_range_from_binary_expr (value_range_base *vr,
 	  else if (vr0.zero_p () || vr1.zero_p ())
 	    vr->set_zero (expr_type);
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	}
       else
-	vr->set_varying ();
+	vr->set_varying (expr_type);
 
       return;
     }
@@ -1720,7 +1802,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	  if (((bool)min_ovf && sym_min_op0 != sym_min_op1)
 	      || ((bool)max_ovf && sym_max_op0 != sym_max_op1))
 	    {
-	      vr->set_varying ();
+	      vr->set_varying (expr_type);
 	      return;
 	    }
 
@@ -1731,7 +1813,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 					 wmin, wmax, min_ovf, max_ovf);
 	  if (type == VR_VARYING)
 	    {
-	      vr->set_varying ();
+	      vr->set_varying (expr_type);
 	      return;
 	    }
 
@@ -1757,7 +1839,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	     a single range or anti-range as the above is
 		 [-INF+1, +INF(OVF)] intersected with ~[5, 5]
 	     but one could use a scheme similar to equivalences for this. */
-	  vr->set_varying ();
+	  vr->set_varying (expr_type);
 	  return;
 	}
     }
@@ -1774,7 +1856,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
 		 wide_int_to_tree (expr_type, wmax));
       else
-	vr->set_varying ();
+	vr->set_varying (expr_type);
       return;
     }
   else if (code == MULT_EXPR)
@@ -1782,10 +1864,10 @@ extract_range_from_binary_expr (value_range_base *vr,
       if (!range_int_cst_p (&vr0)
 	  || !range_int_cst_p (&vr1))
 	{
-	  vr->set_varying ();
+	  vr->set_varying (expr_type);
 	  return;
 	}
-      extract_range_from_multiplicative_op (vr, code, &vr0, &vr1);
+      extract_range_from_multiplicative_op (vr, code, &vr0, &vr1, expr_type);
       return;
     }
   else if (code == RSHIFT_EXPR
@@ -1800,13 +1882,8 @@ extract_range_from_binary_expr (value_range_base *vr,
 	{
 	  if (code == RSHIFT_EXPR)
 	    {
-	      /* Even if vr0 is VARYING or otherwise not usable, we can derive
-		 useful ranges just from the shift count.  E.g.
-		 x >> 63 for signed 64-bit x is always [-1, 0].  */
-	      if (vr0.kind () != VR_RANGE || vr0.symbolic_p ())
-		vr0.set (VR_RANGE, vrp_val_min (expr_type),
-			 vrp_val_max (expr_type));
-	      extract_range_from_multiplicative_op (vr, code, &vr0, &vr1);
+	      extract_range_from_multiplicative_op (vr, code, &vr0, &vr1,
+						    expr_type);
 	      return;
 	    }
 	  else if (code == LSHIFT_EXPR
@@ -1827,7 +1904,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 		}
 	    }
 	}
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
   else if (code == TRUNC_DIV_EXPR
@@ -1843,7 +1920,7 @@ extract_range_from_binary_expr (value_range_base *vr,
       /* Special case explicit division by zero as undefined.  */
       if (vr1.zero_p ())
 	{
-	  vr->set_undefined ();
+	  vr->set_undefined (expr_type);
 	  return;
 	}
 
@@ -1864,7 +1941,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 			       TYPE_OVERFLOW_UNDEFINED (expr_type),
 			       extra_range_p, extra_min, extra_max))
 	{
-	  vr->set_varying ();
+	  vr->set_varying (expr_type);
 	  return;
 	}
       vr->set (VR_RANGE, wide_int_to_tree (expr_type, wmin),
@@ -1882,7 +1959,7 @@ extract_range_from_binary_expr (value_range_base *vr,
     {
       if (vr1.zero_p ())
 	{
-	  vr->set_undefined ();
+	  vr->set_undefined (expr_type);
 	  return;
 	}
       wide_int wmin, wmax, tmp;
@@ -1923,7 +2000,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	      vr->set (VR_RANGE, min, max);
 	    }
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	  return;
 	}
       else if (code == BIT_IOR_EXPR)
@@ -1941,7 +2018,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	      vr->set (VR_RANGE, min, max);
 	    }
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	  return;
 	}
       else if (code == BIT_XOR_EXPR)
@@ -1957,7 +2034,7 @@ extract_range_from_binary_expr (value_range_base *vr,
 	      vr->set (VR_RANGE, min, max);
 	    }
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (expr_type);
 	  return;
 	}
     }
@@ -1971,7 +2048,7 @@ extract_range_from_binary_expr (value_range_base *vr,
       || max == NULL_TREE
       || TREE_OVERFLOW_P (max))
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -1980,7 +2057,7 @@ extract_range_from_binary_expr (value_range_base *vr,
      Note that we do accept [-INF, -INF] and [+INF, +INF].  */
   if (vrp_val_is_min (min) && vrp_val_is_max (max))
     {
-      vr->set_varying ();
+      vr->set_varying (expr_type);
       return;
     }
 
@@ -1990,7 +2067,7 @@ extract_range_from_binary_expr (value_range_base *vr,
       /* 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.  */
-      vr->set_varying ();
+      vr->set_varying (expr_type);
     }
   else
     vr->set (type, min, max);
@@ -2016,14 +2093,14 @@ extract_range_from_unary_expr (value_range_base *vr,
       || !(INTEGRAL_TYPE_P (type)
 	   || POINTER_TYPE_P (type)))
     {
-      vr->set_varying ();
+      vr->set_varying (type);
       return;
     }
 
   /* If VR0 is UNDEFINED, so is the result.  */
   if (vr0.undefined_p ())
     {
-      vr->set_undefined ();
+      vr->set_undefined (type);
       return;
     }
 
@@ -2088,7 +2165,7 @@ extract_range_from_unary_expr (value_range_base *vr,
 	  else if (vr0.zero_p ())
 	    vr->set_zero (type);
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (type);
 	  return;
 	}
 
@@ -2123,7 +2200,7 @@ extract_range_from_unary_expr (value_range_base *vr,
 	  vr->set_and_canonicalize (VR_RANGE, min, max);
 	}
       else
-	vr->set_varying ();
+	vr->set_varying (outer_type);
       return;
     }
   else if (code == ABS_EXPR)
@@ -2136,7 +2213,7 @@ extract_range_from_unary_expr (value_range_base *vr,
 	vr->set (VR_RANGE, wide_int_to_tree (type, wmin),
 		 wide_int_to_tree (type, wmax));
       else
-	vr->set_varying ();
+	vr->set_varying (type);
       return;
     }
   else if (code == ABSU_EXPR)
@@ -2151,7 +2228,7 @@ extract_range_from_unary_expr (value_range_base *vr,
     }
 
   /* For unhandled operations fall back to varying.  */
-  vr->set_varying ();
+  vr->set_varying (type);
   return;
 }
 
@@ -5147,7 +5224,7 @@ vrp_prop::vrp_initialize ()
 	  if (!stmt_interesting_for_vrp (phi))
 	    {
 	      tree lhs = PHI_RESULT (phi);
-	      get_value_range (lhs)->set_varying ();
+	      get_value_range (lhs)->set_varying (TREE_TYPE (lhs));
 	      prop_set_simulate_again (phi, false);
 	    }
 	  else
@@ -5342,7 +5419,7 @@ vrp_prop::visit_stmt (gimple *stmt, edge *taken_edge_p, tree *output_p)
 	    use_operand_p use_p;
 	    enum ssa_prop_result res = SSA_PROP_VARYING;
 
-	    get_value_range (lhs)->set_varying ();
+	    get_value_range (lhs)->set_varying (TREE_TYPE (lhs));
 
 	    FOR_EACH_IMM_USE_FAST (use_p, iter, lhs)
 	      {
@@ -6132,7 +6209,12 @@ value_range_base::union_helper (const value_range_base *vr0,
 
   /* Work on a temporary so we can still use vr0 when union returns varying.  */
   value_range_base tem;
-  tem.set_and_canonicalize (vr0type, vr0min, vr0max);
+  if (vr0type == VR_UNDEFINED)
+    tem.set_undefined (TREE_TYPE (vr0->min ()));
+  else if (vr0type == VR_VARYING)
+    tem.set_varying (TREE_TYPE (vr0->min ()));
+  else
+    tem.set_and_canonicalize (vr0type, vr0min, vr0max);
 
   /* Failed to find an efficient meet.  Before giving up and setting
      the result to VARYING, see if we can at least derive a useful
@@ -6212,6 +6294,49 @@ value_range::union_ (const value_range *other)
     }
 }
 
+/* Normalize symbolics into constants.  */
+
+value_range_base
+value_range_base::normalize_symbolics (tree ttype) const
+{
+  if (varying_p () || undefined_p ())
+    return *this;
+  bool min_symbolic = !is_gimple_min_invariant (min ());
+  bool max_symbolic = !is_gimple_min_invariant (max ());
+  if (!min_symbolic && !max_symbolic)
+    return *this;
+
+  // [SYM, SYM] -> VARYING
+  if (min_symbolic && max_symbolic)
+    return value_range_base (ttype);
+  if (kind () == VR_RANGE)
+    {
+      // [SYM, NUM] -> [-MIN, NUM]
+      if (min_symbolic)
+	return value_range_base (VR_RANGE, vrp_val_min (ttype), max ());
+      // [NUM, SYM] -> [NUM, +MAX]
+      return value_range_base (VR_RANGE, min (), vrp_val_max (ttype));
+    }
+  gcc_assert (kind () == VR_ANTI_RANGE);
+  // ~[SYM, NUM] -> [NUM + 1, +MAX]
+  if (min_symbolic)
+    {
+      if (!vrp_val_is_max (max ()))
+	{
+	  tree n = wide_int_to_tree (ttype, wi::to_wide (max ()) + 1);
+	  return value_range_base (VR_RANGE, n, vrp_val_max (ttype));
+	}
+      return value_range_base (ttype);
+    }
+  // ~[NUM, SYM] -> [-MIN, NUM - 1]
+  if (!vrp_val_is_min (min ()))
+    {
+      tree n = wide_int_to_tree (ttype, wi::to_wide (min ()) - 1);
+      return value_range_base (VR_RANGE, vrp_val_min (ttype), n);
+    }
+  return value_range_base (ttype);
+}
+
 /* Visit all arguments for PHI node PHI that flow through executable
    edges.  If a valid value range can be derived from all the incoming
    value ranges, set a new range for the LHS of PHI.  */
@@ -6885,7 +7010,7 @@ determine_value_range_1 (value_range_base *vr, tree expr)
 	vr->set (kind, wide_int_to_tree (TREE_TYPE (expr), min),
 		 wide_int_to_tree (TREE_TYPE (expr), max));
       else
-	vr->set_varying ();
+	vr->set_varying (TREE_TYPE (expr));
     }
 }
 
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index 4ec974f5fdb..b1ddf484aa7 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -43,6 +43,7 @@ class GTY((for_user)) value_range_base
 public:
   value_range_base ();
   value_range_base (value_range_kind, tree, tree);
+  value_range_base (tree type);
 
   void set (value_range_kind, tree, tree);
   void set (tree);
@@ -58,8 +59,8 @@ public:
   bool constant_p () const;
   bool undefined_p () const;
   bool varying_p () const;
-  void set_varying ();
-  void set_undefined ();
+  void set_varying (tree = NULL);
+  void set_undefined (tree = NULL);
 
   void union_ (const value_range_base *);
   void intersect (const value_range_base *);
@@ -76,6 +77,10 @@ public:
   bool nonzero_p () const;
   bool singleton_p (tree *result = NULL) const;
   void dump (FILE *) const;
+  void dump () const;
+
+  static bool supports_type_p (tree);
+  value_range_base normalize_symbolics (tree) const;
 
 protected:
   void check ();
@@ -133,8 +138,8 @@ class GTY((user)) value_range : public value_range_base
   bool equal_p (const value_range &, bool ignore_equivs) const;
 
   /* Types of value ranges.  */
-  void set_undefined ();
-  void set_varying ();
+  void set_undefined (tree = NULL);
+  void set_varying (tree = NULL);
 
   /* Equivalence bitmap methods.  */
   bitmap equiv () const;
@@ -145,6 +150,7 @@ class GTY((user)) value_range : public value_range_base
   void deep_copy (const value_range *);
   void set_and_canonicalize (enum value_range_kind, tree, tree, bitmap = NULL);
   void dump (FILE *) const;
+  void dump () const;
 
  private:
   /* Deep-copies bitmap argument.  */
@@ -254,6 +260,17 @@ struct assert_info
   tree expr;
 };
 
+// Return true if TYPE is a valid type for value_range to operate on.
+// Otherwise return FALSE.
+
+inline bool
+value_range_base::supports_type_p (tree type)
+{
+  if (type && (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)))
+    return type;
+  return NULL;
+}
+
 extern void register_edge_assert_for (tree, edge, enum tree_code,
 				      tree, tree, vec<assert_info> &);
 extern bool stmt_interesting_for_vrp (gimple *);
@@ -267,11 +284,11 @@ extern bool range_int_cst_singleton_p (const value_range_base *);
 extern int compare_values (tree, tree);
 extern int compare_values_warnv (tree, tree, bool *);
 extern int operand_less_p (tree, tree);
-extern bool vrp_val_is_min (const_tree);
-extern bool vrp_val_is_max (const_tree);
+extern bool vrp_val_is_min (const_tree, bool handle_pointers = false);
+extern bool vrp_val_is_max (const_tree, bool handle_pointers = false);
 
-extern tree vrp_val_min (const_tree);
-extern tree vrp_val_max (const_tree);
+extern tree vrp_val_min (const_tree, bool handle_pointers = false);
+extern tree vrp_val_max (const_tree, bool handle_pointers = false);
 
 extern void extract_range_from_unary_expr (value_range_base *vr,
 					   enum tree_code code,
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 3f20c1a6fe8..f0efb6eca3d 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "attribs.h"
 #include "vr-values.h"
 #include "cfghooks.h"
+#include "wide-int-range.h"
 
 /* Set value range VR to a non-negative range of type TYPE.  */
 
@@ -64,7 +65,7 @@ static inline void
 set_value_range_to_truthvalue (value_range *vr, tree type)
 {
   if (TYPE_PRECISION (type) == 1)
-    vr->set_varying ();
+    vr->set_varying (type);
   else
     vr->update (VR_RANGE, build_int_cst (type, 0), build_int_cst (type, 1));
 }
@@ -126,10 +127,10 @@ vr_values::get_value_range (const_tree var)
 	    {
 	      get_range_info (var, *vr);
 	      if (vr->undefined_p ())
-		vr->set_varying ();
+		vr->set_varying (TREE_TYPE (sym));
 	    }
 	  else
-	    vr->set_varying ();
+	    vr->set_varying (TREE_TYPE (sym));
 	}
       else if (TREE_CODE (sym) == RESULT_DECL
 	       && DECL_BY_REFERENCE (sym))
@@ -198,13 +199,13 @@ vr_values::update_value_range (const_tree var, value_range *new_vr)
 	 called, if we are anyway, keep it VARYING.  */
       if (old_vr->varying_p ())
 	{
-	  new_vr->set_varying ();
+	  new_vr->set_varying (new_vr->type ());
 	  is_new = false;
 	}
       else if (new_vr->undefined_p ())
 	{
-	  old_vr->set_varying ();
-	  new_vr->set_varying ();
+	  old_vr->set_varying (TREE_TYPE (var));
+	  new_vr->set_varying (TREE_TYPE (var));
 	  return true;
 	}
       else
@@ -435,7 +436,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
   if ((POINTER_TYPE_P (type) && cond_code != NE_EXPR && cond_code != EQ_EXPR)
       || limit == var)
     {
-      vr_p->set_varying ();
+      vr_p->set_varying (type);
       return;
     }
 
@@ -595,7 +596,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
 	 all should be optimized away above us.  */
       if (cond_code == LT_EXPR
 	  && compare_values (max, min) == 0)
-	vr_p->set_varying ();
+	vr_p->set_varying (TREE_TYPE (min));
       else
 	{
 	  /* For LT_EXPR, we create the range [MIN, MAX - 1].  */
@@ -635,7 +636,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
 	 all should be optimized away above us.  */
       if (cond_code == GT_EXPR
 	  && compare_values (min, max) == 0)
-	vr_p->set_varying ();
+	vr_p->set_varying (TREE_TYPE (min));
       else
 	{
 	  /* For GT_EXPR, we create the range [MIN + 1, MAX].  */
@@ -743,14 +744,14 @@ vr_values::extract_range_from_binary_expr (value_range *vr,
   else if (is_gimple_min_invariant (op0))
     vr0.set (op0);
   else
-    vr0.set_varying ();
+    vr0.set_varying (TREE_TYPE (op0));
 
   if (TREE_CODE (op1) == SSA_NAME)
     vr1 = *(get_value_range (op1));
   else if (is_gimple_min_invariant (op1))
     vr1.set (op1);
   else
-    vr1.set_varying ();
+    vr1.set_varying (TREE_TYPE (op1));
 
   /* If one argument is varying, we can sometimes still deduce a
      range for the output: any + [3, +INF] is in [MIN+3, +INF].  */
@@ -891,7 +892,7 @@ vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code,
   else if (is_gimple_min_invariant (op0))
     vr0.set (op0);
   else
-    vr0.set_varying ();
+    vr0.set_varying (type);
 
   ::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
 }
@@ -913,7 +914,7 @@ vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
   else if (is_gimple_min_invariant (op0))
     tem0.set (op0);
   else
-    tem0.set_varying ();
+    tem0.set_varying (TREE_TYPE (op0));
 
   tree op1 = gimple_assign_rhs3 (stmt);
   value_range tem1;
@@ -923,7 +924,7 @@ vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
   else if (is_gimple_min_invariant (op1))
     tem1.set (op1);
   else
-    tem1.set_varying ();
+    tem1.set_varying (TREE_TYPE (op1));
 
   /* The resulting value range is the union of the operand ranges */
   vr->deep_copy (vr0);
@@ -975,14 +976,14 @@ vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
   else if (TREE_CODE (op0) == INTEGER_CST)
     vr0.set (op0);
   else
-    vr0.set_varying ();
+    vr0.set_varying (TREE_TYPE (op0));
 
   if (TREE_CODE (op1) == SSA_NAME)
     vr1 = *get_value_range (op1);
   else if (TREE_CODE (op1) == INTEGER_CST)
     vr1.set (op1);
   else
-    vr1.set_varying ();
+    vr1.set_varying (TREE_TYPE (op1));
 
   tree vr0min = vr0.min (), vr0max = vr0.max ();
   tree vr1min = vr1.min (), vr1max = vr1.max ();
@@ -1310,7 +1311,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
 	  if (vr->kind () == VR_RANGE
 	      && (vr->min () == vr->max ()
 		  || operand_equal_p (vr->min (), vr->max (), 0)))
-	    vr->set_varying ();
+	    vr->set_varying (vr->type ());
 	  return;
 	}
     }
@@ -1366,7 +1367,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
 			vr->set (build_int_cst (type, ovf));
 		      else if (TYPE_PRECISION (type) == 1
 			       && !TYPE_UNSIGNED (type))
-			vr->set_varying ();
+			vr->set_varying (type);
 		      else
 			vr->set (VR_RANGE, build_int_cst (type, 0),
 				 build_int_cst (type, 1));
@@ -1411,7 +1412,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
       vr->equiv_clear ();
     }
   else
-    vr->set_varying ();
+    vr->set_varying (type);
 }
 
 
@@ -1447,7 +1448,7 @@ vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt)
 	   && is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
     vr->set (gimple_assign_rhs1 (stmt));
   else
-    vr->set_varying ();
+    vr->set_varying (TREE_TYPE (gimple_assign_lhs (stmt)));
 
   if (vr->varying_p ())
     extract_range_basic (vr, stmt);
@@ -2856,7 +2857,7 @@ vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
 		      vr_arg_tem.set (vr_arg_->kind (), vr_arg_->min (),
 				      vr_arg_->max (), NULL);
 		      if (vr_arg_tem.symbolic_p ())
-			vr_arg_tem.set_varying ();
+			vr_arg_tem.set_varying (TREE_TYPE (arg));
 		    }
 		  else
 		    vr_arg = vr_arg_;
@@ -2978,7 +2979,7 @@ vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
   goto update_range;
 
 varying:
-  vr_result->set_varying ();
+  vr_result->set_varying (TREE_TYPE (lhs));
 
 scev_check:
   /* If this is a loop PHI node SCEV may known more about its value-range.
@@ -2999,7 +3000,7 @@ infinite_check:
 	   || compare_values (vr_result->min (), vr_result->max ()) > 0))
     ;
   else
-    vr_result->set_varying ();
+    vr_result->set_varying (TREE_TYPE (lhs));
 
   /* If the new range is different than the previous value, keep
      iterating.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]