public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Aldy Hernandez <aldyh@redhat.com>
To: Andrew MacLeod <amacleod@redhat.com>,
	gcc-patches <gcc-patches@gcc.gnu.org>, Jeff Law <law@redhat.com>
Subject: Re: PING: Fwd: [PATCH 2/2] Decouple adjust_range_from_scev from vr_values and value_range_equiv.
Date: Tue, 18 Aug 2020 18:23:50 +0200	[thread overview]
Message-ID: <666093fc-bd2a-9816-0c53-b3373563f3ea@redhat.com> (raw)
In-Reply-To: <e4231786-8e33-9166-807f-5952b5b4336b@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 14880 bytes --]



On 8/17/20 5:59 PM, Andrew MacLeod wrote:
> On 8/17/20 6:04 AM, Aldy Hernandez wrote:
>>
>>
>> On 8/14/20 7:16 PM, Andrew MacLeod wrote:
>>> On 8/14/20 12:05 PM, Aldy Hernandez wrote:
>>>> I made some minor changes to the function comments.
>>>>
>>>> gcc/ChangeLog:
>>>>
>>>>     * vr-values.c (check_for_binary_op_overflow): Change type of store
>>>>     to range_query.
>>>>     (vr_values::adjust_range_with_scev): Abstract most of the code...
>>>>     (range_of_var_in_loop): ...here.  Remove value_range_equiv uses.
>>>>     (simplify_using_ranges::simplify_using_ranges): Change type of 
>>>> store
>>>>     to range_query.
>>>>     * vr-values.h (class range_query): New.
>>>>     (class simplify_using_ranges): Use range_query.
>>>>     (class vr_values): Add OVERRIDE to get_value_range.
>>>>     (range_of_var_in_loop): New.
>>>> ---
>>>>  gcc/vr-values.c | 150 ++++++++++++++++++++++--------------------------
>>>>  gcc/vr-values.h |  23 ++++++--
>>>>  2 files changed, 88 insertions(+), 85 deletions(-)
>>>>
>>>> diff --git a/gcc/vr-values.c b/gcc/vr-values.c
>>>> index 9002d87c14b..5b7bae3bfb7 100644
>>>> --- a/gcc/vr-values.c
>>>> +++ b/gcc/vr-values.c
>>>> @@ -1004,7 +1004,7 @@ vr_values::extract_range_from_comparison 
>>>> (value_range_equiv *vr,
>>>>     overflow.  */
>>>>
>>>>  static bool
>>>> -check_for_binary_op_overflow (vr_values *store,
>>>> +check_for_binary_op_overflow (range_query *store,
>>>>                    enum tree_code subcode, tree type,
>>>>                    tree op0, tree op1, bool *ovf)
>>>>  {
>>>> @@ -1737,22 +1737,18 @@ compare_range_with_value (enum tree_code 
>>>> comp, const value_range *vr,
>>>>
>>>>    gcc_unreachable ();
>>>>  }
>>>> -/* Given a range VR, a LOOP and a variable VAR, determine whether it
>>>> -   would be profitable to adjust VR using scalar evolution information
>>>> -   for VAR.  If so, update VR with the new limits.  */
>>>> +
>>>> +/* Given a VAR in STMT within LOOP, determine the range of the
>>>> +   variable and store it in VR.  If no range can be determined, the
>>>> +   resulting range will be set to VARYING.  */
>>>>
>>>>  void
>>>> -vr_values::adjust_range_with_scev (value_range_equiv *vr, class 
>>>> loop *loop,
>>>> -                   gimple *stmt, tree var)
>>>> +range_of_var_in_loop (irange *vr, range_query *query,
>>>> +              class loop *loop, gimple *stmt, tree var)
>>>>  {
>>>> -  tree init, step, chrec, tmin, tmax, min, max, type, tem;
>>>> +  tree init, step, chrec, tmin, tmax, min, max, type;
>>>>    enum ev_direction dir;
>>>>
>>>> -  /* TODO.  Don't adjust anti-ranges.  An anti-range may provide
>>>> -     better opportunities than a regular range, but I'm not sure.  */
>>>> -  if (vr->kind () == VR_ANTI_RANGE)
>>>> -    return;
>>>> -
>>>
>>> IIUC, you've switched to using the new API, so the bounds calls will 
>>> basically turn and ANTI range into a varying , making [lbound,ubound] 
>>> will be [MIN, MAX] ?
>>> so its effectively a no-op, except we will not punt on getting a 
>>> range when VR is an anti range anymore.. so that goodness...
>>
>> Yes.
>>
>>>
>>>
>>>> chrec = instantiate_parameters (loop, analyze_scalar_evolution 
>>>> (loop, var));
>>>>
>>>>    /* Like in PR19590, scev can return a constant function. */
>>>> @@ -1763,16 +1759,17 @@ vr_values::adjust_range_with_scev 
>>>> (value_range_equiv *vr, class loop *loop,
>>>>      }
>>>>
>>>>    if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
>>>> -    return;
>>>> +    {
>>>> +      vr->set_varying (TREE_TYPE (var));
>>>> +      return;
>>>> +    }
>>>
>>> Im seeing a lot of this pattern...
>>> Maybe we should set vr to varying upon entry to the function as the 
>>> default return value.. then we can just return like it did before in 
>>> all those places.
>>>
>>> Better yet, since this routine doesn't "update" anymore and simply 
>>> returns a range, maybe it could instead return a boolean if it finds 
>>> a range rather than the current behaviour...
>>> then those simply become
>>>
>>> +    return false;
>>>
>>> We won't have to intersect at the caller if we don't need to, and its 
>>> useful information at other points to know a range was calculated 
>>> without having to see if varying_p () came back from the call.
>>> ie, we'd the usage pattern would then be
>>>
>>> value_range_equiv r;
>>> if (range_of_var_in_loop (&r, this, loop, stmt, var))
>>>     vr->intersect (&r);
>>>
>>> This is the pattern we use throughout the ranger.
>>
>> Done.
>>
>>>
>>>
>>>>
>>>>    init = initial_condition_in_loop_num (chrec, loop->num);
>>>> -  tem = op_with_constant_singleton_value_range (init);
>>>> -  if (tem)
>>>> -    init = tem;
>>>> +  if (TREE_CODE (init) == SSA_NAME)
>>>> +    query->get_value_range (init, stmt)->singleton_p (&init);
>>>>    step = evolution_part_in_loop_num (chrec, loop->num);
>>>> -  tem = op_with_constant_singleton_value_range (step);
>>>> -  if (tem)
>>>> -    step = tem;
>>>> +  if (TREE_CODE (step) == SSA_NAME)
>>>> +    query->get_value_range (step, stmt)->singleton_p (&step);
>>>
>>> If I read this correctly, we get values for init and step... and if 
>>> they are SSA_NAMES, then we query ranges, otherwise use what we got 
>>> back.. So that would seem to be the same behaviour as before then..
>>> Perhaps a comment is warranted? I had to read it a few times :-)
>>
>> Indeed.  I am trying to do too much in one line.  I've added a comment.
>>
>>>
>>>
>>>>
>>>>    /* If STEP is symbolic, we can't know whether INIT will be the
>>>>       minimum or maximum value in the range.  Also, unless INIT is
>>>> @@ -1781,7 +1778,10 @@ vr_values::adjust_range_with_scev 
>>>> (value_range_equiv *vr, class loop *loop,
>>>>    if (step == NULL_TREE
>>>>        || !is_gimple_min_invariant (step)
>>>>        || !valid_value_p (init))
>>>> -    return;
>>>> +    {
>>>> +      vr->set_varying (TREE_TYPE (var));
>>>> +      return;
>>>> +    }
>>>>
>>>>    dir = scev_direction (chrec);
>>>>    if (/* Do not adjust ranges if we do not know whether the iv 
>>>> increases
>>>> @@ -1790,7 +1790,10 @@ vr_values::adjust_range_with_scev 
>>>> (value_range_equiv *vr, class loop *loop,
>>>>        /* ... or if it may wrap.  */
>>>>        || scev_probably_wraps_p (NULL_TREE, init, step, stmt,
>>>>                  get_chrec_loop (chrec), true))
>>>> -    return;
>>>> +    {
>>>> +      vr->set_varying (TREE_TYPE (var));
>>>> +      return;
>>>> +    }
>>>>
>>>>    type = TREE_TYPE (var);
>>>>    if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type))
>>>> @@ -1807,7 +1810,7 @@ vr_values::adjust_range_with_scev 
>>>> (value_range_equiv *vr, class loop *loop,
>>>>    if (TREE_CODE (step) == INTEGER_CST
>>>>        && is_gimple_val (init)
>>>>        && (TREE_CODE (init) != SSA_NAME
>>>> -      || get_value_range (init, stmt)->kind () == VR_RANGE))
>>>> +      || query->get_value_range (init, stmt)->kind () == VR_RANGE))
>>>>      {
>>>>        widest_int nit;
>>>>
>>>> @@ -1830,21 +1833,32 @@ vr_values::adjust_range_with_scev 
>>>> (value_range_equiv *vr, class loop *loop,
>>>>            && (sgn == UNSIGNED
>>>>            || wi::gts_p (wtmp, 0) == wi::gts_p (wi::to_wide (step), 
>>>> 0)))
>>>>          {
>>>> -          value_range_equiv maxvr;
>>>> -          tem = wide_int_to_tree (TREE_TYPE (init), wtmp);
>>>> -          extract_range_from_binary_expr (&maxvr, PLUS_EXPR,
>>>> -                          TREE_TYPE (init), init, tem);
>>>> +          value_range maxvr, vr0, vr1;
>>>> +          if (TREE_CODE (init) == SSA_NAME)
>>>> +        vr0 = *(query->get_value_range (init, stmt));
>>>> +          else if (is_gimple_min_invariant (init))
>>>> +        vr0.set (init);
>>>> +          else
>>>> +        vr0.set_varying (TREE_TYPE (init));
>>>> +          tree tem = wide_int_to_tree (TREE_TYPE (init), wtmp);
>>>> +          vr1.set (tem, tem);
>>>> +          range_fold_binary_expr (&maxvr, PLUS_EXPR,
>>>> +                      TREE_TYPE (init), &vr0, &vr1);
>>>> +
>>>>            /* Likewise if the addition did.  */
>>>>            if (maxvr.kind () == VR_RANGE)
>>>>          {
>>>>            value_range initvr;
>>>>
>>>>            if (TREE_CODE (init) == SSA_NAME)
>>>> -            initvr = *(get_value_range (init, stmt));
>>>> +            initvr = *(query->get_value_range (init, stmt));
>>>>            else if (is_gimple_min_invariant (init))
>>>>              initvr.set (init);
>>>>            else
>>>> -            return;
>>>> +            {
>>>> +              vr->set_varying (TREE_TYPE (var));
>>>> +              return;
>>>> +            }
>>>>
>>>>            /* Check if init + nit * step overflows.  Though we checked
>>>>               scev {init, step}_loop doesn't wrap, it is not enough
>>>> @@ -1854,7 +1868,10 @@ vr_values::adjust_range_with_scev 
>>>> (value_range_equiv *vr, class loop *loop,
>>>>                 && compare_values (maxvr.min (), initvr.min ()) != -1)
>>>>                || (dir == EV_DIR_GROWS
>>>>                && compare_values (maxvr.max (), initvr.max ()) != 1))
>>>> -            return;
>>>> +            {
>>>> +              vr->set_varying (TREE_TYPE (var));
>>>> +              return;
>>>> +            }
>>>>
>>>>            tmin = maxvr.min ();
>>>>            tmax = maxvr.max ();
>>>> @@ -1863,56 +1880,12 @@ vr_values::adjust_range_with_scev 
>>>> (value_range_equiv *vr, class loop *loop,
>>>>      }
>>>>      }
>>>>
>>>> -  if (vr->varying_p () || vr->undefined_p ())
>>>> -    {
>>>> -      min = tmin;
>>>> -      max = tmax;
>>>> -
>>>> -      /* For VARYING or UNDEFINED ranges, just about anything we get
>>>> -     from scalar evolutions should be better.  */
>>>> -
>>>> -      if (dir == EV_DIR_DECREASES)
>>>> -    max = init;
>>>> -      else
>>>> -    min = init;
>>>> -    }
>>>> -  else if (vr->kind () == VR_RANGE)
>>>> -    {
>>>> -      min = vr->min ();
>>>> -      max = vr->max ();
>>>> -
>>>> -      if (dir == EV_DIR_DECREASES)
>>>> -    {
>>>> -      /* INIT is the maximum value.  If INIT is lower than VR->MAX ()
>>>> -         but no smaller than VR->MIN (), set VR->MAX () to INIT.  */
>>>> -      if (compare_values (init, max) == -1)
>>>> -        max = init;
>>>> -
>>>> -      /* According to the loop information, the variable does not
>>>> -         overflow.  */
>>>> -      if (compare_values (min, tmin) == -1)
>>>> -        min = tmin;
>>>> -
>>>> -    }
>>>> -      else
>>>> -    {
>>>> -      /* If INIT is bigger than VR->MIN (), set VR->MIN () to 
>>>> INIT.  */
>>>> -      if (compare_values (init, min) == 1)
>>>> -        min = init;
>>>> -
>>>> -      if (compare_values (tmax, max) == -1)
>>>> -        max = tmax;
>>>> -    }
>>>> -    }
>>>> +  min = tmin;
>>>> +  max = tmax;
>>>> +  if (dir == EV_DIR_DECREASES)
>>>> +    max = init;
>>>>    else
>>>> -    return;
>>>> -
>>>> -  /* If we just created an invalid range with the minimum
>>>> -     greater than the maximum, we fail conservatively.
>>>> -     This should happen only in unreachable
>>>> -     parts of code, or for invalid programs.  */
>>>> -  if (compare_values (min, max) == 1)
>>>> -    return;
>>>> +    min = init;
>>>>
>>>>    /* Even for valid range info, sometimes overflow flag will leak in.
>>>>       As GIMPLE IL should have no constants with TREE_OVERFLOW set, we
>>>> @@ -1922,7 +1895,24 @@ vr_values::adjust_range_with_scev 
>>>> (value_range_equiv *vr, class loop *loop,
>>>>    if (TREE_OVERFLOW_P (max))
>>>>      max = drop_tree_overflow (max);
>>>>
>>>> -  vr->update (min, max);
>>>> +  gcc_checking_assert (compare_values (min, max) != 1);
>>>> +  if (TREE_CODE (min) == INTEGER_CST && TREE_CODE (max) == 
>>>> INTEGER_CST)
>>>> +    vr->set (min, max);
>>>> +  else
>>>> +    vr->set_varying (TREE_TYPE (var));
>>>> +}
>>>
>>> if min OR max is an integer (not both as in here),  shouldn't we be 
>>> setting the bounds we do know?
>>> ie  [min, +INF] or [0/-INF, max] ?
>>> or is that an behaviour change?
>>
>> It is definitely a behavior change.  However, I did try it just in 
>> case, but it caused a stage gengtype error, which I'm quite 
>> disinterested in chasing down.
>>
>> OK?
>>
>>
> hum. is it a behaviour change?  It might be for multiranges, but it 
> seems like min or max could be symbolics in legacy mode... and we'd lose 
> that information...
> 
> why can't we just    set (min, max) all the time like it did before?

Ah crap.  You're right.  Loop info may give us [SYM, 10] which must play 
well with a VR of say [5, 8].

I changed the interface to take in a *MIN and *MAX and set those in a 
function which is now called bounds_of_var_in_loop() since it's 
returning a pair of bounds, not a range.

I also moved the tweaking what was being done in said function into 
adjust_range_with_scev, which should now handle symbolics as we were 
doing before.

And as a bonus I tested all this by making sure that my new code gives 
the same result as the old code (see "FIXME: Temporary testing 
construct" in patch).  Bootstraps without failing the sanity check. 
Tests currently running.

For the ranger code, we can just normalize MIN/MAX into constants (or 
resolve any symbolics on-demand), and then just intersect.  For the 
record, any symbolics are guaranteed to be either SYM or SYM +- INT (per 
the valid_value_p() predicate in bounds_of_var_in_loop).  So they will 
be easy to parse.

I added a future enhancement comment for anti-ranges in the 
adjust_range_with_scev method if anyone is so inclined.  The previous 
code bailed on anti-ranges in preference of the VR passed down.  I have 
kept this functionality to avoid changing current behavior (and failing 
the sanity test).  And yes, we are steering away from anti-ranges and 
kind() as a whole, but adjust_range_with_scev() is meant to work with 
legacy ranges.

OK pending tests (provided I remove the double checking blocks :)).

Aldy

[-- Attachment #2: curr.patch --]
[-- Type: text/x-patch, Size: 11419 bytes --]

diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index fe51a6faeb8..2538629b45d 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -1006,7 +1006,7 @@ vr_values::extract_range_from_comparison (value_range_equiv *vr,
    overflow.  */
 
 static bool
-check_for_binary_op_overflow (vr_values *store,
+check_for_binary_op_overflow (range_query *store,
 			      enum tree_code subcode, tree type,
 			      tree op0, tree op1, bool *ovf)
 {
@@ -1736,6 +1736,156 @@ compare_range_with_value (enum tree_code comp, const value_range *vr,
 
   gcc_unreachable ();
 }
+
+/* Given a VAR in STMT within LOOP, determine the bounds of the
+   variable and store it in MIN/MAX and return TRUE.  If no bounds
+   could be determined, return FALSE.  */
+
+bool
+bounds_of_var_in_loop (tree *min, tree *max, range_query *query,
+		       class loop *loop, gimple *stmt, tree var)
+{
+  tree init, step, chrec, tmin, tmax, type = TREE_TYPE (var);
+  enum ev_direction dir;
+
+  chrec = instantiate_parameters (loop, analyze_scalar_evolution (loop, var));
+
+  /* Like in PR19590, scev can return a constant function.  */
+  if (is_gimple_min_invariant (chrec))
+    {
+      *min = *max = chrec;
+      return true;
+    }
+
+  if (TREE_CODE (chrec) != POLYNOMIAL_CHREC)
+    return false;
+
+  init = initial_condition_in_loop_num (chrec, loop->num);
+  step = evolution_part_in_loop_num (chrec, loop->num);
+
+  /* If INIT is an SSA with a singleton range, set INIT to said
+     singleton, otherwise leave INIT alone.  */
+  if (TREE_CODE (init) == SSA_NAME)
+    query->get_value_range (init, stmt)->singleton_p (&init);
+  /* Likewise for step.  */
+  if (TREE_CODE (step) == SSA_NAME)
+    query->get_value_range (step, stmt)->singleton_p (&step);
+
+  /* If STEP is symbolic, we can't know whether INIT will be the
+     minimum or maximum value in the range.  Also, unless INIT is
+     a simple expression, compare_values and possibly other functions
+     in tree-vrp won't be able to handle it.  */
+  if (step == NULL_TREE
+      || !is_gimple_min_invariant (step)
+      || !valid_value_p (init))
+    return false;
+
+  dir = scev_direction (chrec);
+  if (/* Do not adjust ranges if we do not know whether the iv increases
+	 or decreases,  ... */
+      dir == EV_DIR_UNKNOWN
+      /* ... or if it may wrap.  */
+      || scev_probably_wraps_p (NULL_TREE, init, step, stmt,
+				get_chrec_loop (chrec), true))
+    return false;
+
+  if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type))
+    tmin = lower_bound_in_type (type, type);
+  else
+    tmin = TYPE_MIN_VALUE (type);
+  if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type))
+    tmax = upper_bound_in_type (type, type);
+  else
+    tmax = TYPE_MAX_VALUE (type);
+
+  /* Try to use estimated number of iterations for the loop to constrain the
+     final value in the evolution.  */
+  if (TREE_CODE (step) == INTEGER_CST
+      && is_gimple_val (init)
+      && (TREE_CODE (init) != SSA_NAME
+	  || query->get_value_range (init, stmt)->kind () == VR_RANGE))
+    {
+      widest_int nit;
+
+      /* We are only entering here for loop header PHI nodes, so using
+	 the number of latch executions is the correct thing to use.  */
+      if (max_loop_iterations (loop, &nit))
+	{
+	  signop sgn = TYPE_SIGN (TREE_TYPE (step));
+	  wi::overflow_type overflow;
+
+	  widest_int wtmp = wi::mul (wi::to_widest (step), nit, sgn,
+				     &overflow);
+	  /* If the multiplication overflowed we can't do a meaningful
+	     adjustment.  Likewise if the result doesn't fit in the type
+	     of the induction variable.  For a signed type we have to
+	     check whether the result has the expected signedness which
+	     is that of the step as number of iterations is unsigned.  */
+	  if (!overflow
+	      && wi::fits_to_tree_p (wtmp, TREE_TYPE (init))
+	      && (sgn == UNSIGNED
+		  || wi::gts_p (wtmp, 0) == wi::gts_p (wi::to_wide (step), 0)))
+	    {
+	      value_range maxvr, vr0, vr1;
+	      if (TREE_CODE (init) == SSA_NAME)
+		vr0 = *(query->get_value_range (init, stmt));
+	      else if (is_gimple_min_invariant (init))
+		vr0.set (init);
+	      else
+		vr0.set_varying (TREE_TYPE (init));
+	      tree tem = wide_int_to_tree (TREE_TYPE (init), wtmp);
+	      vr1.set (tem, tem);
+	      range_fold_binary_expr (&maxvr, PLUS_EXPR,
+				      TREE_TYPE (init), &vr0, &vr1);
+
+	      /* Likewise if the addition did.  */
+	      if (maxvr.kind () == VR_RANGE)
+		{
+		  value_range initvr;
+
+		  if (TREE_CODE (init) == SSA_NAME)
+		    initvr = *(query->get_value_range (init, stmt));
+		  else if (is_gimple_min_invariant (init))
+		    initvr.set (init);
+		  else
+		    return false;
+
+		  /* Check if init + nit * step overflows.  Though we checked
+		     scev {init, step}_loop doesn't wrap, it is not enough
+		     because the loop may exit immediately.  Overflow could
+		     happen in the plus expression in this case.  */
+		  if ((dir == EV_DIR_DECREASES
+		       && compare_values (maxvr.min (), initvr.min ()) != -1)
+		      || (dir == EV_DIR_GROWS
+			  && compare_values (maxvr.max (), initvr.max ()) != 1))
+		    return false;
+
+		  tmin = maxvr.min ();
+		  tmax = maxvr.max ();
+		}
+	    }
+	}
+    }
+
+  *min = tmin;
+  *max = tmax;
+  if (dir == EV_DIR_DECREASES)
+    *max = init;
+  else
+    *min = init;
+
+  /* Even for valid range info, sometimes overflow flag will leak in.
+     As GIMPLE IL should have no constants with TREE_OVERFLOW set, we
+     drop them.  */
+  if (TREE_OVERFLOW_P (*min))
+    *min = drop_tree_overflow (*min);
+  if (TREE_OVERFLOW_P (*max))
+    *max = drop_tree_overflow (*max);
+
+  gcc_checking_assert (compare_values (*min, *max) != 1);
+  return true;
+}
+
 /* Given a range VR, a LOOP and a variable VAR, determine whether it
    would be profitable to adjust VR using scalar evolution information
    for VAR.  If so, update VR with the new limits.  */
@@ -1743,6 +1893,57 @@ compare_range_with_value (enum tree_code comp, const value_range *vr,
 void
 vr_values::adjust_range_with_scev (value_range_equiv *vr, class loop *loop,
 				   gimple *stmt, tree var)
+{
+  // FIXME: Temporary testing construct.
+  value_range_equiv old;
+  old.deep_copy (vr);
+
+  tree min, max;
+  if (bounds_of_var_in_loop (&min, &max, this, loop, stmt, var))
+    {
+      if (vr->undefined_p () || vr->varying_p ())
+	{
+	  /* For VARYING or UNDEFINED ranges, just about anything we get
+	     from scalar evolutions should be better.  */
+	  vr->update (min, max);
+	}
+      else if (vr->kind () == VR_RANGE)
+	{
+	  /* Start with the input range... */
+	  tree vrmin = vr->min ();
+	  tree vrmax = vr->max ();
+
+	  /* ...and narrow it down with what we got from SCEV.  */
+	  if (compare_values (min, vrmin) == 1)
+	    vrmin = min;
+	  if (compare_values (max, vrmax) == -1)
+	    vrmax = max;
+
+	  vr->update (vrmin, vrmax);
+	}
+      else if (vr->kind () == VR_ANTI_RANGE)
+	{
+	  /* ?? As an enhancement, if VR, MIN, and MAX are constants, one
+	     could just intersect VR with a range of [MIN,MAX].  */
+	}
+    }
+
+  // FIXME: Temporary testing construct.
+  old_adjust_range_with_scev (&old, loop, stmt, var);
+  if (!vr->equal_p (old, false))
+    {
+      fprintf (stderr, "old range: ");
+      old.dump ();
+      fprintf (stderr, "\nnew range: ");
+      vr->dump ();
+      gcc_unreachable ();
+      fprintf (stderr, "\n");
+    }
+}
+
+void
+vr_values::old_adjust_range_with_scev (value_range_equiv *vr, class loop *loop,
+				   gimple *stmt, tree var)
 {
   tree init, step, chrec, tmin, tmax, min, max, type, tem;
   enum ev_direction dir;
@@ -1806,7 +2007,7 @@ vr_values::adjust_range_with_scev (value_range_equiv *vr, class loop *loop,
   if (TREE_CODE (step) == INTEGER_CST
       && is_gimple_val (init)
       && (TREE_CODE (init) != SSA_NAME
-	  || get_value_range (init, stmt)->kind () == VR_RANGE))
+	  || get_value_range (init)->kind () == VR_RANGE))
     {
       widest_int nit;
 
@@ -1839,7 +2040,7 @@ vr_values::adjust_range_with_scev (value_range_equiv *vr, class loop *loop,
 		  value_range initvr;
 
 		  if (TREE_CODE (init) == SSA_NAME)
-		    initvr = *(get_value_range (init, stmt));
+		    initvr = *(get_value_range (init));
 		  else if (is_gimple_min_invariant (init))
 		    initvr.set (init);
 		  else
@@ -1924,6 +2125,7 @@ vr_values::adjust_range_with_scev (value_range_equiv *vr, class loop *loop,
   vr->update (min, max);
 }
 
+
 /* Dump value ranges of all SSA_NAMEs to FILE.  */
 
 void
@@ -4216,7 +4418,7 @@ simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
   return false;
 }
 
-simplify_using_ranges::simplify_using_ranges (vr_values *store)
+simplify_using_ranges::simplify_using_ranges (range_query *store)
   : store (store)
 {
   to_remove_edges = vNULL;
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index 330b4605e39..1a14df2357b 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -22,16 +22,26 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "value-range-equiv.h"
 
+// Abstract class to return a range for a given SSA.
+
+class range_query
+{
+public:
+  virtual const value_range_equiv *get_value_range (const_tree,
+						    gimple * = NULL) = 0;
+  virtual ~range_query () { }
+};
+
 // Class to simplify a statement using range information.
 //
 // The constructor takes a full vr_values, but all it needs is
 // get_value_range() from it.  This class could be made to work with
 // any range repository.
 
-class simplify_using_ranges
+class simplify_using_ranges : public range_query
 {
 public:
-  simplify_using_ranges (class vr_values *);
+  simplify_using_ranges (class range_query *);
   ~simplify_using_ranges ();
   bool simplify (gimple_stmt_iterator *);
 
@@ -44,7 +54,7 @@ public:
 
 private:
   const value_range_equiv *get_value_range (const_tree op,
-					    gimple *stmt = NULL);
+					    gimple *stmt = NULL) OVERRIDE;
   bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *);
   bool simplify_div_or_mod_using_ranges (gimple_stmt_iterator *, gimple *);
   bool simplify_abs_using_ranges (gimple_stmt_iterator *, gimple *);
@@ -79,7 +89,7 @@ private:
 
   vec<edge> to_remove_edges;
   vec<switch_update> to_update_switch_stmts;
-  class vr_values *store;
+  class range_query *store;
 };
 
 /* The VR_VALUES class holds the current view of range information
@@ -96,7 +106,7 @@ private:
    gets attached to an SSA_NAME.  It's unclear how useful that global
    information will be in a world where we can compute context sensitive
    range information fast or perform on-demand queries.  */
-class vr_values
+class vr_values : public range_query
 {
  public:
   vr_values (void);
@@ -112,6 +122,8 @@ class vr_values
   tree op_with_constant_singleton_value_range (tree);
   void adjust_range_with_scev (value_range_equiv *, class loop *,
 			       gimple *, tree);
+  // FIXME: Temporary testing construct.
+  void old_adjust_range_with_scev (value_range_equiv *, class loop *, gimple *, tree);
   void dump_all_value_ranges (FILE *);
 
   void extract_range_for_var_from_comparison_expr (tree, enum tree_code,
@@ -177,4 +189,7 @@ extern tree get_output_for_vrp (gimple *);
 // FIXME: Move this to tree-vrp.c.
 void simplify_cond_using_ranges_2 (class vr_values *, gcond *);
 
+extern bool bounds_of_var_in_loop (tree *min, tree *max, range_query *,
+				   class loop *loop, gimple *stmt, tree var);
+
 #endif /* GCC_VR_VALUES_H */

  reply	other threads:[~2020-08-18 16:24 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-04 11:54 [PATCH 0/2] decouple adjust_range_from_scev from vr_values Aldy Hernandez
2020-08-04 11:55 ` [PATCH 1/2] Add statement context to get_value_range Aldy Hernandez
2020-08-11 11:53   ` PING: Fwd: " Aldy Hernandez
2020-08-14 16:03     ` Andrew MacLeod
2020-08-17  9:19       ` Aldy Hernandez
2020-08-04 11:55 ` [PATCH 2/2] Decouple adjust_range_from_scev from vr_values and value_range_equiv Aldy Hernandez
2020-08-04 13:27   ` Richard Biener
2020-08-04 14:20     ` Aldy Hernandez
2020-08-11 11:54   ` PING: Fwd: " Aldy Hernandez
2020-08-14 16:05     ` Aldy Hernandez
2020-08-14 17:16       ` Andrew MacLeod
2020-08-17 10:04         ` Aldy Hernandez
2020-08-17 15:59           ` Andrew MacLeod
2020-08-18 16:23             ` Aldy Hernandez [this message]
2020-08-18 16:38               ` Aldy Hernandez
2020-08-18 17:05                 ` Andrew MacLeod

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=666093fc-bd2a-9816-0c53-b3373563f3ea@redhat.com \
    --to=aldyh@redhat.com \
    --cc=amacleod@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=law@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).