Richard Biener <rguent...@suse.de> writes:

> On Fri, 14 Jan 2022, Jiufu Guo wrote:
>
>> Richard Biener <rguent...@suse.de> writes:
>> 
>> > On Thu, 13 Jan 2022, guojiufu wrote:
>> >
>> >> On 2022-01-03 22:30, Richard Biener wrote:
>> >> > On Wed, 22 Dec 2021, Jiufu Guo wrote:
>> >> > 
>> >> >> Hi,
>> >> >> ...
>> >> >> 
>> >> >> Bootstrap and regtest pass on ppc64* and x86_64.  Is this ok for trunk?
>> >> > 
 may means infer_loop_bounds_from_undefined may not useful
before IV's scev is ready.

> override the global caching of analyze_scalar_evolution the per
> SSA name cache for SCEV analysis isn't overridden.  That also means
> computing the estimates early will break your patch (I've
> tested calling estimate_numbers_of_iterations explicitely from
> loop distribution for example).
Calling simple_iv_with_niters/simple_iv early may break the patch,
because only inside number_of_iterations_exit_assumptions, the flag
is disabled.

>
> What I'm trying to see is whether we can do some more concious
> setup of control IV computation and estimate computation.  While
> your patch produces the desired result it is far from obvious
> why exactly it does this since it also does it in a "midlevel"
> place (of course my attempts to do it in a more obvious position
> failed).
>
> But first of all yes, we should disallow / early out on recursions
> via public APIs like estimate_numbers_of_iterations (already done)
> or number_of_latch_executions (missing) or 
> number_of_iterations_exit[_assumptions] (very difficult there).

I'm wondering if we can set loop->nb_iterations=chrec_dont_know
or chrec_known in number_of_iterations_exit_assumption at the
begining, and use it as a guard to avoid recursions on them.

>
> IMHO that we lazily compute estimate_numbers_of_iterations and that
> computes niter for each exit of a loop is a misdesign - the estimate
> should be computed from the toplevel, and maybe independently for
> each exit?  I think that Honza changed it this way to make sure the
> estimates are always available when queried but I may mis-remember.
>
> With your patch, ontop of that limiting recursion of
> number_of_latch_executions doesn't break the positive effect
> at least.
>
> One unwanted side-effect of your patch might be that the
> computed estimate is now recorded w/o infer_loop_bounds_from_undefined
> which means it could be worse (and we won't re-compute it).
Yes, estimate was computed but infer_loop_bounds_from_undefined was
not called, and it will never be called before estimate is reset.

>
> All in all it is somewhat of a mess and I'm not convinced your
> patch is an improvement in this regard :/  It looks like there's
> a chicken and egg problem with using and recording (at least one)
> control IV and SCEV caching whilst searching for one.

Thanks for your comments, and welcome any sugguestions!

BR,
Jiufu

>
> Richard.
>
>
>> >
>> > I also tried
>> >
>> > diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
>> > index 935d2d4d8f3..d1787ba39b6 100644
>> > --- a/gcc/tree-ssa-loop-ivopts.c
>> > +++ b/gcc/tree-ssa-loop-ivopts.c
>> > @@ -8093,6 +8093,8 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, 
>> > class loop *loop,
>> >        fprintf (dump_file, "\n");
>> >      }
>> >  
>> > +  estimate_numbers_of_iterations (loop);
>> > +
>> >    body = get_loop_body (loop);
>> >    data->body_includes_call = loop_body_includes_call (body, 
>> > loop->num_nodes);
>> >    renumber_gimple_stmt_uids_in_blocks (body, loop->num_nodes);
>> >
>> > to get into the cycles from the "correct" entry but that does
>> > not help either.  Nor does
>> >
>> > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
>> > index b767056aeb0..f058be04836 100644
>> > --- a/gcc/tree-ssa-loop-niter.c
>> > +++ b/gcc/tree-ssa-loop-niter.c
>> > @@ -2534,6 +2534,14 @@ number_of_iterations_exit_assumptions (class loop 
>> > *loop, edge exit,
>> >        && !POINTER_TYPE_P (type))
>> >      return false;
>> >  
>> > +  if (loop->estimate_state == EST_NOT_COMPUTED)
>> > +    {
>> > +      bool saved = flag_aggressive_loop_optimizations;
>> > +      flag_aggressive_loop_optimizations = false;
>> > +      estimate_numbers_of_iterations (loop);
>> > +      flag_aggressive_loop_optimizations = saved;
>> > +    }
>> > +
>> >    tree iv0_niters = NULL_TREE;
>> >    if (!simple_iv_with_niters (loop, loop_containing_stmt (stmt),
>> >                               op0, &iv0, safe ? &iv0_niters : NULL, 
>> > false))
>> >
>> > or
>> >
>> > diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
>> > index 61d72c278a1..d1af89eb459 100644
>> > --- a/gcc/tree-scalar-evolution.c
>> > +++ b/gcc/tree-scalar-evolution.c
>> > @@ -518,7 +518,8 @@ set_scalar_evolution (basic_block instantiated_below, 
>> > tree scalar, tree chrec)
>> >         nb_set_scev++;
>> >      }
>> >  
>> > -  *scalar_info = chrec;
>> > +  if (*scalar_info == chrec_not_analyzed_yet)
>> > +    *scalar_info = chrec;
>> >  }
>> >  
>> >  /* Retrieve the chrec associated to SCALAR instantiated below
>> >
>> > That said, having the cycles is bad, we should definitively break
>> > them (if only for compile-time reasons).  But I don't really
>> > understand how your patch helps and my attempts do not which
>> > means I am missing a critical piece of understanding ... :/
>> 
>> This patch disables flag_aggressive_loop_optimizations before
>> analyze_scalar_evolution is called, then lv_10's scev is not
>> computed during this call cycle.  lv_10's scev is calculated
>> when it other passes (e.g. ivopt) request, at that time i_15
>> has 'final' scev.
>> 
>> I had also tried to disable recursive from analyze_scalar_evolution
>> on the same ssa name(i_15), and directly get the final result.  But
>> I'm not finding a good way yet.
>> 
>> Again thanks for your suggestions!
>> 
>> Thanks!
>> Jiufu
>> 
>> >
>> > Thanks,
>> > Richard.
>> >
>> >> Thanks again.
>> >> 
>> >> BR,
>> >> Jiufu
>> >> 
>> >> > to SCEV and thus may recurse again - to me it would be more
>> >> > logical to try avoid recursing in number_of_latch_executions by
>> >> > setting ->nb_iterations to something early, maybe chrec_dont_know,
>> >> > to signal we're using something we're just trying to compute.
>> >> > 
>> >> > Richard.
>> >> > 
>> >> >> BR,
>> >> >> Jiufu
>> >> >> 
>> >> >> gcc/ChangeLog:
>> >> >> 
>> >> >>  * tree-ssa-loop-niter.c (number_of_iterations_exit_assumptions):
>> >> >>  Disable/restore flag_aggressive_loop_optimizations.
>> >> >> 
>> >> >> gcc/testsuite/ChangeLog:
>> >> >> 
>> >> >>  * gcc.dg/tree-ssa/scev-16.c: New test.
>> >> >> 
>> >> >> ---
>> >> >>  gcc/tree-ssa-loop-niter.c               | 23 +++++++++++++++++++----
>> >> >>  gcc/testsuite/gcc.dg/tree-ssa/scev-16.c | 20 ++++++++++++++++++++
>> >> >>  2 files changed, 39 insertions(+), 4 deletions(-)
>> >> >>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/scev-16.c
>> >> >> 
>> >> >> diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
>> >> >> index 06954e437f5..51bb501019e 100644
>> >> >> --- a/gcc/tree-ssa-loop-niter.c
>> >> >> +++ b/gcc/tree-ssa-loop-niter.c
>> >> >> @@ -2534,18 +2534,31 @@ number_of_iterations_exit_assumptions (class 
>> >> >> loop
>> >> >> *loop, edge exit,
>> >> >>        && !POINTER_TYPE_P (type))
>> >> >>      return false;
>> >> >> 
>> >> >> +  /* Before niter is calculated, avoid to analyze interim state. */
>> >> >> +  int old_aggressive_loop_optimizations =
>> >> >> flag_aggressive_loop_optimizations;
>> >> >> +  flag_aggressive_loop_optimizations = 0;
>> >> >> +
>> >> >>    tree iv0_niters = NULL_TREE;
>> >> >>    if (!simple_iv_with_niters (loop, loop_containing_stmt (stmt),
>> >> >>                              op0, &iv0, safe ? &iv0_niters : NULL, 
>> >> >> false))
>> >> >> -    return number_of_iterations_popcount (loop, exit, code, niter);
>> >> >> +    {
>> >> >> +      bool res = number_of_iterations_popcount (loop, exit, code, 
>> >> >> niter);
>> >> >> +      flag_aggressive_loop_optimizations =
>> >> >> old_aggressive_loop_optimizations;
>> >> >> +      return res;
>> >> >> +    }
>> >> >>    tree iv1_niters = NULL_TREE;
>> >> >>    if (!simple_iv_with_niters (loop, loop_containing_stmt (stmt),
>> >> >>                              op1, &iv1, safe ? &iv1_niters : NULL, 
>> >> >> false))
>> >> >> -    return false;
>> >> >> +    {
>> >> >> +      flag_aggressive_loop_optimizations =
>> >> >> old_aggressive_loop_optimizations;
>> >> >> +      return false;
>> >> >> +    }
>> >> >>    /* Give up on complicated case.  */
>> >> >>    if (iv0_niters && iv1_niters)
>> >> >> -    return false;
>> >> >> -
>> >> >> +    {
>> >> >> +      flag_aggressive_loop_optimizations =
>> >> >> old_aggressive_loop_optimizations;
>> >> >> +      return false;
>> >> >> +    }
>> >> >>    /* We don't want to see undefined signed overflow warnings while
>> >> >>       computing the number of iterations.  */
>> >> >>    fold_defer_overflow_warnings ();
>> >> >> @@ -2565,6 +2578,7 @@ number_of_iterations_exit_assumptions (class loop
>> >> >> *loop, edge exit,
>> >> >>                                  only_exit_p, safe))
>> >> >>      {
>> >> >>        fold_undefer_and_ignore_overflow_warnings ();
>> >> >> +      flag_aggressive_loop_optimizations =
>> >> >> old_aggressive_loop_optimizations;
>> >> >>        return false;
>> >> >>      }
>> >> >> 
>> >> >> @@ -2608,6 +2622,7 @@ number_of_iterations_exit_assumptions (class loop
>> >> >> *loop, edge exit,
>> >> >>              niter->may_be_zero);
>> >> >> 
>> >> >>    fold_undefer_and_ignore_overflow_warnings ();
>> >> >> +  flag_aggressive_loop_optimizations = 
>> >> >> old_aggressive_loop_optimizations;
>> >> >> 
>> >> >>    /* If NITER has simplified into a constant, update MAX.  */
>> >> >>    if (TREE_CODE (niter->niter) == INTEGER_CST)
>> >> >> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-16.c
>> >> >> b/gcc/testsuite/gcc.dg/tree-ssa/scev-16.c
>> >> >> new file mode 100644
>> >> >> index 00000000000..708ffab88ca
>> >> >> --- /dev/null
>> >> >> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-16.c
>> >> >> @@ -0,0 +1,20 @@
>> >> >> +/* { dg-do compile } */
>> >> >> +/* { dg-options "-O2 -fdump-tree-ivopts-scev" } */
>> >> >> +
>> >> >> +/* Expect scalar_evolution = {(int) start_7(D), +, 1}_1), instead
>> >> >> +   (int) (short int) {(unsigned short) start_7(D), +, 1}_1 */
>> >> >> +
>> >> >> +int arr[1000];
>> >> >> +
>> >> >> +void
>> >> >> +s2i (short start, short end)
>> >> >> +{
>> >> >> +  int res = 0;
>> >> >> +  for (short i = start; i < end; i++)
>> >> >> +    {
>> >> >> +      int lv = i;
>> >> >> +      arr[lv] += lv;
>> >> >> +    }
>> >> >> +}
>> >> >> +
>> >> >> +/* { dg-final { scan-tree-dump-times "scalar_evolution = \{\\(int\\)
>> >> >> start_\[0-9\]+\\(D\\), \\+, 1\}_1" 1 "ivopts" } } */
>> >> >> 
>> >> 
>> >> 
>> 

Reply via email to