diff mbox series

[range-ops] patch 02/04: enforce canonicalization in value_range

Message ID 09587b14-fa15-53fa-8162-b643c8537b9a@redhat.com
State New
Headers show
Series [range-ops] patch 02/04: enforce canonicalization in value_range | expand

Commit Message

Aldy Hernandez July 1, 2019, 9:02 a.m. UTC
As discussed prior.  This enforces canonicalization at creation time, 
which makes things a lot more consistent throughout.

Since now [MIN, MAX] will be canonicalized into VR_VARYING, we can no 
longer depend on normalizing VARYING's into [MIN, MAX] for more general 
handling.  I've adjusted the few places where we were doing this so that 
they work correctly.

As a bonus, now that we're canonicalized, I've tweaked singleton to work 
with anti-ranges.

Note: There is a small note in ranges_from_anti_range, which I will 
start making heavier use of in subsequent patches:

+  /* ?? This function is called multiple times from num_pairs,
+     lower_bound, and upper_bound.  We should probably memoize this, or
+     rewrite the callers in such a way that we're not re-calculating
+     this constantly.  */

I don't think this is needed now, but just a note of things to come.  It 
may not be an issue, but just something to keep in mind.

Tested on x86-64 Linux with --enable-languages=all.

Aldy

Comments

Jeff Law July 2, 2019, 9:36 p.m. UTC | #1
On 7/1/19 3:02 AM, Aldy Hernandez wrote:
> As discussed prior.  This enforces canonicalization at creation time,
> which makes things a lot more consistent throughout.
> 
> Since now [MIN, MAX] will be canonicalized into VR_VARYING, we can no
> longer depend on normalizing VARYING's into [MIN, MAX] for more general
> handling.  I've adjusted the few places where we were doing this so that
> they work correctly.
> 
> As a bonus, now that we're canonicalized, I've tweaked singleton to work
> with anti-ranges.
> 
> Note: There is a small note in ranges_from_anti_range, which I will
> start making heavier use of in subsequent patches:
> 
> +  /* ?? This function is called multiple times from num_pairs,
> +     lower_bound, and upper_bound.  We should probably memoize this, or
> +     rewrite the callers in such a way that we're not re-calculating
> +     this constantly.  */
> 
> I don't think this is needed now, but just a note of things to come.  It
> may not be an issue, but just something to keep in mind.
> 
> Tested on x86-64 Linux with --enable-languages=all.
> 
> Aldy
> 
> range-ops-canon.patch
> 
> commit d220a3eeb77615b39260e532e34815a3810e8348
> Author: Aldy Hernandez <aldyh@redhat.com>
> Date:   Fri Jun 28 11:15:03 2019 +0200
> 
>     Enforce canonicalization in value_range.
> 
> diff --git a/gcc/ChangeLog b/gcc/ChangeLog
> index a5247735694..866200d9594 100644
> --- a/gcc/ChangeLog
> +++ b/gcc/ChangeLog
> @@ -1,3 +1,20 @@
> +2019-07-01  Aldy Hernandez  <aldyh@redhat.com>
> +
> +	* tree-vrp.c (value_range_base::set_and_canonicalize): Rename to
> +	set() and add normalization of [MIN, MAX] into varying.
> +	(value_range_base::singleton_p): Make work with anti ranges.
> +	(ranges_from_anti_range): Handle pointers.
> +	(extract_range_into_wide_ints): Call normalize_symbolics.
> +	(extract_range_from_binary_expr): Do not build a [MIN,MAX] range
> +	because it will be canonicalized into varying.
> +	Call set() instead of set_and_canonicalize().
> +	(extract_range_from_unary_expr): Call set() instead of
> +	set_and_canonicalize().
> +	(intersect_helper): Do not call set_and_canonicalize.
> +	* tree-vrp.h (value_range_base): Remove set_and_canonicalize.
> +	(value_range): Same.
> +	* vr-values.c (extract_range_from_var_from_comparison_expr): Same.
I don't see anything inherently concerning here.  I do wonder if there's
any value in having a debugging function in the class that would iterate
over the ranges and check them for proper canonicalization, verify that
VR_{VARYING,UNDEFINED} objects do not have equivalences, etc.  Thoughts?

Jeff
Aldy Hernandez July 3, 2019, 9:35 a.m. UTC | #2
On 7/2/19 5:36 PM, Jeff Law wrote:

> I don't see anything inherently concerning here.  I do wonder if there's
> any value in having a debugging function in the class that would iterate
> over the ranges and check them for proper canonicalization, verify that
> VR_{VARYING,UNDEFINED} objects do not have equivalences, etc.  Thoughts?

In patch 01 we have:

> diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
> index 594ee9adc17..97046c22ed1 100644
> --- a/gcc/tree-vrp.c
> +++ b/gcc/tree-vrp.c
> @@ -86,6 +86,8 @@ value_range_base::set (enum value_range_kind kind, tree min, t
> ree max)
>  void
>  value_range::set_equiv (bitmap equiv)
>  {
> +  if (undefined_p () || varying_p ())
> +    equiv = NULL;

So it shouldn't be possible to attach an equivalence to a VARYING / 
UNDEFINED range.  Plus, we already have a sanity checker:

> void
> value_range::check ()
> {
>   value_range_base::check ();
>   switch (m_kind)
>     {
>     case VR_UNDEFINED:
>     case VR_VARYING:
>       gcc_assert (!m_equiv || bitmap_empty_p (m_equiv));
>     default:;
>     }
> }

We have no methods for altering a range, except for changing 
equivalences.  So it shouldn't be possible to create a non-canonicalized 
range.

Aldy
Jeff Law July 3, 2019, 10:57 p.m. UTC | #3
On 7/3/19 3:35 AM, Aldy Hernandez wrote:
> On 7/2/19 5:36 PM, Jeff Law wrote:
> 
>> I don't see anything inherently concerning here.  I do wonder if there's
>> any value in having a debugging function in the class that would iterate
>> over the ranges and check them for proper canonicalization, verify that
>> VR_{VARYING,UNDEFINED} objects do not have equivalences, etc.  Thoughts?
> 
> In patch 01 we have:
> 
>> diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
>> index 594ee9adc17..97046c22ed1 100644
>> --- a/gcc/tree-vrp.c
>> +++ b/gcc/tree-vrp.c
>> @@ -86,6 +86,8 @@ value_range_base::set (enum value_range_kind kind,
>> tree min, t
>> ree max)
>>  void
>>  value_range::set_equiv (bitmap equiv)
>>  {
>> +  if (undefined_p () || varying_p ())
>> +    equiv = NULL;
> 
> So it shouldn't be possible to attach an equivalence to a VARYING /
> UNDEFINED range.  Plus, we already have a sanity checker:
> 
>> void
>> value_range::check ()
>> {
>>   value_range_base::check ();
>>   switch (m_kind)
>>     {
>>     case VR_UNDEFINED:
>>     case VR_VARYING:
>>       gcc_assert (!m_equiv || bitmap_empty_p (m_equiv));
>>     default:;
>>     }
>> }
> 
> We have no methods for altering a range, except for changing
> equivalences.  So it shouldn't be possible to create a non-canonicalized
> range.
Ah.  Cool.  Thanks for enlightening me ;-)

jeff
Aldy Hernandez July 17, 2019, 8:05 a.m. UTC | #4
I've rebased this patch to be independent of the others, to perhaps 
parallelize the review process.

As mentioned before, this patch enforces canonicalization of ranges upon 
creation.  This makes it easier to compare results of range 
implementations and avoids multiple representations for the same range 
(and the special casing the is usually needed to handle these).  The 
patch also enforces no equivalences for VARYING and UNDEFINED, and 
guarantees that there is only one way to represent varying, with 
VR_VARYING, not with [MIN,MAX], etc.

I have also adjusted ranges_from_anti_range, vrp_val_max, and 
vrp_val_min to work with pointers.  I have seen multiple uses of pointer 
ranges containing constants in VRP, for magic pointer values and such in 
libgcc, and other code bases.  Even though VRP mostly generalizes 
pointers to null / non-null, range-ops gets finer results because it 
doesn't "forget" that a pointer could have been 0 or 0xdeadbeef, or 
whatever.  These changes are not strictly necessary (we could dumb down 
range-ops), but I see no reason to do so.

No ChangeLog entries yet, as we usually go through various interations 
before we agree on anything.

Tested on x86-64 Linux with all languages.

Aldy
diff mbox series

Patch

commit d220a3eeb77615b39260e532e34815a3810e8348
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Fri Jun 28 11:15:03 2019 +0200

    Enforce canonicalization in value_range.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a5247735694..866200d9594 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@ 
+2019-07-01  Aldy Hernandez  <aldyh@redhat.com>
+
+	* tree-vrp.c (value_range_base::set_and_canonicalize): Rename to
+	set() and add normalization of [MIN, MAX] into varying.
+	(value_range_base::singleton_p): Make work with anti ranges.
+	(ranges_from_anti_range): Handle pointers.
+	(extract_range_into_wide_ints): Call normalize_symbolics.
+	(extract_range_from_binary_expr): Do not build a [MIN,MAX] range
+	because it will be canonicalized into varying.
+	Call set() instead of set_and_canonicalize().
+	(extract_range_from_unary_expr): Call set() instead of
+	set_and_canonicalize().
+	(intersect_helper): Do not call set_and_canonicalize.
+	* tree-vrp.h (value_range_base): Remove set_and_canonicalize.
+	(value_range): Same.
+	* vr-values.c (extract_range_from_var_from_comparison_expr): Same.
+
 2019-07-01  Aldy Hernandez  <aldyh@redhat.com>
 
 	* gimple-ssa-evrp-analyze.c (record_ranges_from_phis): Skip PHIs
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 97046c22ed1..f78517b5b3b 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -69,20 +69,15 @@  along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "wide-int-range.h"
 
+static bool
+ranges_from_anti_range (const value_range_base *ar,
+			value_range_base *vr0, value_range_base *vr1,
+			bool handle_pointers = false);
+
 /* Set of SSA names found live during the RPO traversal of the function
    for still active basic-blocks.  */
 static sbitmap *live;
 
-void
-value_range_base::set (enum value_range_kind kind, tree min, tree max)
-{
-  m_kind = kind;
-  m_min = min;
-  m_max = max;
-  if (flag_checking)
-    check ();
-}
-
 void
 value_range::set_equiv (bitmap equiv)
 {
@@ -363,6 +358,24 @@  value_range::equiv_add (const_tree var,
 bool
 value_range_base::singleton_p (tree *result) const
 {
+  if (m_kind == VR_ANTI_RANGE)
+    {
+      if (nonzero_p ())
+	{
+	  if (TYPE_PRECISION (type ()) == 1)
+	    {
+	      if (result)
+		*result = m_max;
+	      return true;
+	    }
+	  return false;
+	}
+
+      value_range_base vr0, vr1;
+      return (ranges_from_anti_range (this, &vr0, &vr1, true)
+	      && vr1.undefined_p ()
+	      && vr0.singleton_p (result));
+    }
   if (m_kind == VR_RANGE
       && vrp_operand_equal_p (min (), max ())
       && is_gimple_min_invariant (min ()))
@@ -690,8 +703,7 @@  intersect_range_with_nonzero_bits (enum value_range_kind vr_type,
    extract ranges from var + CST op limit.  */
 
 void
-value_range_base::set_and_canonicalize (enum value_range_kind kind,
-					tree min, tree max)
+value_range_base::set (enum value_range_kind kind, tree min, tree max)
 {
   if (kind == VR_UNDEFINED)
     {
@@ -711,7 +723,9 @@  value_range_base::set_and_canonicalize (enum value_range_kind kind,
   if (TREE_CODE (min) != INTEGER_CST
       || TREE_CODE (max) != INTEGER_CST)
     {
-      set (kind, min, max);
+      m_kind = kind;
+      m_min = min;
+      m_max = max;
       return;
     }
 
@@ -747,12 +761,13 @@  value_range_base::set_and_canonicalize (enum value_range_kind kind,
       kind = kind == VR_RANGE ? VR_ANTI_RANGE : VR_RANGE;
     }
 
+  tree type = TREE_TYPE (min);
+
   /* Anti-ranges that can be represented as ranges should be so.  */
   if (kind == VR_ANTI_RANGE)
     {
       /* For -fstrict-enums we may receive out-of-range ranges so consider
          values < -INF and values > INF as -INF/INF as well.  */
-      tree type = TREE_TYPE (min);
       bool is_min = (INTEGRAL_TYPE_P (type)
 		     && tree_int_cst_compare (min, TYPE_MIN_VALUE (type)) <= 0);
       bool is_max = (INTEGRAL_TYPE_P (type)
@@ -795,22 +810,37 @@  value_range_base::set_and_canonicalize (enum value_range_kind kind,
         }
     }
 
+  /* Normalize [MIN, MAX] into VARYING and ~[MIN, MAX] into UNDEFINED.
+
+     Avoid using TYPE_{MIN,MAX}_VALUE because -fstrict-enums can
+     restrict those to a subset of what actually fits in the type.
+     Instead use the extremes of the type precision which will allow
+     compare_range_with_value() to check if a value is inside a range,
+     whereas if we used TYPE_*_VAL, said function would just punt
+     upon seeing a VARYING.  */
+  unsigned prec = TYPE_PRECISION (type);
+  signop sign = TYPE_SIGN (type);
+  if (wi::eq_p (wi::to_wide (min), wi::min_value (prec, sign))
+      && wi::eq_p (wi::to_wide (max), wi::max_value (prec, sign)))
+    {
+      if (kind == VR_RANGE)
+	set_varying (type);
+      else if (kind == VR_ANTI_RANGE)
+	set_undefined (type);
+      else
+	gcc_unreachable ();
+      return;
+    }
+
   /* Do not drop [-INF(OVF), +INF(OVF)] to varying.  (OVF) has to be sticky
      to make sure VRP iteration terminates, otherwise we can get into
      oscillations.  */
 
-  set (kind, min, max);
-}
-
-void
-value_range::set_and_canonicalize (enum value_range_kind kind,
-				   tree min, tree max, bitmap equiv)
-{
-  value_range_base::set_and_canonicalize (kind, min, max);
-  if (this->kind () == VR_RANGE || this->kind () == VR_ANTI_RANGE)
-    set_equiv (equiv);
-  else
-    equiv_clear ();
+  m_kind = kind;
+  m_min = min;
+  m_max = max;
+  if (flag_checking)
+    check ();
 }
 
 void
@@ -1240,8 +1270,14 @@  vrp_set_zero_nonzero_bits (const tree expr_type,
 
 static bool
 ranges_from_anti_range (const value_range_base *ar,
-			value_range_base *vr0, value_range_base *vr1)
+			value_range_base *vr0, value_range_base *vr1,
+			bool handle_pointers)
 {
+  /* ?? This function is called multiple times from num_pairs,
+     lower_bound, and upper_bound.  We should probably memoize this, or
+     rewrite the callers in such a way that we're not re-calculating
+     this constantly.  */
+
   tree type = ar->type ();
 
   vr0->set_undefined (type);
@@ -1253,18 +1289,18 @@  ranges_from_anti_range (const value_range_base *ar,
   if (ar->kind () != VR_ANTI_RANGE
       || TREE_CODE (ar->min ()) != INTEGER_CST
       || TREE_CODE (ar->max ()) != INTEGER_CST
-      || !vrp_val_min (type)
-      || !vrp_val_max (type))
+      || !vrp_val_min (type, handle_pointers)
+      || !vrp_val_max (type, handle_pointers))
     return false;
 
-  if (tree_int_cst_lt (vrp_val_min (type), ar->min ()))
+  if (tree_int_cst_lt (vrp_val_min (type, handle_pointers), ar->min ()))
     vr0->set (VR_RANGE,
-	      vrp_val_min (type),
+	      vrp_val_min (type, handle_pointers),
 	      wide_int_to_tree (type, wi::to_wide (ar->min ()) - 1));
-  if (tree_int_cst_lt (ar->max (), vrp_val_max (type)))
+  if (tree_int_cst_lt (ar->max (), vrp_val_max (type, handle_pointers)))
     vr1->set (VR_RANGE,
 	      wide_int_to_tree (type, wi::to_wide (ar->max ()) + 1),
-	      vrp_val_max (type));
+	      vrp_val_max (type, handle_pointers));
   if (vr0->undefined_p ())
     {
       *vr0 = *vr1;
@@ -1275,21 +1311,19 @@  ranges_from_anti_range (const value_range_base *ar,
 }
 
 /* Extract the components of a value range into a pair of wide ints in
-   [WMIN, WMAX].
-
-   If the value range is anything but a VR_*RANGE of constants, the
-   resulting wide ints are set to [-MIN, +MAX] for the type.  */
+   [WMIN, WMAX], after having normalized any symbolics from the input.  */
 
 static void inline
-extract_range_into_wide_ints (const value_range_base *vr,
+extract_range_into_wide_ints (const value_range_base *vr_,
 			      signop sign, unsigned prec,
 			      wide_int &wmin, wide_int &wmax)
 {
-  gcc_assert (vr->kind () != VR_ANTI_RANGE || vr->symbolic_p ());
-  if (range_int_cst_p (vr))
+  gcc_assert (vr_->kind () != VR_ANTI_RANGE || vr_->symbolic_p ());
+  value_range vr = vr_->normalize_symbolics ();
+  if (range_int_cst_p (&vr))
     {
-      wmin = wi::to_wide (vr->min ());
-      wmax = wi::to_wide (vr->max ());
+      wmin = wi::to_wide (vr.min ());
+      wmax = wi::to_wide (vr.max ());
     }
   else
     {
@@ -1351,9 +1385,8 @@  extract_range_from_multiplicative_op (value_range_base *vr,
 					code, TYPE_SIGN (type), prec,
 					vr0_lb, vr0_ub, vr1_lb, vr1_ub,
 					overflow_undefined))
-    vr->set_and_canonicalize (VR_RANGE,
-			      wide_int_to_tree (type, res_lb),
-			      wide_int_to_tree (type, res_ub));
+    vr->set (VR_RANGE, wide_int_to_tree (type, res_lb),
+	     wide_int_to_tree (type, res_ub));
   else
     vr->set_varying (type);
 }
@@ -1747,19 +1780,30 @@  extract_range_from_binary_expr (value_range_base *vr,
      range and see what we end up with.  */
   if (code == PLUS_EXPR || code == MINUS_EXPR)
     {
+      value_range_kind vr0_kind = vr0.kind (), vr1_kind = vr1.kind ();
+      tree vr0_min = vr0.min (), vr0_max = vr0.max ();
+      tree vr1_min = vr1.min (), vr1_max = vr1.max ();
       /* This will normalize things such that calculating
 	 [0,0] - VR_VARYING is not dropped to varying, but is
 	 calculated as [MIN+1, MAX].  */
       if (vr0.varying_p ())
-	vr0.set (VR_RANGE, vrp_val_min (expr_type), vrp_val_max (expr_type));
+	{
+	  vr0_kind = VR_RANGE;
+	  vr0_min = vrp_val_min (expr_type);
+	  vr0_max = vrp_val_max (expr_type);
+	}
       if (vr1.varying_p ())
-	vr1.set (VR_RANGE, vrp_val_min (expr_type), vrp_val_max (expr_type));
+	{
+	  vr1_kind = VR_RANGE;
+	  vr1_min = vrp_val_min (expr_type);
+	  vr1_max = vrp_val_max (expr_type);
+	}
 
       const bool minus_p = (code == MINUS_EXPR);
-      tree min_op0 = vr0.min ();
-      tree min_op1 = minus_p ? vr1.max () : vr1.min ();
-      tree max_op0 = vr0.max ();
-      tree max_op1 = minus_p ? vr1.min () : vr1.max ();
+      tree min_op0 = vr0_min;
+      tree min_op1 = minus_p ? vr1_max : vr1_min;
+      tree max_op0 = vr0_max;
+      tree max_op1 = minus_p ? vr1_min : vr1_max;
       tree sym_min_op0 = NULL_TREE;
       tree sym_min_op1 = NULL_TREE;
       tree sym_max_op0 = NULL_TREE;
@@ -1772,7 +1816,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 	 single-symbolic ranges, try to compute the precise resulting range,
 	 but only if we know that this resulting range will also be constant
 	 or single-symbolic.  */
-      if (vr0.kind () == VR_RANGE && vr1.kind () == VR_RANGE
+      if (vr0_kind == VR_RANGE && vr1_kind == VR_RANGE
 	  && (TREE_CODE (min_op0) == INTEGER_CST
 	      || (sym_min_op0
 		  = get_single_symbol (min_op0, &neg_min_op0, &min_op0)))
@@ -1902,7 +1946,7 @@  extract_range_from_binary_expr (value_range_base *vr,
 		{
 		  min = wide_int_to_tree (expr_type, res_lb);
 		  max = wide_int_to_tree (expr_type, res_ub);
-		  vr->set_and_canonicalize (VR_RANGE, min, max);
+		  vr->set (VR_RANGE, min, max);
 		  return;
 		}
 	    }
@@ -2200,7 +2244,7 @@  extract_range_from_unary_expr (value_range_base *vr,
 	{
 	  tree min = wide_int_to_tree (outer_type, wmin);
 	  tree max = wide_int_to_tree (outer_type, wmax);
-	  vr->set_and_canonicalize (VR_RANGE, min, max);
+	  vr->set (VR_RANGE, min, max);
 	}
       else
 	vr->set_varying (outer_type);
@@ -6107,7 +6151,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_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 (vr0type, vr0min, vr0max);
   /* If that failed, use the saved original VR0.  */
   if (tem.varying_p ())
     return *vr0;
@@ -6217,7 +6266,7 @@  value_range_base::union_helper (const value_range_base *vr0,
   else if (vr0type == VR_VARYING)
     tem.set_varying (TREE_TYPE (vr0->min ()));
   else
-    tem.set_and_canonicalize (vr0type, vr0min, vr0max);
+    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
diff --git a/gcc/tree-vrp.h b/gcc/tree-vrp.h
index 5baabfd8b8d..3511cfaf0fc 100644
--- a/gcc/tree-vrp.h
+++ b/gcc/tree-vrp.h
@@ -72,7 +72,6 @@  public:
   /* Misc methods.  */
   tree type () const;
   bool may_contain_p (tree) const;
-  void set_and_canonicalize (enum value_range_kind, tree, tree);
   bool zero_p () const;
   bool nonzero_p () const;
   bool singleton_p (tree *result = NULL) const;
@@ -148,7 +147,6 @@  class GTY((user)) value_range : public value_range_base
 
   /* Misc methods.  */
   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;
 
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 6569af391ed..421d05d9017 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -565,9 +565,9 @@  vr_values::extract_range_for_var_from_comparison_expr (tree var,
          vice-versa.  Use set_and_canonicalize which does this for
          us.  */
       if (cond_code == LE_EXPR)
-        vr_p->set_and_canonicalize (VR_RANGE, min, max, vr_p->equiv ());
+        vr_p->set (VR_RANGE, min, max, vr_p->equiv ());
       else if (cond_code == GT_EXPR)
-        vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ());
+        vr_p->set (VR_ANTI_RANGE, min, max, vr_p->equiv ());
       else
 	gcc_unreachable ();
     }
@@ -639,7 +639,7 @@  vr_values::extract_range_for_var_from_comparison_expr (tree var,
 	  && vrp_val_is_max (max))
 	min = max = limit;
 
-      vr_p->set_and_canonicalize (VR_ANTI_RANGE, min, max, vr_p->equiv ());
+      vr_p->set (VR_ANTI_RANGE, min, max, vr_p->equiv ());
     }
   else if (cond_code == LE_EXPR || cond_code == LT_EXPR)
     {