On Mon, Jan 20, 2025 at 6:01 AM Andrew Pinski <quic_apin...@quicinc.com> wrote:
>
> While fixing PR target/117665, I had noticed that fold_marked_statements
> would not purge the abnormal edges which could not be taken any more due
> to folding a call (devirtualization or simplification of a [target] builtin).
> Devirutalization could also cause a call that used to be able to have an
> abornal edge become one not needing one too so this was needed for GCC 15.
>
> Bootstrapped and tested on x86_64-linux-gnu

OK.

Thanks,
Richard.

>         PR tree-optimization/118077
>         PR tree-optimization/117668
>
> gcc/ChangeLog:
>
>         * tree-inline.cc (fold_marked_statements): Purge abnormal edges
>         as needed.
>
> gcc/testsuite/ChangeLog:
>
>         * g++.dg/opt/devirt6.C: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
>  gcc/testsuite/g++.dg/opt/devirt6.C | 23 +++++++++++++++++++++++
>  gcc/tree-inline.cc                 | 22 ++++++++++++++++++++--
>  2 files changed, 43 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/opt/devirt6.C
>
> diff --git a/gcc/testsuite/g++.dg/opt/devirt6.C 
> b/gcc/testsuite/g++.dg/opt/devirt6.C
> new file mode 100644
> index 00000000000..5caf9da7891
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/opt/devirt6.C
> @@ -0,0 +1,23 @@
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-O3" }
> +
> +// PR tree-optimization/118077
> +
> +// This used to ICE because the devirtualization call
> +// of bb inside f1 (which was inlined into f2) became
> +// a direct call to c1::bb but the abnormal edge
> +// was not removed even though bb was const.
> +
> +int f() __attribute__((returns_twice));
> +struct c1 {
> +  virtual int bb(void) const { return 0; }
> +  bool f1(int a)
> +  {
> +    return a && !bb();
> +  }
> +};
> +struct c2 final : c1 { void f2(int); };
> +void c2::f2(int a) {
> +  if (!f1(a))
> +    f();
> +}
> diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc
> index 11278e5c483..5b3539009a3 100644
> --- a/gcc/tree-inline.cc
> +++ b/gcc/tree-inline.cc
> @@ -5430,6 +5430,7 @@ static void
>  fold_marked_statements (int first, hash_set<gimple *> *statements)
>  {
>    auto_bitmap to_purge;
> +  auto_bitmap to_purge_abnormal;
>
>    auto_vec<edge, 20> stack (n_basic_blocks_for_fn (cfun) + 2);
>    auto_sbitmap visited (last_basic_block_for_fn (cfun));
> @@ -5456,8 +5457,16 @@ fold_marked_statements (int first, hash_set<gimple *> 
> *statements)
>               continue;
>
>             gimple *old_stmt = gsi_stmt (gsi);
> -           tree old_decl = (is_gimple_call (old_stmt)
> -                            ? gimple_call_fndecl (old_stmt) : 0);
> +           bool can_make_abnormal_goto = false;
> +           tree old_decl = NULL_TREE;
> +
> +           if (is_gimple_call (old_stmt))
> +             {
> +               old_decl = gimple_call_fndecl (old_stmt);
> +               if (stmt_can_make_abnormal_goto (old_stmt))
> +                 can_make_abnormal_goto = true;
> +             }
> +
>             if (old_decl && fndecl_built_in_p (old_decl))
>               {
>                 /* Folding builtins can create multiple instructions,
> @@ -5473,6 +5482,8 @@ fold_marked_statements (int first, hash_set<gimple *> 
> *statements)
>                       {
>                         cgraph_update_edges_for_call_stmt (old_stmt,
>                                                            old_decl, NULL);
> +                       if (can_make_abnormal_goto)
> +                         bitmap_set_bit (to_purge_abnormal, dest->index);
>                         break;
>                       }
>                     if (gsi_end_p (i2))
> @@ -5501,6 +5512,9 @@ fold_marked_statements (int first, hash_set<gimple *> 
> *statements)
>                             if (maybe_clean_or_replace_eh_stmt (old_stmt,
>                                                                 new_stmt))
>                               bitmap_set_bit (to_purge, dest->index);
> +                           if (can_make_abnormal_goto
> +                               && !stmt_can_make_abnormal_goto (new_stmt))
> +                             bitmap_set_bit (to_purge_abnormal, dest->index);
>                             break;
>                           }
>                         gsi_next (&i2);
> @@ -5521,6 +5535,9 @@ fold_marked_statements (int first, hash_set<gimple *> 
> *statements)
>
>                 if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
>                   bitmap_set_bit (to_purge, dest->index);
> +               if (can_make_abnormal_goto
> +                   && !stmt_can_make_abnormal_goto (new_stmt))
> +                 bitmap_set_bit (to_purge_abnormal, dest->index);
>               }
>           }
>
> @@ -5542,6 +5559,7 @@ fold_marked_statements (int first, hash_set<gimple *> 
> *statements)
>      }
>
>    gimple_purge_all_dead_eh_edges (to_purge);
> +  gimple_purge_all_dead_abnormal_call_edges (to_purge_abnormal);
>  }
>
>  /* Expand calls to inline functions in the body of FN.  */
> --
> 2.43.0
>

Reply via email to