On Tue, Feb 24, 2026 at 1:14 AM Richard Biener
<[email protected]> wrote:
>
> On Tue, Feb 24, 2026 at 6:40 AM Andrew Pinski
> <[email protected]> wrote:
> >
> > After outlinining the bbs for function splitting, we move the clobbers that 
> > were in the
> > last bb to be after the newly calling function.
> > This allows for stack location sharing and more when the non split out part 
> > is inlined
> > into another function.
> >
> > This also fixes some of the warnings about dangling-pointers because
> > the clobbers are now correctly handled while function splitting.
> > The testcases test for the cases where the dangling-pointers pointer
> > warnings would show up too.
> >
> > Note only end of storage clobbers in this case.
> >
> > Bootstrapped and tested on x86_64-linux-gnu.
> >
> >         PR tree-optimization/110091
> >
> > gcc/ChangeLog:
> >
> >         * ipa-split.cc (split_function): Find the bb
> >         which is used for return in the outlined function.
> >         Move the clobbers that are at the end of that bb
> >         to be after the new call.
> >
> > gcc/testsuite/ChangeLog:
> >
> >         * gcc.dg/tree-ssa/pr110091-3.c: New test.
> >         * gcc.dg/tree-ssa/pr110091-4.c: New test.
> >
> > Signed-off-by: Andrew Pinski <[email protected]>
> > ---
> >  gcc/ipa-split.cc                           | 48 ++++++++++++++++++++++
> >  gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c | 38 +++++++++++++++++
> >  gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c | 34 +++++++++++++++
> >  3 files changed, 120 insertions(+)
> >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c
> >  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c
> >
> > diff --git a/gcc/ipa-split.cc b/gcc/ipa-split.cc
> > index 3185830609d..aae4cf9e151 100644
> > --- a/gcc/ipa-split.cc
> > +++ b/gcc/ipa-split.cc
> > @@ -1470,8 +1470,31 @@ split_function (basic_block return_bb, class 
> > split_point *split_point,
> >        }
> >      else
> >        break;
> > +
> > +  /* Find the old return bb, it might contain some clobbers
> > +     which we want to copy back after the call.  */
> > +  basic_block old_return = nullptr;
> > +  if (split_part_return_p)
> > +    {
> > +      bool one_return_bb = true;
> > +      FOR_EACH_EDGE (e, ei, return_bb->preds)
> > +       if (bitmap_bit_p (split_point->split_bbs, e->src->index))
> > +         {
> > +           if (old_return != nullptr)
> > +             {
> > +               one_return_bb = false;
> > +               break;
> > +             }
> > +           old_return = e->src;
> > +         }
> > +      if (!one_return_bb)
> > +       old_return = nullptr;
> > +    }
> > +
> >    call_bb->count = split_point->count;
> >    e = split_block (split_point->entry_bb, last_stmt);
> > +  if (old_return == e->src)
> > +    old_return = e->dest;
> >    remove_edge (e);
> >
> >    /* Produce the call statement.  */
> > @@ -1713,6 +1736,31 @@ split_function (basic_block return_bb, class 
> > split_point *split_point,
> >           gsi_insert_after (&gsi, ret, GSI_NEW_STMT);
> >         }
> >      }
> > +
> > +  /* Move the clobbers from the old return bb to after the call. */
> > +  if (old_return)
> > +    {
> > +      gimple_stmt_iterator ngsi = gsi_last_bb (call_bb);
> > +      gsi_next (&ngsi);
> > +      for (gimple_stmt_iterator ogsi = gsi_last_bb (old_return);
> > +          !gsi_end_p (ogsi); )
> > +       {
> > +         gimple *stmt = *ogsi;
> > +         if (is_gimple_debug (stmt))
> > +           {
> > +             gsi_prev (&ogsi);
> > +             continue;
> > +           }
> > +         if (!gimple_clobber_p (stmt, CLOBBER_STORAGE_END))
> > +           break;
> > +         gimple_set_vuse (stmt, gimple_vop (cfun));
> > +         gimple_set_vdef (stmt, gimple_vop (cfun));
>
> I believe this will leak an unreleased SSA name.  You might want to use
> unlink_stmt_vdef before?

Actually unlink_stmt_vdef does not do that alone.
`release_ssa_name (gimple_vdef (stmt));` is also needed.
Since I only tested with unlink_stmt_vdef I will provide a new patch
for this later this afternoon.

Thanks,
Andrew

>
> > +         gimple_stmt_iterator nogsi = ogsi;
> > +         gsi_prev (&ogsi);
> > +         gsi_move_before (&nogsi, &ngsi, GSI_NEW_STMT);
> > +         update_stmt (stmt);
> > +       }
> > +    }
> >    free_dominance_info (CDI_DOMINATORS);
> >    free_dominance_info (CDI_POST_DOMINATORS);
> >    compute_fn_summary (node, true);
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c
> > new file mode 100644
> > index 00000000000..532b138655f
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110091-3.c
> > @@ -0,0 +1,38 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-Wall -O2 -fdump-tree-optimized 
> > -fdump-tree-sink1-details" } */
> > +/* PR tree-optimization/110091 */
> > +/* The clobbers are after the outlined code */
> > +
> > +struct tEntry
> > +{
> > +    int value;
> > +};
> > +int *out;
> > +
> > +extern int otherfunc(struct tEntry *);
> > +extern void anotherfunc(int val);
> > +
> > +void bar()
> > +{
> > +    struct tEntry entry1 = { 0 };
> > +    struct tEntry entry2 = { 0 };
> > +
> > +    if (otherfunc(&entry2) != 0)
> > +      return;
> > +    if (otherfunc(&entry1) != 0)
> > +      return;
> > +    if (out)
> > +     *out = entry2.value; /* { dg-bogus "dangling pointer to" } */
> > +    anotherfunc(5);
> > +}
> > +
> > +void foo()
> > +{
> > +    bar();
> > +}
> > +
> > +/* There should be 2 CLOBBERs, 1 for each: entry1 and entry2 as they have 
> > been "sinked".  */
> > +/* { dg-final { scan-tree-dump-times "CLOBBER\\\(eos\\\)" 2 "optimized" } 
> > } */
> > +/* { dg-final { scan-tree-dump "sinking common stores with same value to 
> > entry2" "sink1" } } */
> > +/* { dg-final { scan-tree-dump "sinking common stores with same value to 
> > entry1" "sink1" } } */
> > +
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c 
> > b/gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c
> > new file mode 100644
> > index 00000000000..e2ce19b0e83
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr110091-4.c
> > @@ -0,0 +1,34 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-Wall -O2 -fdump-tree-optimized 
> > -fdump-tree-sink1-details" } */
> > +/* PR tree-optimization/110091 */
> > +/* The clobbers are after the outlined code */
> > +
> > +struct tEntry
> > +{
> > +    int value;
> > +};
> > +int *out;
> > +
> > +extern int otherfunc(struct tEntry *);
> > +extern void anotherfunc(int val);
> > +
> > +void bar()
> > +{
> > +    struct tEntry entry = { 0 };
> > +
> > +    if (otherfunc(&entry) != 0)
> > +      return;
> > +    if (out)
> > +     *out = entry.value; /* { dg-bogus "dangling pointer to" } */
> > +    anotherfunc(5);
> > +}
> > +
> > +void foo()
> > +{
> > +    bar();
> > +}
> > +
> > +/* There should be 2 CLOBBERs, 1 for entry as they have been "sinked" and 
> > one for the inlined version.  */
> > +/* { dg-final { scan-tree-dump-times "CLOBBER\\\(eos\\\)" 2 "optimized" } 
> > } */
> > +/* { dg-final { scan-tree-dump "sinking common stores with same value to 
> > entry" "sink1" } } */
> > +
> > --
> > 2.43.0
> >

Reply via email to