On Mon, 10 Nov 2025, Andrew MacLeod wrote:

> 
> On 11/10/25 03:55, Richard Biener wrote:
> > On Fri, 7 Nov 2025, Andrew MacLeod wrote:
> >
> >> On 11/7/25 13:28, Richard Biener wrote:
> >>>> Am 07.11.2025 um 15:46 schrieb Andrew MacLeod <[email protected]>:
> >>>>
> >>>>
> >>>>> On 11/7/25 08:29, Richard Biener wrote:
> >>>>> When feeding non-SSA names to range_on_edge we degrade to a
> >>>>> non-contextual query even though range_on_exits handling suggests
> >>>>> that we can do better.  The following does what it does in
> >>>>> range_on_edge directly, passing the edge source as 'bbend'
> >>>>> argument to get_tree_range if the edge source has a single
> >>>>> successor (as will be the case for queries from niter analysis).
> >>>>>
> >>>>> Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.
> >>>>>
> >>>>> OK?  The remainder of the series makes use of this, I'll hold of
> >>>>> that a bit for followup work.
> >>>> Yeah, That's good.
> >>> I did wonder whether the else path using range_on_exit is wrong in this
> >>> regard?
> >>>
> >>> Richard
> >>>
> >> No it is correct
> >>
> >> For the most part GORI calculates edge ranges for ssa-names independant of
> >> their actual range.    So this is combined with the range-on-exit from the
> >> block, to produce the actual range on the edge.
> >>
> >> ie,  if (a > 100)     GORI will produce [101, +INF] for the edge range of
> >> 'a'
> >> on the true side.
> >>
> >> It is combined with the on exit range of 'a' in the edges src block to
> >> determine the true range of 'a' on an edge.,
> >>
> >>        range_on_exit (r, e->src, name);
> >>        <...>
> >>        if (m_cache.range_on_edge (edge_range, e, name))
> >>          r.intersect (edge_range);
> >>
> >> In your path with a non-SSA name, its important to only use the on exit
> >> range
> >> if there is a single successor since there will be no edge adjustment.
> > Hmm, but the above adjustment is intersection, it will make ranges only
> > smaller.  There's also
> 
> well, it needs to.  Ranges are only every reduced by an interaction.  Lets
> assume  a_2 has been calculated to have a global range of [0, 100]
> 
> if the block exit is
> 
>   if (a_2 > 40)
> 
> GORI will return [41, +INF].
> 
> on the true edge we need to intersect the exit range with the edge range, and
> can then determine that a_2 on that edge is [41, 100]
> 
> 
> >        // If this is not an abnormal edge, check for a non-null exit .
> >        if ((e->flags & (EDGE_EH | EDGE_ABNORMAL)) == 0)
> >          infer_oracle ().maybe_adjust_range (r, name, e->src);
> >
> > at the <...>, not sure what that does.
> 
> Aggregates and applies any inferred ranges from within the block, like a
> de-reference that causes non-zero, or what have you.  It makes sure they are
> applied to any ranges exiting the block
> 
> in our above example a_2 was [0, 100], if in the block also contained
> 
>    b_6 = v_5 / a_2
> 
> there would be an inferred range applied of [-INF, -1][1, +INF] as divide by
> zero ensures it cant be zero, and that make the range f a_2 [1, 100] at block
> exit rather than [0, 100]
> 
> 
> >
> > That said, there's currently no worker for on_edge for GENERIC in GORI.
> > But this and the above means that even doing
> >
> >    if (!gimple_range_ssa_p (name))
> >      res = get_tree_range (r, name, NULL, NULL, e->src);
> >
> > should be correct.
> 
> yes, the on exit value is always correct, especially if there is no branch.  
> if there is a branch, you simply don't get the benefit of potential range
> reduction on the edge.
> 
> 
> > Similarly doing get_tree_range (r, name, NULL,
> > e->dest, NULL) should produce correct answers, no?  So I should be
> 
> No, that would no be the same.  Range on entry is calculated by aggregating
> (unioning) all the incoming edges.   Lets assume b_3 is varying.
> 
> bb2:
> if (b_3) > 100 goto bb5
> bb3:   // b_3 range on entry is [-INF, 100]
> bb4:   // b_3 is still [-INF, 100]
> // bb4 falls through to bb5.
> bb5: // b_3 range on entry is now VARYING.
> 
> for the edge 4->5 ,  exit range of bb4 is [-INF, 100], but the  entry range
> of  bb5 is VARYING. because the branch in bb2 no longer dominates the block.
> 
> so yes, for a single pred successor, the on entry is the same as the on exit,
> but im not sure what value there is in checking.. just use the on exit value
> always for get_tree_range.
> 
> Because its an expression rather than a specific SSA_NAME, there are no
> callbacks into ranger for any ssa-names found in the expression, so the only
> granularity we currently have is the on exit or on entry range...
> 
> the entry and exit blocks are late additions to solve some issues i forget... 
> I never really considered range on edge... I see no reason not to add it if it
> is useful...
> 
> I attached a quick patch that should allow you to specify an edge.. try it.

Oh - I didn't even try to see wheter it was that trivial to add.  Thanks
for that.  This of course simplifies enhancing range_on_edge.

I've posted, tested and pushed a series with your change.

Thanks,
Richard.

> > able to remove the single_succ (e->src) requirement - in fact I'd
> > expect the most precise ranges when using the e->dest in case
> > there's a single predecessor because then (hopefully) GORI can do
> > work on mentioned SSA names in the GENERIC expression?
> Well, if there is a single predecessor, yes, you may pick up the outgoing edge
> range that way.
> >
> > I'm testing
> >
> > diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
> > index 942bf8bf0a5..cc474db6818 100644
> > --- a/gcc/gimple-range.cc
> > +++ b/gcc/gimple-range.cc
> > @@ -252,8 +252,12 @@ gimple_ranger::range_on_edge (vrange &r, edge e, tree
> > name)
> >   
> >     bool res = true;
> >     if (!gimple_range_ssa_p (name))
> > -    res = get_tree_range (r, name, NULL, NULL,
> > -                         single_succ_p (e->src) ? e->src : NULL);
> > +    {
> > +      if (single_pred_p (e->dest)
> > +       res = get_tree_range (r, name, NULL, e->dest, NULL);
> > +      else
> > +       res = get_tree_range (r, name, NULL, NULL, e->src);
> > +    }
> >     else
> >       {
> >         range_on_exit (r, e->src, name);
> >
> > there's the twist that at e->dest not all mentioned SSA names might
> > be defined in a dominating position, so this would be an argument
> > against using e->dest.  But then always using e->src should be still
> > correct?
> >
> > Thanks,
> > Richard.
> 
> If you find that patch useful, feel free to commit it with your other changes
> 
> Andrew
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to