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)