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: types for VR_VARYING




On 8/12/19 7:46 PM, Jeff Law wrote:
On 8/12/19 12:43 PM, Aldy Hernandez wrote:
This is a fresh re-post of:

https://gcc.gnu.org/ml/gcc-patches/2019-07/msg00006.html

Andrew gave me some feedback a week ago, and I obviously don't remember
what it was because I was about to leave on PTO.  However, I do remember
I addressed his concerns before getting drunk on rum in tropical islands.
FWIW found a great coffee infused rum while in Kauai last week.  I'm not
a coffee fan, but it was wonderful.  The one bottle we brought back
isn't going to last until Cauldron and I don't think I can get a special
order filled before I leave :(

You must bring some to Cauldron before we believe you. :)


Their more traditional rums were good as well.  Koloa Rum.  See if you
can get it locally :-)



This patch adds MIN/MAX values for VR_VARYING.  As was discussed
earlier, we are only changing VR_VARYING, not VR_UNDEFINED as was the
original plan.

As I mentioned earlier, I am tired of re-doing ChangeLogs, so I'll whip
up the changelog when the review starts.
ACK.

ChangeLog entries included in attached patch.




@@ -150,12 +166,11 @@ vr_values::set_defs_to_varying (gimple *stmt)
    ssa_op_iter i;
    tree def;
    FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_DEF)
-    {
-      value_range *vr = get_value_range (def);
-      /* Avoid writing to vr_const_varying get_value_range may return.  */
-      if (!vr->varying_p ())
-	vr->set_varying ();
-    }
+    if (value_range_base::supports_type_p (TREE_TYPE (def)))
+      {
+	value_range *vr = get_value_range (def);
+	vr->set_varying (TREE_TYPE (def));
+      }
  }
Is the supports_type_p stuff there to placate the calls from ipa-cp?  I
can live with it in the short term, but it really feels like there
should be something in the ipa-cp client that avoids this silliness.

I am not happy with this either, but there are various places where statements that are !stmt_interesting_for_vrp() are still setting a range of VARYING, which is then being ignored at a later time.

For example, vrp_initialize:

	  if (!stmt_interesting_for_vrp (phi))
	    {
	      tree lhs = PHI_RESULT (phi);
	      set_def_to_varying (lhs);
	      prop_set_simulate_again (phi, false);
	    }

Also in evrp_range_analyzer::record_ranges_from_stmt(), where we if the statement is interesting for VRP but extract_range_from_stmt() does not produce a useful range, we also set a varying for a range we will never use. Similarly for a statement that is not interesting in this hunk.

Then there is vrp_prop::visit_stmt() where we also set VARYING for types that VRP will never handle:

      case IFN_ADD_OVERFLOW:
      case IFN_SUB_OVERFLOW:
      case IFN_MUL_OVERFLOW:
      case IFN_ATOMIC_COMPARE_EXCHANGE:
	/* These internal calls return _Complex integer type,
	   which VRP does not track, but the immediate uses
	   thereof might be interesting.  */
	if (lhs && TREE_CODE (lhs) == SSA_NAME)
	  {
	    imm_use_iterator iter;
	    use_operand_p use_p;
	    enum ssa_prop_result res = SSA_PROP_VARYING;

	    set_def_to_varying (lhs);

I've adjusted the patch so that set_def_to_varying will set the range to VR_UNDEFINED if !supports_type_p. This is a fail safe, as we can't really do anything with a nonsensical range. I just don't want to leave the range in an indeterminate state.



/* Update the value range and equivalence set for variable VAR to

@@ -1920,7 +1935,7 @@ vr_values::dump_all_value_ranges (FILE *file)
  vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
  {
    values_propagated = false;
-  num_vr_values = num_ssa_names;
+  num_vr_values = num_ssa_names + num_ssa_names / 10;
    vr_value = XCNEWVEC (value_range *, num_vr_values);
    vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
    bitmap_obstack_initialize (&vrp_equiv_obstack);
My recollection was someone (Richi) proposed 2X for the initial
allocation which should ensure that in all but the most pathological
cases that we never trigger a reallocation.  In terms of "wasted" space,
it shouldn't matter in practice.

So if you could check the old thread and verify that Richi recommended
the 2X initial allocation and if so, make that minor update.

Yes, it was 2X.

I noticed that Richi made some changes to the lattice handling for VARYING while the discussion was on-going. I missed these, and had failed to adapt the patch for it. I would appreciate a final review of the attached patch, especially the vr-values.c changes, which I have modified to play nice with current trunk.

I also noticed that Andrew's patch was setting num_vr_values to num_ssa_names + num_ssa_names / 10. I think he meant num_vr_values + num_vr_values / 10. Please verify the current incantation makes sense.

Tested on x86-64 Linux.

OK for trunk?

Aldy
commit 4c21b0f667176933f67469372da7459b8cf0ef71
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Mon Jul 22 10:04:43 2019 +0200

    Add type to VR_VARYING.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3fa864624c9..911bda1b79c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,51 @@
+2019-08-13  Aldy Hernandez  <aldyh@redhat.com>
+
+	* gimple-ssa-evrp-analyze.c (record_ranges_from_phis): Skip PHIs
+	for which we can't represent a range.
+	* ipa-cp.c (ipcp_vr_lattice::set_to_bottom): Pass type to
+	set_varying.
+	* tree-ssa-threadedge.c (record_temporary_equivalences_from_phis):
+	Set VR_UNDEFINED if type is not supported.
+	* tree-ssanames.c (get_range_info): Pass type to set_varying.
+	* tree-vrp.c (value_range_base::check): Assert that a varying has
+	min/max set.
+	(value_range_base::equal_p): Early bail for undefines.
+	(value_range_base::set_varying): Accept a type.
+	(value_range::set_varying): Same.
+	(value_range_base::type): VARYING can have a type, while UNDEFINE
+	is typeless.
+	(value_range_base::dump): Print type for VARYING nodes.
+	(value_range_base::set): Add type to VARYING.
+	(extract_range_from_multiplicative_op): Pass type to set_varying.
+	(extract_range_from_binary_expr): Same.
+	(value_range_base::intersect_helper): Same.
+	(value_range_base::union_helper): Same.
+	(value_range_base::normalize_symbolics): Same.
+	(determine_value_range_1): Same.
+	* tree-vrp.h (class value_range_base): Add type to set_varying.
+	Add prototype for dump(void).
+	Add prototype for supports_type_p.
+	(class value_range): Add type to set_varying.
+	Add prototype for dump(void).
+	* vr-values.c (set_value_range_to_truthvalue): Pass type to
+	set_varying.
+	(vr_values::get_lattice_entry): Set varying even if propagation
+	finished.
+	Pass type to set_varying.
+	(vr_values::get_value_range): Remove vr_const_varying.
+	Reallocate the lattice if needed.
+	(vr_values::update_value_range): Pass type to set_varying.
+	(vr_values::extract_range_for_var_from_comparison_expr): Same.
+	(vr_values::extract_range_from_binary_expr): Same.
+	(vr_values::extract_range_from_unary_expr): Same.
+	(vr_values::extract_range_from_cond_expr): Same.
+	(vr_values::check_for_binary_op_overflow): Same.
+	(vr_values::extract_range_basic): Same.
+	(vr_values::extract_range_from_assignment): Same.
+	(vr_values::vr_values): Increase size of num_vr_values.
+	(vr_values::extract_range_from_phi_node): Pass type to
+	set_varying.
+
 2019-08-13  Aldy Hernandez  <aldyh@redhat.com>
 
 	* tree-vrp.c (value_range_base::set): Merge in code from
diff --git a/gcc/gimple-ssa-evrp-analyze.c b/gcc/gimple-ssa-evrp-analyze.c
index 1c4fc8d8682..68f317f9930 100644
--- a/gcc/gimple-ssa-evrp-analyze.c
+++ b/gcc/gimple-ssa-evrp-analyze.c
@@ -254,13 +254,18 @@ 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)
 	vr_values->extract_range_from_phi_node (phi, &vr_result);
       else
 	{
-	  vr_result.set_varying ();
+	  vr_result.set_varying (TREE_TYPE (lhs));
 	  /* When we have an unvisited executable predecessor we can't
 	     use PHI arg ranges which may be still UNDEFINED but have
 	     to use VARYING for them.  But we can still resort to
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index b20a6d08794..32f7cb699f7 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -977,7 +977,12 @@ ipcp_vr_lattice::set_to_bottom ()
 {
   if (m_vr.varying_p ())
     return false;
-  m_vr.set_varying ();
+  /* ?? We create all sorts of VARYING ranges for floats, structures,
+     and other types which we cannot handle as ranges.  We should
+     probably avoid handling them throughout the pass, but it's easier
+     to create a sensible VARYING here and let the lattice
+     propagate.  */
+  m_vr.set_varying (integer_type_node);
   return true;
 }
 
diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c
index 39ea22f0554..663dd6e2398 100644
--- a/gcc/tree-ssa-threadedge.c
+++ b/gcc/tree-ssa-threadedge.c
@@ -182,8 +182,10 @@ record_temporary_equivalences_from_phis (edge e,
 	    new_vr->deep_copy (vr_values->get_value_range (src));
 	  else if (TREE_CODE (src) == INTEGER_CST)
 	    new_vr->set (src);
+	  else if (value_range_base::supports_type_p (TREE_TYPE (src)))
+	    new_vr->set_varying (TREE_TYPE (src));
 	  else
-	    new_vr->set_varying ();
+	    new_vr->set_undefined ();
 
 	  /* 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..3911db9c26e 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 ();
   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 77e7594eee5..60c2c37f533 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -186,9 +186,11 @@ value_range_base::check ()
 	break;
       }
     case VR_UNDEFINED:
-    case VR_VARYING:
       gcc_assert (!min () && !max ());
       break;
+    case VR_VARYING:
+      gcc_assert (m_min && m_max);
+      break;
     default:
       gcc_unreachable ();
     }
@@ -214,6 +216,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));
@@ -269,16 +275,19 @@ value_range::set_undefined ()
 }
 
 void
-value_range_base::set_varying ()
+value_range_base::set_varying (tree type)
 {
+  gcc_assert (supports_type_p (type));
   m_kind = VR_VARYING;
-  m_min = m_max = NULL;
+  m_min = vrp_val_min (type, true);
+  m_max = vrp_val_max (type, true);
 }
 
 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.  */
@@ -355,9 +364,7 @@ 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 ());
+  gcc_assert (m_min || undefined_p ());
   return TREE_TYPE (min ());
 }
 
@@ -395,11 +402,20 @@ value_range_base::dump (FILE *file) const
       fprintf (file, "]");
     }
   else if (varying_p ())
-    fprintf (file, "VARYING");
+    {
+      print_generic_expr (file, type ());
+      fprintf (file, " VARYING");
+    }
   else
     gcc_unreachable ();
 }
 
+void
+value_range_base::dump () const
+{
+  dump (stderr);
+}
+
 void
 value_range::dump (FILE *file) const
 {
@@ -423,6 +439,12 @@ value_range::dump (FILE *file) const
     }
 }
 
+void
+value_range::dump () const
+{
+  dump (stderr);
+}
+
 void
 dump_value_range (FILE *file, const value_range *vr)
 {
@@ -658,7 +680,10 @@ value_range_base::set (enum value_range_kind kind, tree min, tree max)
     }
   else if (kind == VR_VARYING)
     {
-      set_varying ();
+      gcc_assert (TREE_TYPE (min) == TREE_TYPE (max));
+      gcc_assert (vrp_val_min (TREE_TYPE (min), true));
+      gcc_assert (vrp_val_max (TREE_TYPE (max), true));
+      set_varying (TREE_TYPE (min));
       return;
     }
 
@@ -683,7 +708,7 @@ value_range_base::set (enum value_range_kind kind, tree min, tree max)
 	 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;
 	}
 
@@ -697,7 +722,7 @@ value_range_base::set (enum value_range_kind kind, tree min, tree max)
 	 to varying in this case.  */
       if (tree_int_cst_lt (max, min))
 	{
-	  set_varying ();
+	  set_varying (TREE_TYPE (min));
 	  return;
 	}
 
@@ -720,7 +745,7 @@ value_range_base::set (enum value_range_kind kind, tree min, tree max)
 	{
 	  /* 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
@@ -767,7 +792,7 @@ value_range_base::set (enum value_range_kind kind, tree min, tree max)
       && wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign)))
     {
       if (kind == VR_RANGE)
-	set_varying ();
+	set_varying (type);
       else if (kind == VR_ANTI_RANGE)
 	set_undefined ();
       else
@@ -1297,7 +1322,7 @@ extract_range_from_multiplicative_op (value_range_base *vr,
 	      || code == LSHIFT_EXPR);
   if (!range_int_cst_p (vr1))
     {
-      vr->set_varying ();
+      vr->set_varying (type);
       return;
     }
 
@@ -1332,7 +1357,7 @@ extract_range_from_multiplicative_op (value_range_base *vr,
     vr->set (VR_RANGE, 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,
@@ -1541,7 +1566,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;
     }
 
@@ -1565,7 +1590,7 @@ 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;
     }
 
@@ -1580,9 +1605,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
@@ -1654,7 +1679,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;
     }
 
@@ -1672,7 +1697,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)
 	{
@@ -1701,7 +1726,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)
 	{
@@ -1712,10 +1737,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;
     }
@@ -1793,7 +1818,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;
 	    }
 
@@ -1804,7 +1829,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;
 	    }
 
@@ -1830,7 +1855,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;
 	}
     }
@@ -1847,7 +1872,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)
@@ -1855,7 +1880,7 @@ 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, expr_type, &vr0, &vr1);
@@ -1895,7 +1920,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
@@ -1932,7 +1957,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),
@@ -1991,7 +2016,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)
@@ -2009,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;
 	}
       else if (code == BIT_XOR_EXPR)
@@ -2025,7 +2050,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;
 	}
     }
@@ -2039,7 +2064,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;
     }
 
@@ -2048,7 +2073,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;
     }
 
@@ -2058,7 +2083,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);
@@ -2084,7 +2109,7 @@ 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;
     }
 
@@ -2156,7 +2181,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;
 	}
 
@@ -2190,7 +2215,7 @@ extract_range_from_unary_expr (value_range_base *vr,
 	  vr->set (VR_RANGE, min, max);
 	}
       else
-	vr->set_varying ();
+	vr->set_varying (outer_type);
       return;
     }
   else if (code == ABS_EXPR)
@@ -2203,7 +2228,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)
@@ -2219,7 +2244,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;
 }
 
@@ -6100,7 +6125,12 @@ value_range_base::intersect_helper (const value_range_base *vr0,
      VR_RANGE can still be a VR_RANGE.  Work on a temporary so we can
      fall back to vr0 when this turns things to varying.  */
   value_range_base tem;
-  tem.set (vr0type, vr0min, vr0max);
+  if (vr0type == VR_UNDEFINED)
+    tem.set_undefined ();
+  else if (vr0type == VR_VARYING)
+    tem.set_varying (vr0->type ());
+  else
+    tem.set (vr0type, vr0min, vr0max);
   /* If that failed, use the saved original VR0.  */
   if (tem.varying_p ())
     return *vr0;
@@ -6205,7 +6235,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 (vr0type, vr0min, vr0max);
+  if (vr0type == VR_UNDEFINED)
+    tem.set_undefined ();
+  else if (vr0type == VR_VARYING)
+    tem.set_varying (vr0->type ());
+  else
+    tem.set (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
@@ -6302,7 +6337,7 @@ value_range_base::normalize_symbolics () const
   if (min_symbolic && max_symbolic)
     {
       value_range_base var;
-      var.set_varying ();
+      var.set_varying (ttype);
       return var;
     }
   if (kind () == VR_RANGE)
@@ -6323,7 +6358,7 @@ value_range_base::normalize_symbolics () const
 	  return value_range_base (VR_RANGE, n, vrp_val_max (ttype));
 	}
       value_range_base var;
-      var.set_varying ();
+      var.set_varying (ttype);
       return var;
     }
   // ~[NUM, SYM] -> [-MIN, NUM - 1]
@@ -6333,7 +6368,7 @@ value_range_base::normalize_symbolics () const
       return value_range_base (VR_RANGE, vrp_val_min (ttype), n);
     }
   value_range_base var;
-  var.set_varying ();
+  var.set_varying (ttype);
   return var;
 }
 
@@ -7010,7 +7045,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 b5830851fcb..c879a8c6df8 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -58,7 +58,7 @@ public:
   bool constant_p () const;
   bool undefined_p () const;
   bool varying_p () const;
-  void set_varying ();
+  void set_varying (tree type);
   void set_undefined ();
 
   void union_ (const value_range_base *);
@@ -75,7 +75,9 @@ 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 () const;
 
 protected:
@@ -135,7 +137,7 @@ class GTY((user)) value_range : public value_range_base
 
   /* Types of value ranges.  */
   void set_undefined ();
-  void set_varying ();
+  void set_varying (tree);
 
   /* Equivalence bitmap methods.  */
   bitmap equiv () const;
@@ -145,6 +147,7 @@ class GTY((user)) value_range : public value_range_base
   /* Misc methods.  */
   void deep_copy (const value_range *);
   void dump (FILE *) const;
+  void dump () const;
 
  private:
   /* Deep-copies bitmap argument.  */
@@ -254,6 +257,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 *);
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index a87cb672e36..0d71953a7da 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -64,7 +64,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));
 }
@@ -89,12 +89,22 @@ vr_values::get_lattice_entry (const_tree var)
   if (vr)
     return vr;
 
-  /* After propagation finished do not allocate new value-ranges.  */
-  if (values_propagated)
-    return NULL;
-
   /* Create a default value range.  */
   vr_value[ver] = vr = vrp_value_range_pool.allocate ();
+
+  if (!value_range_base::supports_type_p (TREE_TYPE (var)))
+    {
+      vr->set_undefined ();
+      return vr;
+    }
+
+  /* After propagation finished return varying.  */
+  if (values_propagated)
+    {
+      vr->set_varying (TREE_TYPE (var));
+      return vr;
+    }
+
   vr->set_undefined ();
 
   /* If VAR is a default definition of a parameter, the variable can
@@ -118,10 +128,10 @@ vr_values::get_lattice_entry (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))
@@ -142,15 +152,25 @@ vr_values::get_lattice_entry (const_tree var)
 const value_range *
 vr_values::get_value_range (const_tree var)
 {
-  static const value_range vr_const_varying (VR_VARYING, NULL, NULL);
-
   /* If we have no recorded ranges, then return NULL.  */
   if (!vr_value)
     return NULL;
 
   value_range *vr = get_lattice_entry (var);
+
+  /* Reallocate the lattice if needed.  */
   if (!vr)
-    return &vr_const_varying;
+    {
+      unsigned int old_sz = num_vr_values;
+      num_vr_values = num_vr_values + num_vr_values / 10;
+      vr_value = XRESIZEVEC (value_range *, vr_value, num_vr_values);
+      for ( ; old_sz < num_vr_values; old_sz++)
+        vr_value [old_sz] = NULL;
+
+      /* Now that the lattice has been resized, we should never fail.  */
+      vr = get_lattice_entry (var);
+      gcc_assert (vr);
+    }
 
   return vr;
 }
@@ -162,7 +182,19 @@ vr_values::set_def_to_varying (const_tree def)
 {
   value_range *vr = get_lattice_entry (def);
   if (vr)
-    vr->set_varying ();
+    {
+      tree type = TREE_TYPE (def);
+      if (value_range_base::supports_type_p (type))
+	vr->set_varying (type);
+      else
+	{
+	  /* If we have an unsupported type (structs, void, etc), there
+	     is nothing we'll be able to do with this entry.
+	     Initialize it to UNDEFINED as a sanity measure, just in
+	     case.  */
+	  vr->set_undefined ();
+	}
+    }
 }
 
 /* Set value-ranges of all SSA names defined by STMT to varying.  */
@@ -220,13 +252,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
@@ -457,7 +489,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;
     }
 
@@ -617,7 +649,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].  */
@@ -657,7 +689,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].  */
@@ -765,14 +797,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].  */
@@ -913,7 +945,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));
 }
@@ -935,7 +967,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;
@@ -945,7 +977,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);
@@ -997,14 +1029,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 ();
@@ -1332,7 +1364,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;
 	}
     }
@@ -1388,7 +1420,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));
@@ -1433,7 +1465,7 @@ vr_values::extract_range_basic (value_range *vr, gimple *stmt)
       vr->equiv_clear ();
     }
   else
-    vr->set_varying ();
+    vr->set_varying (type);
 }
 
 
@@ -1469,7 +1501,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);
@@ -1938,7 +1970,7 @@ vr_values::dump_all_value_ranges (FILE *file)
 vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
 {
   values_propagated = false;
-  num_vr_values = num_ssa_names;
+  num_vr_values = num_ssa_names * 2;
   vr_value = XCNEWVEC (value_range *, num_vr_values);
   vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
   bitmap_obstack_initialize (&vrp_equiv_obstack);
@@ -2875,7 +2907,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_;
@@ -2997,7 +3029,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.
@@ -3018,7 +3050,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]