Hi Martin,

On Fri, 4 Aug 2023 at 18:26, Martin Jambor <mjam...@suse.cz> wrote:

> Hello,
>
> On Wed, Aug 02 2023, Richard Biener wrote:
> > On Mon, Jul 31, 2023 at 7:05 PM Martin Jambor <mjam...@suse.cz> wrote:
> >>
> >> Hi,
> >>
> >> when IPA-SRA detects whether a parameter passed by reference is
> >> written to, it does not special case CLOBBERs which means it often
> >> bails out unnecessarily, especially when dealing with C++ destructors.
> >> Fixed by the obvious continue in the two relevant loops.
> >>
> >> The (slightly) more complex testcases in the PR need surprisingly more
> >> effort but the simple one can be fixed now easily by this patch and I'll
> >> work on the others incrementally.
> >>
> >> Bootstrapped and currently undergoing testsuite run on x86_64-linux.  OK
> >> if it passes too?
> >
> > LGTM, btw - how are the clobbers handled during transform?
>
> it turns out your question is spot on.  I assumed that the mini-DCE that
> I implemented into IPA-SRA transform would delete but I had a closer
> look and it is not invoked on split parameters,only on removed ones.
> What was actually happening is that the parameter got remapped to a
> default definition of a replacement VAR_DECL and we were thus
> gimple-clobbering a pointer pointing to nowhere.  The clobber then got
> DSEd and so I originally did not notice looking at the optimized dump.
>
> Still that is of course not ideal and so I added a simple function
> removing clobbers when splitting.  I as considering adding that
> functionality to ipa_param_body_adjustments::mark_dead_statements but
> that would make the function harder to read without much gain.
>
> So thanks again for the remark.  The following passes bootstrap and
> testing on x86_64-linux.  I am running LTO bootstrap now.  OK if it
> passes?
>
> Martin
>
>
>
> When IPA-SRA detects whether a parameter passed by reference is
> written to, it does not special case CLOBBERs which means it often
> bails out unnecessarily, especially when dealing with C++ destructors.
> Fixed by the obvious continue in the two relevant loops and by adding
> a simple function that marks the clobbers in the transformation code
> as statements to be removed.
>
>
Not sure if you noticed: I updated bugzilla because the new test fails on
arm, and I attached  pr110378-1.C.083i.sra there, to help you debug.

Thanks,

Christophe

gcc/ChangeLog:
>
> 2023-08-04  Martin Jambor  <mjam...@suse.cz>
>
>         PR ipa/110378
>         * ipa-param-manipulation.h (class ipa_param_body_adjustments): New
>         members get_ddef_if_exists_and_is_used and mark_clobbers_dead.
>         * ipa-sra.cc (isra_track_scalar_value_uses): Ignore clobbers.
>         (ptr_parm_has_nonarg_uses): Likewise.
>         * ipa-param-manipulation.cc
>         (ipa_param_body_adjustments::get_ddef_if_exists_and_is_used): New.
>         (ipa_param_body_adjustments::mark_dead_statements): Move initial
>         checks to get_ddef_if_exists_and_is_used.
>         (ipa_param_body_adjustments::mark_clobbers_dead): New.
>         (ipa_param_body_adjustments::common_initialization): Call
>         mark_clobbers_dead when splitting.
>
> gcc/testsuite/ChangeLog:
>
> 2023-07-31  Martin Jambor  <mjam...@suse.cz>
>
>         PR ipa/110378
>         * g++.dg/ipa/pr110378-1.C: New test.
> ---
>  gcc/ipa-param-manipulation.cc         | 44 +++++++++++++++++++++---
>  gcc/ipa-param-manipulation.h          |  2 ++
>  gcc/ipa-sra.cc                        |  6 ++--
>  gcc/testsuite/g++.dg/ipa/pr110378-1.C | 48 +++++++++++++++++++++++++++
>  4 files changed, 94 insertions(+), 6 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/ipa/pr110378-1.C
>
> diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc
> index a286af7f5d9..4a185ddbdf4 100644
> --- a/gcc/ipa-param-manipulation.cc
> +++ b/gcc/ipa-param-manipulation.cc
> @@ -1072,6 +1072,20 @@ ipa_param_body_adjustments::carry_over_param (tree
> t)
>    return new_parm;
>  }
>
> +/* If DECL is a gimple register that has a default definition SSA name
> and that
> +   has some uses, return the default definition, otherwise return
> NULL_TREE.  */
> +
> +tree
> +ipa_param_body_adjustments::get_ddef_if_exists_and_is_used (tree decl)
> +{
> + if (!is_gimple_reg (decl))
> +    return NULL_TREE;
> +  tree ddef = ssa_default_def (m_id->src_cfun, decl);
> +  if (!ddef || has_zero_uses (ddef))
> +    return NULL_TREE;
> +  return ddef;
> +}
> +
>  /* Populate m_dead_stmts given that DEAD_PARAM is going to be removed
> without
>     any replacement or splitting.  REPL is the replacement VAR_SECL to
> base any
>     remaining uses of a removed parameter on.  Push all removed SSA names
> that
> @@ -1084,10 +1098,8 @@ ipa_param_body_adjustments::mark_dead_statements
> (tree dead_param,
>    /* Current IPA analyses which remove unused parameters never remove a
>       non-gimple register ones which have any use except as parameters in
> other
>       calls, so we can safely leve them as they are.  */
> -  if (!is_gimple_reg (dead_param))
> -    return;
> -  tree parm_ddef = ssa_default_def (m_id->src_cfun, dead_param);
> -  if (!parm_ddef || has_zero_uses (parm_ddef))
> +  tree parm_ddef = get_ddef_if_exists_and_is_used (dead_param);
> +  if (!parm_ddef)
>      return;
>
>    auto_vec<tree, 4> stack;
> @@ -1169,6 +1181,28 @@ ipa_param_body_adjustments::mark_dead_statements
> (tree dead_param,
>    m_dead_ssa_debug_equiv.put (parm_ddef, dp_ddecl);
>  }
>
> +/* Put all clobbers of of dereference of default definition of PARAM into
> +   m_dead_stmts.  */
> +
> +void
> +ipa_param_body_adjustments::mark_clobbers_dead (tree param)
> +{
> +  if (!is_gimple_reg (param))
> +    return;
> +  tree ddef = get_ddef_if_exists_and_is_used (param);
> +  if (!ddef)
> +    return;
> +
> + imm_use_iterator imm_iter;
> + use_operand_p use_p;
> + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ddef)
> +   {
> +     gimple *stmt = USE_STMT (use_p);
> +     if (gimple_clobber_p (stmt))
> +       m_dead_stmts.add (stmt);
> +   }
> +}
> +
>  /* Callback to walk_tree.  If REMAP is an SSA_NAME that is present in
> hash_map
>     passed in DATA, replace it with unshared version of what it was mapped
> to.
>     If an SSA argument would be remapped to NULL, the whole operation
> needs to
> @@ -1504,6 +1538,8 @@ ipa_param_body_adjustments::common_initialization
> (tree old_fndecl,
>                that will guide what not to copy to the new body.  */
>             if (!split[i])
>               mark_dead_statements (m_oparms[i], &ssas_to_process_debug);
> +           else
> +             mark_clobbers_dead (m_oparms[i]);
>             if (MAY_HAVE_DEBUG_STMTS
>                 && is_gimple_reg (m_oparms[i]))
>               m_reset_debug_decls.safe_push (m_oparms[i]);
> diff --git a/gcc/ipa-param-manipulation.h b/gcc/ipa-param-manipulation.h
> index 9798eedf0b6..d6a26e9ad36 100644
> --- a/gcc/ipa-param-manipulation.h
> +++ b/gcc/ipa-param-manipulation.h
> @@ -378,7 +378,9 @@ private:
>    bool modify_call_stmt (gcall **stmt_p, gimple *orig_stmt);
>    bool modify_cfun_body ();
>    void reset_debug_stmts ();
> +  tree get_ddef_if_exists_and_is_used (tree decl);
>    void mark_dead_statements (tree dead_param, vec<tree> *debugstack);
> +  void mark_clobbers_dead (tree dead_param);
>    bool prepare_debug_expressions (tree dead_ssa);
>
>    /* Declaration of the function that is being transformed.  */
> diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc
> index c35e03b7abd..edba364f56e 100644
> --- a/gcc/ipa-sra.cc
> +++ b/gcc/ipa-sra.cc
> @@ -898,7 +898,8 @@ isra_track_scalar_value_uses (function *fun,
> cgraph_node *node, tree name,
>
>    FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
>      {
> -      if (is_gimple_debug (stmt))
> +      if (is_gimple_debug (stmt)
> +         || gimple_clobber_p (stmt))
>         continue;
>
>        /* TODO: We could handle at least const builtin functions like
> arithmetic
> @@ -1056,7 +1057,8 @@ ptr_parm_has_nonarg_uses (cgraph_node *node,
> function *fun, tree parm,
>        unsigned uses_ok = 0;
>        use_operand_p use_p;
>
> -      if (is_gimple_debug (stmt))
> +      if (is_gimple_debug (stmt)
> +         || gimple_clobber_p (stmt))
>         continue;
>
>        if (gimple_assign_single_p (stmt))
> diff --git a/gcc/testsuite/g++.dg/ipa/pr110378-1.C
> b/gcc/testsuite/g++.dg/ipa/pr110378-1.C
> new file mode 100644
> index 00000000000..fda7699795a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/ipa/pr110378-1.C
> @@ -0,0 +1,48 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-ipa-sra -fdump-tree-optimized-slim"  } */
> +
> +/* Test that even though destructors end with clobbering all of *this, it
> +   should not prevent IPA-SRA.  */
> +
> +namespace {
> +
> +  class foo
> +  {
> +  public:
> +    short move_offset_of_a;
> +    int *a;
> +    foo(int c)
> +    {
> +      a = new int[c];
> +      a[0] = 4;
> +    }
> +    __attribute__((noinline)) ~foo();
> +    int f ()
> +    {
> +      return a[0] + 1;
> +    }
> +  };
> +
> +  volatile int v1 = 4;
> +
> +  __attribute__((noinline)) foo::~foo()
> +  {
> +    delete[] a;
> +    return;
> +  }
> +
> +
> +}
> +
> +volatile int v2 = 20;
> +
> +int test (void)
> +{
> +  foo shouldnotexist(v2);
> +  v2 = shouldnotexist.f();
> +  return 0;
> +}
> +
> +
> +/* { dg-final { scan-ipa-dump "Will split parameter 0" "sra"  } } */
> +/* { dg-final { scan-tree-dump-not "shouldnotexist" "optimized" } } */
> --
> 2.41.0
>
>

Reply via email to