On Tue, May 21, 2019 at 12:12 PM Richard Biener
<richard.guent...@gmail.com> wrote:
>
> On Mon, May 20, 2019 at 4:51 PM Feng Xue OS <f...@os.amperecomputing.com> 
> wrote:
> >
> > > I don't see how it is safe in a late pass when it is not safe in an
> >
> > > earlier one.  Optimization is imperfect - we could fail to remove
> > > an "obvious" never taken exit and still have a loop that appears to be
> > > finite according to our definition.
> >
> > Yes. it is. This is somewhat similar to strict-alias option/loop dep pragma.
> > Compiler tries to do something based on hint you tell it, but does not 
> > ensure correctness.
> >
> > > The only way
> > > to define it would be if there was, at any point, an exit from the
> > > loop (and there it _may_ be exclude EH edges) then
> > > the loop is assumed to be finite.
> >
> > No catch your point. If we treat an infinite loop as finite, it's bad 
> > because the loop might be removed.
> >
> > Suppose we have a function:
> >
> >     void foo(int bound)
> >      { for (int i = 0; i <= bound; i++); }
> >
> >  In an early CD-DCE pass, "bound" is represented as a variable, and loop 
> > has a exit, so it is assumed to finite, and is removed.
> >
> > But in a late pass, this function is inlined into another one, and "bound" 
> > has value of INT_MAX, this loop is infinite, and here we can know it should 
> > not be removed.
>
> But if "bound" is always INT_MAX but that's not visible to the
> compiler we will still remove the
> loop so I see no difference with removing it always.
>
> > This is why I suggest doing the optimization as late as possible.
>
> But this will defeat the purpose of allowing followup optimizations.
>
> IMHO the only "sensible" thing is to do
>
> Index: gcc/tree-ssa-dce.c
> ===================================================================
> --- gcc/tree-ssa-dce.c  (revision 271415)
> +++ gcc/tree-ssa-dce.c  (working copy)
> @@ -417,7 +417,7 @@ find_obviously_necessary_stmts (bool agg
>           }
>
>        FOR_EACH_LOOP (loop, 0)
> -       if (!finite_loop_p (loop))
> +       if (!loop_has_exit_edges (loop))
>           {
>             if (dump_file)
>               fprintf (dump_file, "cannot prove finiteness of loop
> %i\n", loop->num);

Bootstrapped / tested on x86_64-unknown-linux-gnu.  Fallout:

FAIL: gcc.dg/loop-unswitch-1.c scan-tree-dump unswitch ";; Unswitching loop"
FAIL: gcc.dg/predict-9.c scan-tree-dump-times profile_estimate "first
match heuristics: 2.20%" 3
FAIL: gcc.dg/predict-9.c scan-tree-dump-times profile_estimate "first
match heuristics: 5.50%" 1
FAIL: gcc.dg/uninit-28-gimple.c  (test for bogus messages, line 9)
FAIL: gcc.dg/graphite/scop-19.c scan-tree-dump-times graphite "number
of SCoPs: 0" 2
...
UNRESOLVED: gcc.dg/tree-ssa/20040211-1.c scan-tree-dump cddce2 "if "
FAIL: gcc.dg/tree-ssa/loop-10.c scan-tree-dump-times optimized "if " 3
FAIL: gcc.dg/tree-ssa/pr84648.c scan-tree-dump-times cddce1 "Found
loop 1 to be finite: upper bound found" 1
FAIL: gcc.dg/tree-ssa/split-path-6.c scan-tree-dump-times split-paths
"Duplicating join block" 3
FAIL: gcc.dg/tree-ssa/ssa-thread-12.c scan-tree-dump thread2 "FSM"
FAIL: gcc.dg/tree-ssa/ssa-thread-12.c scan-tree-dump thread3 "FSM"

I didn't look if the testcases are sensible for loop removal (or what
actually happens).

Richard.

> that also has the obvious advantage that we don't need to replace the loop
> with a trap() but have a place to forward control flow to.  The loop in the
> following testcase is then successfully removed:
>
> int main(int argc, char **argv)
> {
>   unsigned i = argc;
>   while (i+=2);
>   return 0;
> }
>
> Likewise is the loop
>
> void **q;
> int main(int argc, char **argv)
> {
>   void **p = q;
>   while (p = (void **)*p);
>   return 0;
> }
>
> (that's the pointer-chasing).  Not with -fnon-call-exceptions
> -fexceptions though.
>
> Richard.
>
> > Feng
> >

Reply via email to