On Tue, Apr 1, 2025 at 12:54 AM Richard Biener
<[email protected]> wrote:
>
> On Tue, Apr 1, 2025 at 6:10 AM Andrew Pinski <[email protected]> wrote:
> >
> > phiprop can sometimes prop loads back into loops
> > and in some cases cause wrong code when the load
> > was from a weak symbol as now it becomes an unconditional
> > load before the loop.
> >
> > Bootstrapped and tested on x86_64-linux-gnu with no regressions.
> >
> >         PR tree-optimization/116835
> >
> > gcc/ChangeLog:
> >
> >         * tree-ssa-phiprop.cc (propagate_with_phi): Check
> >         the use is at the same or deeper loop depth than
> >         the phi node.
> >         (pass_phiprop::execute): Initialize loops.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * gcc.dg/torture/pr116835.c: New test.
> >
> > Signed-off-by: Andrew Pinski <[email protected]>
> > ---
> >  gcc/testsuite/gcc.dg/torture/pr116835.c | 33 +++++++++++++++++++++++++
> >  gcc/tree-ssa-phiprop.cc                 | 14 ++++++++++-
> >  2 files changed, 46 insertions(+), 1 deletion(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/torture/pr116835.c
> >
> > diff --git a/gcc/testsuite/gcc.dg/torture/pr116835.c 
> > b/gcc/testsuite/gcc.dg/torture/pr116835.c
> > new file mode 100644
> > index 00000000000..31d3b59d945
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/torture/pr116835.c
> > @@ -0,0 +1,33 @@
> > +/* { dg-do run { target { weak_undefined } } } */
> > +/* { dg-add-options weak_undefined } */
> > +
> > +/* PR tree-optimization/116835 */
> > +/* phiprop would prop into the loop the load of b
> > +   and also prop the load of a before the loop.
> > +   Which is incorrect as a is a weak symbol.  */
> > +
> > +struct s1
> > +{
> > +  int t;
> > +  int t1;
> > +};
> > +typedef struct s1 type;
> > +extern type a __attribute__((weak));
> > +int t;
> > +type b;
> > +type bar (int c) __attribute__((noipa, noinline));
> > +type
> > +bar (int c)
> > +{
> > +  t = 1;
> > +  type *p = &a;
> > +  for (int j = 0; j < c; ++j)
> > +    p = &b;
> > +  return *p;
> > +}
> > +
> > +int main(void)
> > +{
> > + if (bar(&a == nullptr).t)
> > +   __builtin_abort();
> > +}
> > diff --git a/gcc/tree-ssa-phiprop.cc b/gcc/tree-ssa-phiprop.cc
> > index a2e1fb16a30..c5fe231d3e9 100644
> > --- a/gcc/tree-ssa-phiprop.cc
> > +++ b/gcc/tree-ssa-phiprop.cc
> > @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "tree-ssa-loop.h"
> >  #include "tree-cfg.h"
> >  #include "tree-ssa-dce.h"
> > +#include "cfgloop.h"
> >
> >  /* This pass propagates indirect loads through the PHI node for its
> >     address to make the load source possibly non-addressable and to
> > @@ -348,11 +349,17 @@ propagate_with_phi (basic_block bb, gphi *phi, struct 
> > phiprop_d *phivn,
> >         calculate_dominance_info (CDI_POST_DOMINATORS);
> >
> >        /* Only replace loads in blocks that post-dominate the PHI node.  
> > That
> > -         makes sure we don't end up speculating loads.  */
> > +        makes sure we don't end up speculating loads.  */
> >        if (!dominated_by_p (CDI_POST_DOMINATORS,
> >                            bb, gimple_bb (use_stmt)))
> >         continue;
>
> I think the testcase shows the above test is not sufficient to avoid doing
> invalid speculation.  We need to verify the assumption that the
> PHI is dereferenced each time it is "executed".
> With cycles SSA form and post-dominance are not helpful here.
>
> I think we have to amend the post-dominance check to deal with
> SSA cycles, but your check does not look fully correct (and its
> comment is misleading).
> We need to constrain the load to be in the same or a subloop (use
> flow_loop_nested_p,
> not loop depth) or in the same BB when either the load or the PHI is
> in an irreducible region.
>
> >
> > +      /* Only replace loads in blocks are in the same loop
> > +        are inside an deeper loop.  This is to make sure not
> > +        to prop back into the loop.  */
> > +      if (bb_loop_depth (gimple_bb (use_stmt)) < bb_loop_depth (bb))
> > +       continue;
> > +
>
> So something like
>
>    /* Amend the post-dominance check for SSA cycles, we need to
>       make sure each PHI result value is dereferenced.  */
>    if (!(gimple_bb (use_stmt) == bb
>          || (!(bb->flags & BB_IRREDUCIBLE_LOOP)
>             && !(gimple_bb (use_stmt)->flags & BB_IRREDUCIBLE_LOOP)
>             && (bb->loop_father == gimple_bb (use_stmt)->loop_father
>                   || flow_loop_nested_p (bb->loop_father, gimple_bb
> (use_stmt)->loop_father)))))
>     continue;

That works except now phiprop only does the following partly:
```
int a;

int b;
int bar (int c) __attribute__((noipa, noinline));
int
bar (int c)
{
  int *p = &a;
  for (int j = 0; j < *p; ++j)
  {
    p = &b;
  }
  return *p;
}
```
So maybe the analysis part needs to be separated from the insert part ...
Let me try that.

Thanks,
Andrew

>
> >        /* Check whether this is a load of *ptr.  */
> >        if (!(is_gimple_assign (use_stmt)
> >             && gimple_assign_rhs_code (use_stmt) == MEM_REF
> > @@ -520,6 +527,10 @@ pass_phiprop::execute (function *fun)
> >    size_t n;
> >    auto_bitmap dce_ssa_names;
> >
> > +  /* Find the loops, so that we can prevent moving loads in
> > +     them.  */
> > +  loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
> > +
> >    calculate_dominance_info (CDI_DOMINATORS);
> >
> >    n = num_ssa_names;
> > @@ -548,6 +559,7 @@ pass_phiprop::execute (function *fun)
> >    free (phivn);
> >
> >    free_dominance_info (CDI_POST_DOMINATORS);
> > +  loop_optimizer_finalize ();
> >
> >    return did_something ? TODO_update_ssa_only_virtuals : 0;
> >  }
> > --
> > 2.43.0
> >

Reply via email to