https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107822

--- Comment #2 from Andrew Macleod <amacleod at redhat dot com> ---
Sorry, I've been out for a few weeks.

This isn't an on-demand issue. All versions of VRP do a full walk and resolve
during the walk. This issue is a combination of lack of iteration and not
optimistic evaluations on back edges. 

We do use on-demand to query the back edge to alleviate a number of issues with
lack of iteration. The problem is that with a lack of iteration, we can't take
the fully optimistic approach and assume that the value of c_10 is [1, 1] for a
full iteration of the loop and then determine during the second iteration that
it is always either 1 or 2.

    <bb 3> [local count: 955630225]:
    _1 = c_10 ^ 3;

    <bb 4> [local count: 1073741824]:
    # c_10 = PHI <1(2), _1(3)>
    b.1_3 = b;
    if (b.1_3 <= 8)
      goto <bb 3>; [89.00%]
    else
      goto <bb 5>; [11.00%]

    <bb 5> [local count: 118111600]:
    # c_13 = PHI <c_10(4)>
    if (c_13 != 0)

When we first try to evaluate 
# c_10 = PHI <1(2), _1(3)>
the back edge 3->4 has not been processed, so it is evaluated and _1 needs to
be calculated. Unfortunately the value of c_10 has not been resolved yet, so it
defaults to something pessimistically safe and assumes it is varying and we get
the results you see.


We have a few possible approaches. In an ideal world, we could use the path
ranger to answer questions on the back edge instead of fully evaluating it. 
This would allow us to do a "pretend" first iteration and use the value of
[1,1] for c_10, and produce _1 =  result of [1,2], which in turn would then
cause us to evaluate c_10 as [1,2].  It is too late in the cycle to experiment
with that approach I think.

I have also (still am) experimented with changing that initial value to be more
optimistic.  When we first evaluate a statement, We store an initial value so
that if it is encountered again during evaluation, we can avoid a cycle. That
initial value is what gets used by any calculations along a back edge. When we
return from resolving all the inputs, we do a final evaluation of the statement
and store the real global value.

We have existing infrastructure which uses time stamps that should allow us to
calculate one value when doing the back edge, and then recalculate it for real
when we actually process that block.  I have not convinced myself that this is
100% safe yet.

A third option would be to recognize this is a fairly common pattern that we
have a 2 input PHI node like this. and before setting the initial value we
could walk the use-def chains and see if the PHI is feeding itself and make
some other determinations about the range (ie, increasing, decreasing, specific
values, etc) and use that for the initial estimate instead.   This would give
us similar results to what we did before and is likely safer than depending on
timestamps to do recalculations. It is just not quite as general.      

Im experimenting with the latter 2 approaches this week to determine what seems
safest at this point in the cycle.

Reply via email to