On Tue, 15 May 2018, Richard Biener wrote:

> On Tue, 15 May 2018, Richard Biener wrote:
> 
> > On Tue, 15 May 2018, Richard Biener wrote:
> > 
> > > On Tue, 15 May 2018, Richard Biener wrote:
> > > 
> > > > On Mon, 14 May 2018, Kugan Vivekanandarajah wrote:
> > > > 
> > > > > Hi,
> > > > > 
> > > > > Attached patch handles PR63185 when we reach PHI with temp != NULLL.
> > > > > We could see the PHI and if there isn't any uses for PHI that is
> > > > > interesting, we could ignore that ?
> > > > > 
> > > > > Bootstrapped and regression tested on x86_64-linux-gnu.
> > > > > Is this OK?
> > > > 
> > > > No, as Jeff said we can't do it this way.
> > > > 
> > > > If we end up with multiple VDEFs in the walk of defvar immediate
> > > > uses we know we are dealing with a CFG fork.  We can't really
> > > > ignore any of the paths but we have to
> > > > 
> > > >  a) find the merge point (and the associated VDEF)
> > > >  b) verify for each each chain of VDEFs with associated VUSEs
> > > >     up to that merge VDEF that we have no uses of the to classify
> > > >     store and collect (partial) kills
> > > >  c) intersect kill info and continue walking from the merge point
> > > > 
> > > > in b) there's the optional possibility to find sinking opportunities
> > > > in case we have kills on some paths but uses on others.  This is why
> > > > DSE should be really merged with (store) sinking.
> > > > 
> > > > So if we want to enhance DSEs handling of branches then we need
> > > > to refactor the simple dse_classify_store function.  Let me take
> > > > an attempt at this today.
> > > 
> > > First (baby) step is the following - it arranges to collect the
> > > defs we need to continue walking from and implements trivial
> > > reduction by stopping at (full) kills.  This allows us to handle
> > > the new testcase (which was already handled in the very late DSE
> > > pass with the help of sinking the store).
> > > 
> > > I took the opportunity to kill the use_stmt parameter of
> > > dse_classify_store as the only user is only looking for whether
> > > the kills were all clobbers which I added a new parameter for.
> > > 
> > > I didn't adjust the byte-tracking case fully (I'm not fully understanding
> > > the code in the case of a use and I'm not sure whether it's worth
> > > doing the def reduction with byte-tracking).
> > > 
> > > Your testcase can be handled by reducing the PHI and the call def
> > > by seeing that the only use of a candidate def is another def
> > > we have already processed.  Not sure if worth special-casing though,
> > > I'd rather have a go at "recursing".  That will be the next
> > > patch.
> > > 
> > > Bootstrap & regtest running on x86_64-unknown-linux-gnu.
> > 
> > Applied.
> > 
> > Another intermediate one below, fixing the byte-tracking for
> > stmt with uses.  This also re-does the PHI handling by simply
> > avoiding recursion by means of a visited bitmap and stopping
> > at the DSE classify stmt when re-visiting it instead of failing.
> > This covers Pratamesh loop case for which I added ssa-dse-33.c.
> > For the do-while loop this still runs into the inability to
> > handle two defs to walk from.
> > 
> > Bootstrap & regtest running on x86_64-unknown-linux-gnu.
> 
> Ok, loop handling doesn't work in general since we run into the
> issue that SSA form across the backedge is not representing the
> same values.  Consider
> 
>  <bb 3>
>  # .MEM_22 = PHI <.MEM_12(D)(2), .MEM_13(4)>
>  # n_20 = PHI <0(2), n_7(4)>
>  # .MEM_13 = VDEF <.MEM_22>
>  bytes[n_20] = _4;
>  if (n_20 > 7)
>    goto <bb 5>;
> 
>  <bb 4>
>  n_7 = n_20 + 1;
>  # .MEM_15 = VDEF <.MEM_13>
>  bytes[n_20] = _5;
>  goto <bb 3>;
> 
> then when classifying the store in bb4, visiting the PHI node
> gets us to the store in bb3 which appears to be killing.
> 
>        if (gimple_code (temp) == GIMPLE_PHI)
> -       defvar = PHI_RESULT (temp);
> +       {
> +         /* If we visit this PHI by following a backedge then reset
> +            any info in ref that may refer to SSA names which we'd need
> +            to PHI translate.  */
> +         if (gimple_bb (temp) == gimple_bb (stmt)
> +             || dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt),
> +                                gimple_bb (temp)))
> +           /* ???  ref->ref may not refer to SSA names or it may only
> +              refer to SSA names that are invariant with respect to the
> +              loop represented by this PHI node.  */
> +           ref->ref = NULL_TREE;
> +         defvar = PHI_RESULT (temp);
> +         bitmap_set_bit (visited, SSA_NAME_VERSION (defvar));
> +       }
> 
> should be a workable solution for that.  I'm checking that, but
> eventually you can think of other things that might prevent us from
> handling backedges.  Note the current code tries to allow
> looking across loops but not handle backedges of loops the
> original stmt belongs to.

Just to mention before I leave for the day I think I've identified
a latent issue where I just fail to produce a testcase right now
which is that non-return exits from a function are not reliably
visited given they do not all have virtual operands, like
for example resx.  Thus consider

void foo (int *p, int x)
{
  *p = 0;
  if (x)
    resx;
  *p = 1;
  return;
}

where we will never visit any stmts on the resx path and thus think
the *p = 0 store is dead (all with current trunk of course).

Will continue to dig tomorrow.

Richard.

> Richard.
> 
> 
> > Richard.
> > 
> > 2018-05-15  Richard Biener  <rguent...@suse.de>
> > 
> >     * tree-ssa-dse.c (dse_classify_store): Track cycles via a visited
> >     bitmap of PHI defs and simplify handling of in-loop and across
> >     loop dead stores.  Handle byte-tracking with multiple defs.
> > 
> >     * gcc.dg/tree-ssa/ssa-dse-32.c: New testcase.
> >     * gcc.dg/tree-ssa/ssa-dse-33.c: Likewise.
> > 
> > commit 7129756be201db1bd90e4191ed32084cbb22130d
> > Author: Richard Guenther <rguent...@suse.de>
> > Date:   Tue May 15 14:03:32 2018 +0200
> > 
> >     dse#2
> > 
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-32.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-32.c
> > new file mode 100644
> > index 00000000000..eea0d8d5cf0
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-32.c
> > @@ -0,0 +1,13 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O -fdump-tree-dse1-details" } */
> > +
> > +void f(int n)
> > +{
> > +  char *p = __builtin_malloc (1);
> > +  int i;
> > +  do
> > +    *p = 0;
> > +  while (++i < n);
> > +}
> > +
> > +/* { dg-final { scan-tree-dump-times "Deleted dead store" 1 "dse1" } } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-33.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-33.c
> > new file mode 100644
> > index 00000000000..02e3e6a582c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-33.c
> > @@ -0,0 +1,22 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O -fdump-tree-dse1-details" } */
> > +
> > +void f(char *p, int n)
> > +{
> > +  for (int i = 0; i < n; ++i)
> > +    *p = 0;  /* Removed by DSE.  */
> > +  *p = 1;
> > +}
> > +
> > +void g(char *p, int n)
> > +{
> > +  int i = 0;
> > +  do
> > +    *p = 0;  /* DSE cannot yet handle this case.  */
> > +  while (++i < n);
> > +  *p = 1;
> > +}
> > +
> > +
> > +/* { dg-final { scan-tree-dump-times "Deleted dead store" 2 "dse1" { xfail 
> > *-*-* } } } */
> > +/* { dg-final { scan-tree-dump-times "Deleted dead store" 1 "dse1" } } */
> > diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
> > index 126592a1d13..8836e84dd63 100644
> > --- a/gcc/tree-ssa-dse.c
> > +++ b/gcc/tree-ssa-dse.c
> > @@ -528,6 +528,7 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
> >  {
> >    gimple *temp;
> >    unsigned cnt = 0;
> > +  auto_bitmap visited;
> >  
> >    if (by_clobber_p)
> >      *by_clobber_p = true;
> > @@ -539,7 +540,7 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
> >    temp = stmt;
> >    do
> >      {
> > -      gimple *use_stmt, *defvar_def;
> > +      gimple *use_stmt;
> >        imm_use_iterator ui;
> >        bool fail = false;
> >        tree defvar;
> > @@ -550,47 +551,31 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
> >     return DSE_STORE_LIVE;
> >  
> >        if (gimple_code (temp) == GIMPLE_PHI)
> > -   defvar = PHI_RESULT (temp);
> > +   {
> > +     defvar = PHI_RESULT (temp);
> > +     bitmap_set_bit (visited, SSA_NAME_VERSION (defvar));
> > +   }
> >        else
> >     defvar = gimple_vdef (temp);
> > -      defvar_def = temp;
> >        auto_vec<gimple *, 10> defs;
> >        FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
> >     {
> >       cnt++;
> >  
> > -     /* If we ever reach our DSE candidate stmt again fail.  We
> > -        cannot handle dead stores in loops.  */
> > +     /* We have visited ourselves already so ignore STMT for the
> > +        purpose of chaining.  */
> >       if (use_stmt == stmt)
> > -       {
> > -         fail = true;
> > -         BREAK_FROM_IMM_USE_STMT (ui);
> > -       }
> > +       ;
> >       /* In simple cases we can look through PHI nodes, but we
> >          have to be careful with loops and with memory references
> >          containing operands that are also operands of PHI nodes.
> >          See gcc.c-torture/execute/20051110-*.c.  */
> >       else if (gimple_code (use_stmt) == GIMPLE_PHI)
> >         {
> > -         /* Make sure we are not in a loop latch block.  */
> > -         if (gimple_bb (stmt) == gimple_bb (use_stmt)
> > -             || dominated_by_p (CDI_DOMINATORS,
> > -                                gimple_bb (stmt), gimple_bb (use_stmt))
> > -             /* We can look through PHIs to regions post-dominating
> > -                the DSE candidate stmt.  */
> > -             || !dominated_by_p (CDI_POST_DOMINATORS,
> > -                                 gimple_bb (stmt), gimple_bb (use_stmt)))
> > -           {
> > -             fail = true;
> > -             BREAK_FROM_IMM_USE_STMT (ui);
> > -           }
> > -         /* Do not consider the PHI as use if it dominates the
> > -            stmt defining the virtual operand we are processing,
> > -            we have processed it already in this case.  */
> > -         if (gimple_bb (defvar_def) != gimple_bb (use_stmt)
> > -             && !dominated_by_p (CDI_DOMINATORS,
> > -                                 gimple_bb (defvar_def),
> > -                                 gimple_bb (use_stmt)))
> > +         /* If we already visited this PHI ignore it for further
> > +            processing.  */
> > +         if (!bitmap_bit_p (visited,
> > +                            SSA_NAME_VERSION (PHI_RESULT (use_stmt))))
> >             defs.safe_push (use_stmt);
> >         }
> >       /* If the statement is a use the store is not dead.  */
> > @@ -600,25 +585,20 @@ dse_classify_store (ao_ref *ref, gimple *stmt,
> >              structure for USE_STMT and in doing so we find that the
> >              references hit non-live bytes and thus can be ignored.  */
> >           if (byte_tracking_enabled
> > -             && (!gimple_vdef (use_stmt) || defs.is_empty ()))
> > +             && is_gimple_assign (use_stmt))
> >             {
> > -             if (is_gimple_assign (use_stmt))
> > +             ao_ref use_ref;
> > +             ao_ref_init (&use_ref, gimple_assign_rhs1 (use_stmt));
> > +             if (valid_ao_ref_for_dse (&use_ref)
> > +                 && use_ref.base == ref->base
> > +                 && known_eq (use_ref.size, use_ref.max_size)
> > +                 && !live_bytes_read (use_ref, ref, live_bytes))
> >                 {
> > -                 /* Other cases were noted as non-aliasing by
> > -                    the call to ref_maybe_used_by_stmt_p.  */
> > -                 ao_ref use_ref;
> > -                 ao_ref_init (&use_ref, gimple_assign_rhs1 (use_stmt));
> > -                 if (valid_ao_ref_for_dse (&use_ref)
> > -                     && use_ref.base == ref->base
> > -                     && known_eq (use_ref.size, use_ref.max_size)
> > -                     && !live_bytes_read (use_ref, ref, live_bytes))
> > -                   {
> > -                     /* If this statement has a VDEF, then it is the
> > -                        first store we have seen, so walk through it.  */
> > -                     if (gimple_vdef (use_stmt))
> > -                       defs.safe_push (use_stmt);
> > -                     continue;
> > -                   }
> > +                 /* If this is a store, remember it as we possibly
> > +                    need to walk the defs uses.  */
> > +                 if (gimple_vdef (use_stmt))
> > +                   defs.safe_push (use_stmt);
> > +                 continue;
> >                 }
> >             }
> >  
> > 
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to